如何用Python从网页PDF链接批量下载PDF文件至本地
Python批量下载网页跳转式PDF文件的解决方案
问题背景
网页中的「Download PDF」链接点击后会打开PDF预览页面(需手动点击预览页下载按钮),而非直接触发下载。对应的HTML结构如下:
<a class="cmp-utility-button" href="/content/dam/xxxxxx/en/app-notes/2004/720000999/720000999-en.pdf" target="_blank" title="Download PDF" data-di-id="di-id-31c755d1-a112c01b"> <span>Download PDF </span> </a>
该链接的href为相对路径,完整PDF的绝对URL为:https://www.xxxxxx.com/content/dam/xxxxxx/en/app-notes/2004/720000999/720000999-en.pdf
需求:仅通过原始网页URL,批量处理数百个页面,自动将PDF下载到本地文件夹。
原有代码问题分析
你尝试的代码可能失败的原因包括:
- 相对路径未转绝对路径:直接使用
href的相对路径请求会导致404 - 反爬拦截:
requests请求缺少浏览器标识(UA)、Referer或Cookie,被服务器拦截 - XPATH定位失败:原XPATH用
contains(text(), 'Download PDF'),但文本在<span>子元素中,无法匹配到父级<a>
可行解决方案
方案一:Selenium模拟浏览器自动下载(适配反爬场景)
通过配置Chrome浏览器自动下载PDF(跳过预览页),直接触发下载,适合需要绕过反爬验证的场景。
import os import time from urllib.parse import urljoin from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager def download_pdf_with_selenium(page_url, save_dir): # 创建保存目录 os.makedirs(save_dir, exist_ok=True) # 配置Chrome自动下载PDF,禁用预览 chrome_options = webdriver.ChromeOptions() prefs = { "download.default_directory": os.path.abspath(save_dir), "download.prompt_for_download": False, "download.directory_upgrade": True, "plugins.always_open_pdf_externally": True # 关键:直接下载而非预览 } chrome_options.add_experimental_option("prefs", prefs) driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options) try: driver.get(page_url) time.sleep(2) # 等待页面加载完成 # 定位PDF链接:修正XPATH,匹配子元素文本 pdf_link = driver.find_element(By.XPATH, "//a[contains(@class, 'cmp-utility-button')]/span[contains(text(), 'Download PDF')]/..") pdf_relative_url = pdf_link.get_attribute("href") # 拼接绝对URL pdf_absolute_url = urljoin(page_url, pdf_relative_url) # 点击链接触发自动下载 pdf_link.click() time.sleep(3) # 等待下载完成(根据文件大小调整) print(f"已从 {page_url} 下载PDF到 {save_dir}") except Exception as e: print(f"处理 {page_url} 出错: {str(e)}") finally: driver.quit() # 批量处理示例 save_directory = r"C:\test" page_urls = [ "https://www.example.com/xx1.html", "https://www.example.com/xx2.html", # 更多网页URL... ] for url in page_urls: download_pdf_with_selenium(url, save_directory) time.sleep(1) # 批量处理加延时,避免被封
方案二:Requests+BeautifulSoup高效下载(无反爬场景)
无需启动浏览器,直接解析网页获取PDF链接,带上合规请求头下载,效率更高。
import os import time import requests from bs4 import BeautifulSoup from urllib.parse import urljoin def download_pdf_with_requests(page_url, save_dir): os.makedirs(save_dir, exist_ok=True) # 模拟浏览器请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Referer": page_url } try: # 获取原始网页内容 page_response = requests.get(page_url, headers=headers) page_response.raise_for_status() # 解析网页提取PDF链接 soup = BeautifulSoup(page_response.text, "html.parser") pdf_link = soup.find("a", class_="cmp-utility-button", title="Download PDF") if not pdf_link: print(f"{page_url} 未找到PDF链接") return pdf_relative_url = pdf_link.get("href") pdf_absolute_url = urljoin(page_url, pdf_relative_url) # 下载PDF文件 pdf_response = requests.get(pdf_absolute_url, headers=headers) pdf_response.raise_for_status() # 生成保存路径 pdf_filename = os.path.basename(pdf_absolute_url) save_path = os.path.join(save_dir, pdf_filename) with open(save_path, "wb") as f: f.write(pdf_response.content) print(f"已保存PDF到: {save_path}") except Exception as e: print(f"处理 {page_url} 出错: {str(e)}") # 批量处理示例 save_directory = r"C:\test" page_urls = [ "https://www.example.com/xx1.html", "https://www.example.com/xx2.html", # 更多网页URL... ] for url in page_urls: download_pdf_with_requests(url, save_directory) time.sleep(1) # 加延时避免触发反爬
注意事项
- 批量处理时务必添加延时,或使用代理池,避免被目标网站封禁IP
- 用
urljoin拼接绝对URL,避免手动拼接路径时出错 - 如果遇到登录验证,可在Selenium中先完成登录,或在Requests中保存登录Cookie
- 可添加文件存在检查逻辑,避免重复下载相同文件
内容的提问来源于stack exchange,提问作者ylin321
相关产品推荐
相关产品推荐

