当前位置: 首页 > news >正文

Python实现多线程PDF抓取与下载脚本

在我们日常工作和学习中,经常会遇到一个网站上有大量有价值的PDF文档,比如研究报告、产品手册或教程。如果一个一个手动去查找和下载,不仅费时费力,还容易遗漏。这个Python脚本就是专门为解决这个问题而生的。它能自动帮你遍历指定的网站,像一个小侦察兵一样把所有PDF文件的链接都找出来,然后利用多线程技术,同时开启多个下载任务,极大地提升批量下载的效率,帮你把繁琐的任务一键自动化。

在这里插入图片描述

下面是一个使用 Python 编写的脚本,可以从指定网站收集所有 PDF 文档链接,并通过多线程机制加速下载。

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import os
import threading
from queue import Queue
import time
import argparseclass PDFDownloader:def __init__(self, base_url, max_threads=5, download_dir="downloads"):self.base_url = base_urlself.max_threads = max_threadsself.download_dir = download_dirself.pdf_links = set()self.visited_links = set()self.lock = threading.Lock()self.queue = Queue()# 创建下载目录if not os.path.exists(download_dir):os.makedirs(download_dir)def is_valid_url(self, url):"""检查URL是否有效且属于同一域名"""parsed = urlparse(url)base_parsed = urlparse(self.base_url)return bool(parsed.netloc) and parsed.netloc == base_parsed.netlocdef get_absolute_url(self, url):"""将相对URL转换为绝对URL"""return urljoin(self.base_url, url)def extract_pdf_links(self, url):"""从页面提取所有PDF链接"""try:headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}response = requests.get(url, headers=headers, timeout=10)response.raise_for_status()soup = BeautifulSoup(response.content, 'html.parser')# 查找所有链接for link in soup.find_all('a', href=True):href = link['href']# 检查是否是PDF链接if href.lower().endswith('.pdf'):absolute_url = self.get_absolute_url(href)with self.lock:self.pdf_links.add(absolute_url)# 如果是普通链接,添加到队列中继续爬取else:absolute_url = self.get_absolute_url(href)if self.is_valid_url(absolute_url) and absolute_url not in self.visited_links:self.queue.put(absolute_url)self.visited_links.add(absolute_url)except Exception as e:print(f"Error processing {url}: {str(e)}")def download_pdf(self, url):"""下载PDF文件"""try:# 从URL提取文件名filename = os.path.basename(urlparse(url).path)if not filename:filename = f"document_{int(time.time())}.pdf"filepath = os.path.join(self.download_dir, filename)# 如果文件已存在,跳过下载if os.path.exists(filepath):print(f"File already exists: {filename}")returnprint(f"Downloading: {filename}")headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}response = requests.get(url, headers=headers, stream=True, timeout=30)response.raise_for_status()# 写入文件with open(filepath, 'wb') as f:for chunk in response.iter_content(chunk_size=8192):if chunk:f.write(chunk)print(f"Downloaded: {filename}")except Exception as e:print(f"Error downloading {url}: {str(e)}")def crawl_worker(self):"""爬取工作线程函数"""while True:url = self.queue.get()if url is None:breakself.extract_pdf_links(url)self.queue.task_done()def download_worker(self):"""下载工作线程函数"""while True:url = self.queue.get()if url is None:breakself.download_pdf(url)self.queue.task_done()def find_all_pdfs(self, max_pages=50):"""查找网站中的所有PDF链接"""print("Starting to crawl for PDF links...")# 初始URL加入队列self.queue.put(self.base_url)self.visited_links.add(self.base_url)# 创建爬取线程threads = []for _ in range(self.max_threads):t = threading.Thread(target=self.crawl_worker)t.start()threads.append(t)# 等待队列完成或达到最大页面数pages_processed = 0while not self.queue.empty() and pages_processed < max_pages:time.sleep(0.1)pages_processed += 1# 停止所有线程for _ in range(self.max_threads):self.queue.put(None)for t in threads:t.join()print(f"Found {len(self.pdf_links)} PDF documents")return self.pdf_linksdef download_all_pdfs(self):"""下载所有找到的PDF文件"""print("Starting download process...")# 将PDF链接加入队列for pdf_url in self.pdf_links:self.queue.put(pdf_url)# 创建下载线程threads = []for _ in range(self.max_threads):t = threading.Thread(target=self.download_worker)t.start()threads.append(t)# 等待所有下载完成self.queue.join()# 停止所有线程for _ in range(self.max_threads):self.queue.put(None)for t in threads:t.join()print("All downloads completed!")def main():parser = argparse.ArgumentParser(description='PDF Downloader from Website')parser.add_argument('url', help='Base URL to start crawling from')parser.add_argument('-t', '--threads', type=int, default=5, help='Number of threads (default: 5)')parser.add_argument('-d', '--directory', default='downloads', help='Download directory (default: downloads)')parser.add_argument('-m', '--max-pages', type=int, default=50, help='Maximum pages to crawl (default: 50)')args = parser.parse_args()# 创建下载器实例downloader = PDFDownloader(base_url=args.url,max_threads=args.threads,download_dir=args.directory)# 查找所有PDF链接pdf_links = downloader.find_all_pdfs(max_pages=args.max_pages)if pdf_links:# 下载所有PDF文件downloader.download_all_pdfs()else:print("No PDF documents found on the website.")if __name__ == "__main__":main()

