使用Python脚本下载PDF链接返回404状态码问题排查与解决
问题:Python批量下载PDF返回404,但手动点击链接可正常下载
我有一个包含PDF文件下载链接的.csv文件,手动点击这些链接可自动触发文件下载(示例链接:https://rei.gov.ro/teza-doctorat-document/82405e69f7a7a04f8-TEZA-DOCTORAT-AGNES-GAZDAC-semnat-.pdf)。但用以下Python脚本批量下载时返回404状态码,想知道原因和解决办法。
代码如下:
csv = 'links.csv' df = pd.read_csv(csv) def download_pdf(url, file_name): try: response = requests.get(url) response.raise_for_status() with open(file_name, 'wb') as file: file.write(response.content) except requests.exceptions.RequestException as e: print(e) for i, row in df.iterrows(): url = row['Link'] file_name = f'file_{i + 1}.pdf' download_pdf(url, file_name)
原因分析与解决办法
1. 服务器验证User-Agent
多数网站会通过User-Agent字段识别请求来源,requests库默认的请求头会被标记为非浏览器请求,触发反爬机制返回404。
解决:添加浏览器模拟请求头
修改requests.get请求,加入模拟真实浏览器的User-Agent:
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' } response = requests.get(url, headers=headers)
2. 需要维持会话Cookie
部分网站会在首次访问时设置会话Cookie,后续下载请求必须携带这些Cookie才能通过验证。手动访问时浏览器自动保存Cookie,但脚本每次请求都是独立会话,导致权限验证失败。
解决:使用Session维持会话
用requests.Session()创建持久会话,自动保存和携带Cookie:
# 初始化会话并设置请求头 session = requests.Session() 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' }) # 修改下载函数,传入会话对象 def download_pdf(session, url, file_name): try: response = session.get(url) response.raise_for_status() with open(file_name, 'wb') as file: file.write(response.content) except requests.exceptions.RequestException as e: print(e) # 循环调用时传入session for i, row in df.iterrows(): url = row['Link'].strip() file_name = f'file_{i + 1}.pdf' download_pdf(session, url, file_name)
3. CSV链接存在格式问题
CSV中的链接可能包含多余空格、转义字符或编码错误,导致请求的URL无效。
解决:清理URL格式
读取链接后做标准化处理:
from urllib.parse import unquote url = row['Link'].strip() # 去除首尾空格 url = unquote(url) # 解码URL编码字符
4. 重定向未被正确处理
部分下载链接会先跳转至真实地址,虽然requests默认处理重定向,但极端情况下(如多次跳转、跳转链中有验证)可能失效。
解决:跟踪重定向过程
开启重定向跟踪并检查最终请求地址:
response = session.get(url, allow_redirects=True) print("重定向历史:", response.history) print("最终请求URL:", response.url)
如果发现跳转后地址异常,可直接使用最终URL进行下载。
内容的提问来源于stack exchange,提问作者bSwizzle
相关产品推荐
相关产品推荐

