批量下载与合并课件¶
举例: http://zhiqihuang.top/gr/lectures.php , 网站上有很多 url. 点开后, 是 http://zhiqihuang.top/gr/lectures/*.pdf。
批量爬取 http://zhiqihuang.top/gr/lectures/*.pdf
# 导入所需的库:requests 用于发起网络请求,BeautifulSoup 用于解析 HTML,os 用于操作文件系统
import requests
from bs4 import BeautifulSoup
import os
# 设置要抓取 PDF 文件链接的网页 URL
url = 'http://zhiqihuang.top/gr/lectures.php'
# 使用 requests 库发起 HTTP GET 请求,获取网页内容
response = requests.get(url)
# 使用 BeautifulSoup 解析获取到的网页内容,'html.parser' 是用来解析 HTML 的解析器
soup = BeautifulSoup(response.text, 'html.parser')
# 使用 BeautifulSoup 查找所有的 <a> 标签(即超链接标签),并过滤出那些 href 属性以 '.pdf' 结尾的链接
# 这一步是为了找到所有指向 PDF 文件的链接
pdf_links = [link.get('href') for link in soup.find_all('a') if link.get('href') and link.get('href').endswith('.pdf')]
# 设置一个目录用于存放下载的 PDF 文件
download_dir = 'downloaded_pdfs'
# 使用 os.makedirs 创建这个目录,exist_ok=True 参数表示如果目录已经存在则忽略该命令,不会引发错误
os.makedirs(download_dir, exist_ok=True)
# 遍历所有找到的 PDF 文件链接
for pdf_url in pdf_links:
# 构建完整的 PDF 文件 URL,因为从网页上获取的可能是相对路径
full_pdf_url = f'http://zhiqihuang.top/gr/{pdf_url}'
# 使用 requests 发起 GET 请求下载 PDF 文件,stream=True 参数表示以流模式获取数据,适用于下载大文件
pdf_response = requests.get(full_pdf_url, stream=True)
# 检查 HTTP 响应状态码,200 表示请求成功
if pdf_response.status_code == 200:
# 从 PDF 链接中提取文件名
pdf_name = os.path.basename(pdf_url)
# 构建保存 PDF 文件的完整路径
pdf_path = os.path.join(download_dir, pdf_name)
# 以二进制写模式打开文件,准备写入下载的 PDF 数据
with open(pdf_path, 'wb') as pdf_file:
# iter_content 方法用于流式下载文件,chunk_size=8192 表示每次写入 8192 字节的数据
for chunk in pdf_response.iter_content(chunk_size=8192):
pdf_file.write(chunk)
# 打印下载成功的消息
print(f"Downloaded {pdf_name}")
else:
# 如果状态码不是 200,打印下载失败的消息
print(f"Failed to download {pdf_url}, status code {pdf_response.status_code}")
# 最后,打印所有文件尝试下载完成的消息
print("All PDF files have been downloaded or attempted.")
将下载好的 pdf 合并:
# 导入操作系统相关的库,用于处理文件和目录路径
import os
# 导入 fitz 库,也就是 PyMuPDF,一个用于处理 PDF 文件的库
import fitz
# 定义一个函数来合并 PDF 文件
# pdfs_dir 参数是包含 PDF 文件的目录的路径
# output_pdf_name 参数是合并后的 PDF 文件的名称
def merge_pdfs(pdfs_dir, output_pdf_name):
# 创建一个新的空 PDF 文档对象
merged_pdf = fitz.open()
# 获取指定目录下的所有文件名,然后按字母顺序排序
pdf_files = sorted(os.listdir(pdfs_dir))
# 遍历排序后的文件名列表
for pdf_file in pdf_files:
# 检查文件名是否以 .pdf 结尾
if pdf_file.endswith('.pdf'):
# 构建完整的文件路径
pdf_file_path = os.path.join(pdfs_dir, pdf_file)
# 打印出正在尝试打开的 PDF 文件路径
print(f"Trying to open: {pdf_file_path}")
try:
# 使用 fitz 打开当前的 PDF 文件
current_pdf = fitz.open(pdf_file_path)
# 将当前打开的 PDF 文档插入到合并的 PDF 文档中
merged_pdf.insert_pdf(current_pdf)
# 关闭当前打开的 PDF 文件
current_pdf.close()
except Exception as e:
# 如果在处理当前 PDF 文件时遇到异常,则打印错误信息
print(f"Error processing {pdf_file_path}: {e}")
# 检查合并后的 PDF 文档中是否至少有一页
if len(merged_pdf) > 0:
# 如果有,则保存合并后的 PDF 文档到指定的文件名
merged_pdf.save(output_pdf_name)
# 关闭合并后的 PDF 文档
merged_pdf.close()
# 打印成功合并的消息
print(f"All PDF files have been merged into {output_pdf_name}")
else:
# 如果合并后的 PDF 文档中没有页面,则打印错误消息
print("No PDF files were merged. Please check the file paths.")
# 指定包含 PDF 文件的目录的路径
pdfs_dir = '/mnt/e/garnet/mathworld/huangzhiqiang_gr/downloaded_pdfs'
# 指定合并后的 PDF 文件的名称
output_pdf_name = 'Merged_PDFs.pdf'
# 调用函数,执行合并 PDF 文件的操作
merge_pdfs(pdfs_dir, output_pdf_name)