使用Python和wget自动抓取网站PDF文件失败的问题排查
解决ASP动态网站PDF下载失败的方案
常见失败原因
- ASP(尤其是ASP.NET)类网站依赖会话Cookie或ViewState验证请求合法性,直接用wget或解析本地静态HTML的链接,缺少必要的会话标识,会被服务器拒绝。
- 课程/年份选择后,PDF链接是通过AJAX异步加载的,直接保存的HTML里根本没真实的有效链接。
- 很多这类网站的PDF链接是临时一次性链接,仅当前会话内有效,存到本地后链接已经失效。
针对性解决方法
1. 用带会话保持的HTTP客户端模拟操作(Python示例)
先模拟用户选课程/年份的流程,维持会话状态,再抓取真实的PDF链接并下载:
import requests from bs4 import BeautifulSoup # 初始化会话,自动维护Cookie session = requests.Session() # 模拟浏览器UA,避免被反爬拦截 session.headers.update({ "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" }) # 第一步:访问网站首页,获取ASP.NET需要的ViewState等参数 home_url = "你的网站首页URL" resp = session.get(home_url) soup = BeautifulSoup(resp.text, "html.parser") # 提取ViewState和生成器(ASP.NET网站必备) view_state = soup.find("input", id="__VIEWSTATE")["value"] view_state_gen = soup.find("input", id="__VIEWSTATEGENERATOR")["value"] # 第二步:构造课程/年份选择的表单数据 # 注意:控件ID和值要从网页源码里找(比如用F12看表单元素的name属性) form_data = { "__VIEWSTATE": view_state, "__VIEWSTATEGENERATOR": view_state_gen, "CourseDropdown": "你要选的课程ID", "YearDropdown": "你要选的年份值", "SubmitButton": "确认选择" } # 第三步:提交表单,进入包含PDF的页面 submit_url = "处理表单的ASP页面URL(一般是form的action属性值)" resp = session.post(submit_url, data=form_data) soup = BeautifulSoup(resp.text, "html.parser") # 第四步:提取PDF链接并下载 pdf_a_tag = soup.find("a", href=True, string="PDF下载") # 根据实际文本调整 pdf_link = pdf_a_tag["href"] # 处理相对链接,拼接完整URL if not pdf_link.startswith(("http://", "https://")): pdf_link = f"{home_url.rsplit('/', 1)[0]}/{pdf_link.lstrip('/')}" # 下载PDF文件 pdf_resp = session.get(pdf_link) with open("目标教材.pdf", "wb") as f: f.write(pdf_resp.content)
2. 先排查本地HTML里的链接问题
看看你保存的本地HTML中的PDF链接片段,比如:
<a href="/temp/2024_cs_001.pdf?sess=abcdef">下载扫描版</a>
- 如果是相对链接,必须拼接网站的域名和前缀才能访问;
- 如果链接带
sess这类会话参数,说明必须携带对应Cookie才能访问,这种情况只能用保持会话的方式请求。
3. 用浏览器开发者工具追踪真实请求
- 打开浏览器F12进入Network面板;
- 正常操作选择课程/年份,点击下载按钮;
- 在Network里找到PDF的请求记录,查看请求头里的
Cookie、Referer等关键参数; - 把这些参数复制到你的代码里,确保请求和浏览器完全一致。
特殊情况处理
如果PDF链接是JavaScript动态生成的,上面的方法可能失效,这时候可以用selenium模拟完整的浏览器操作:
from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("你的网站首页URL") # 模拟选择课程和年份 driver.find_element(By.ID, "CourseDropdown").select_by_value("目标课程值") driver.find_element(By.ID, "YearDropdown").select_by_value("目标年份值") driver.find_element(By.ID, "SubmitButton").click() # 等待页面加载,获取PDF链接 pdf_link = driver.find_element(By.LINK_TEXT, "PDF下载").get_attribute("href") # 用之前的session下载,或者直接用selenium保存 driver.get(pdf_link) # 后续处理保存逻辑... driver.quit()
内容的提问来源于stack exchange,提问作者user9118870
相关产品推荐
相关产品推荐

