如何用Beautiful Soup或Selenium(Py)下载ASPX动态PDF链接?
解决ASPX动态网站批量下载Misdemeanor日历PDF的问题
你的问题很典型——ASPX动态页面的链接不是静态URL,而是通过__doPostBack JavaScript函数触发服务器生成PDF,所以直接用requests访问HTML里的href只会得到无效内容。下面给你两种可行的解决方案,优先推荐Selenium方案,因为更直观易实现:
方案一:用Selenium批量点击并自动下载PDF
这个方案会配置Firefox自动下载PDF到指定文件夹,然后循环打开每个"Misdemeanor"链接,完成下载后关闭标签回到原页面:
from selenium import webdriver from selenium.webdriver.firefox.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import time import os # 配置下载路径和浏览器偏好 download_folder = os.path.join(os.getcwd(), "Calendars") os.makedirs(download_folder, exist_ok=True) firefox_options = Options() # 设置自定义下载文件夹 firefox_options.set_preference("browser.download.folderList", 2) firefox_options.set_preference("browser.download.dir", download_folder) # 指定PDF类型自动下载,不弹出询问框 firefox_options.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/pdf") # 禁用Firefox内置PDF查看器,直接下载文件 firefox_options.set_preference("pdfjs.disabled", True) # 启动浏览器并打开目标页面 browser = webdriver.Firefox(options=firefox_options) browser.get("http://www.imperial.courts.ca.gov/CourtCalendars/Public/MCalendars.aspx") # 获取所有"Misdemeanor"链接元素 misdemeanor_links = browser.find_elements(By.LINK_TEXT, "Misdemeanor") total_links = len(misdemeanor_links) print(f"已找到 {total_links} 个Misdemeanor日历链接") # 保存原页面窗口句柄,方便后续切换回去 original_window = browser.current_window_handle for index, link in enumerate(misdemeanor_links): print(f"正在处理第 {index + 1}/{total_links} 个链接...") # 按住Ctrl+点击链接,在新标签页打开(避免跳转原页面导致元素失效) link.send_keys(Keys.CONTROL + Keys.RETURN) # 等待新标签页加载 time.sleep(1) # 切换到新打开的标签页 for window in browser.window_handles: if window != original_window: browser.switch_to.window(window) break # 等待PDF下载完成(根据网络速度调整等待时间) time.sleep(3) # 关闭当前标签页,回到原页面 browser.close() browser.switch_to.window(original_window) print("所有PDF下载完成!") browser.quit()
关键说明:
- 配置浏览器偏好是核心:让Firefox自动下载PDF,不用手动确认弹窗
- 用
Ctrl+RETURN打开新标签,避免原页面DOM被破坏,导致后续链接找不到 - 切换窗口句柄是管理多标签页的关键,记得处理完一个标签后切回原页面
方案二:用requests模拟ASPX表单提交(无需浏览器)
如果想避免使用浏览器,效率更高,可以直接模拟ASPX的__doPostBack请求,需要先获取页面的ViewState和EventValidation等参数:
import requests from bs4 import BeautifulSoup import os import re download_folder = os.path.join(os.getcwd(), "Calendars") os.makedirs(download_folder, exist_ok=True) session = requests.Session() base_url = "http://www.imperial.courts.ca.gov/CourtCalendars/Public/MCalendars.aspx" # 第一步:获取初始页面,提取ViewState、EventValidation和__EVENTTARGET等参数 response = session.get(base_url) response.raise_for_status() soup = BeautifulSoup(response.text, "html.parser") # 提取ASPX必需的表单参数 view_state = soup.find("input", {"id": "__VIEWSTATE"}).get("value") view_state_generator = soup.find("input", {"id": "__VIEWSTATEGENERATOR"}).get("value") event_validation = soup.find("input", {"id": "__EVENTVALIDATION"}).get("value") # 找到所有Misdemeanor链接对应的__doPostBack参数 links = soup.find_all("a", string="Misdemeanor") post_back_pattern = re.compile(r"__doPostBack\('(.*?)','(.*?)'\)") for index, link in enumerate(links): print(f"正在下载第 {index + 1}/{len(links)} 个PDF...") # 解析__doPostBack的参数 match = post_back_pattern.search(link.get("href")) event_target = match.group(1) event_argument = match.group(2) # 构造POST请求数据 form_data = { "__VIEWSTATE": view_state, "__VIEWSTATEGENERATOR": view_state_generator, "__EVENTVALIDATION": event_validation, "__EVENTTARGET": event_target, "__EVENTARGUMENT": event_argument } # 发送POST请求获取PDF内容 pdf_response = session.post(base_url, data=form_data) pdf_response.raise_for_status() # 提取PDF文件名(从响应头或链接推导) content_disposition = pdf_response.headers.get("Content-Disposition") if content_disposition: filename = re.findall(r"filename=(.+)", content_disposition)[0].strip('"') else: filename = f"misdemeanor_calendar_{index + 1}.pdf" # 保存PDF文件 with open(os.path.join(download_folder, filename), "wb") as f: f.write(pdf_response.content) print("所有PDF下载完成!")
关键说明:
- 必须使用
requests.Session()保持会话,因为ASPX页面依赖Cookie维持状态 - 要准确提取
__VIEWSTATE等隐藏表单参数,这些是服务器验证请求合法性的关键 - 通过正则表达式解析
__doPostBack的参数,构造正确的POST请求
两种方案都能解决你的问题,Selenium更适合新手,不用处理复杂的表单参数;requests方案更高效,适合批量处理大量链接。
内容的提问来源于stack exchange,提问作者themagicbean
相关产品推荐
相关产品推荐