使用说明

1、安装必要的依赖库:

pip install requests beautifulsoup4

2、运行脚本:

python pdf_downloader.py https://example.com -t 10 -d my_pdfs -m 100

参数说明:

  • url: 要爬取的网站URL(必需)
  • -t, --threads: 线程数量(默认:5)
  • -d, --directory: 下载目录(默认:downloads)
  • -m, --max-pages: 最大爬取页面数(默认:50)

功能特点

多线程爬取:使用多线程同时爬取多个页面,提高效率

多线程下载:使用多线程同时下载多个PDF文件,加速下载过程

相对URL处理:自动将相对URL转换为绝对URL

域名限制:只爬取同一域名下的链接

重复检测:避免重复下载同一文件

错误处理:完善的异常处理机制

进度显示:显示下载进度和状态

注意事项

1、请确保遵守目标网站的robots.txt规则

2、尊重网站服务器负载,适当调整线程数量

3、仅用于合法和道德的目的

4、某些网站可能有反爬虫机制,可能需要额外处理

这个脚本提供了基本功能,您可以根据需要进一步扩展和优化。

使用这个脚本非常简单,你只需要在命令行里指定要抓取的网址,它就会自动开始工作。所有下载好的PDF文件都会整齐地保存在你指定的文件夹中。不过需要注意的是,请务必尊重网站的规定,不要过度频繁请求而给对方服务器造成压力。合理设置线程数量,并确保你的使用方式是合法合规的。希望这个工具能成为你的得力助手,帮你从重复劳动中解放出来,高效地获取所需的资料。


文章转载自:

http://yBLdY2mY.cwcdr.cn
http://LKZ8nih0.cwcdr.cn
http://pSpm14q1.cwcdr.cn
http://0IdxBDvP.cwcdr.cn
http://hvzX1i6Q.cwcdr.cn
http://Yu5klHpm.cwcdr.cn
http://4Qyi9FhS.cwcdr.cn
http://z5I76Eba.cwcdr.cn
http://YwJ8X7XT.cwcdr.cn
http://XzqqBLNz.cwcdr.cn
http://i9ETiC62.cwcdr.cn
http://qCEkt8SM.cwcdr.cn
http://uo0zHMQU.cwcdr.cn
http://whFLARAk.cwcdr.cn
http://uljBLwxe.cwcdr.cn
http://JXN8f3Ic.cwcdr.cn
http://bLb0UIk9.cwcdr.cn
http://GFEetXb1.cwcdr.cn
http://Rvdop4UB.cwcdr.cn
http://giIW77ME.cwcdr.cn
http://ho8ylG4L.cwcdr.cn
http://N0YFZqxU.cwcdr.cn
http://2DWz3E6Z.cwcdr.cn
http://LxB4RQw1.cwcdr.cn
http://xkoFKiqI.cwcdr.cn
http://ds4tFW0l.cwcdr.cn
http://S8GpB0Bn.cwcdr.cn
http://jWsd45ia.cwcdr.cn
http://ulKFyZ1n.cwcdr.cn
http://sCpdBu5W.cwcdr.cn
http://www.dtcms.com/a/363355.html

相关文章:

  • 每秒扛住10万请求?RedissonRateLimiter 分布式限流器详解
  • 【机器学习深度学习】向量检索到重排序:RAG 系统中的优化实践
  • 好消息:Oracle 23ai 现已支持一键部署!
  • ThinkPHP的log
  • 使用 C 模仿 C++ 模板的拙劣方法
  • Flutter 3.35.2 主题颜色设置指南
  • 揭密设计模式:像搭乐高一样构建功能的装饰器模式
  • 《Vue进阶教程》(7)响应式系统介绍
  • 05 Centos 7尝试是否有网络
  • 基于STM32与华为云联动的智能电动车充电桩管理系统
  • Stop-Process : 由于以下错误而无法停止进程“redis-server (26392)”: 拒绝访问。
  • Python OpenCV图像处理与深度学习:Python OpenCV DNN模块深度学习与图像处理
  • PHP的error_log()函数
  • 智慧工地如何撕掉“高危低效”标签?三大社会效益重构建筑业价值坐标
  • 一款开源的CMS系统简介
  • 优秀开源内容转自公众号后端开发成长指南
  • QuickUp-Ubuntu
  • js设计模式-职责链模式
  • 【音视频】Opus 编码格式介绍
  • WPF应用程序资源和样式的使用示例
  • HarmonyOS 应用开发新范式:深入剖析 Stage 模型与 ArkUI 最佳实践
  • 基于vue3和springboot框架集成websocket
  • 网络数据包是怎么在客户端和服务端之间进行传输的?
  • C#实现与西门子S7-1200_1500 PLC通信
  • qt QWebSocket详解
  • 系统扩展策略
  • 【LeetCode_26】删除有序数组中的重复项
  • 小迪web自用笔记24
  • GPT-5论文选题实测:如何从2000篇文献中提炼出3个可快速落地的高命中选题?
  • 从零开始学Vue3:Vue3的生命周期