Python爬虫使用BeautifulSoup获取PDF直链下载到指定目录失败求助
核心问题排查
你的下载逻辑失效主要有以下几个原因:
- Python3版本中urllib库结构调整,你写的
urllib.urlretrieve属于Python2的旧写法,在Python3环境下会直接抛出属性不存在的错误,正确导入路径为urllib.request.urlretrieve。 - 代码存在冗余逻辑:先后两次调用
requests.get(pdf_path),第一次带stream参数的请求完全没有被使用,浪费网络资源。 - 链接拼接逻辑存在缺陷:手动拼接域名和href的方式无法适配绝对路径的PDF链接,会生成无效的错误地址。
- 缺少基础请求头:目标站点有简单反爬校验,使用默认请求头发起请求会被拦截,返回403权限错误,无法拿到真实PDF文件。
- 异常处理逻辑不完善:仅拼接错误字符串但没有输出/抛出,运行出错时无法获取具体报错信息,很难定位问题。
- 代码漏导入
requests库,运行时会直接报模块不存在的错误。
修复后可直接运行的代码
import sys import os import re import requests from bs4 import BeautifulSoup from urllib.parse import urlparse, urljoin import xml.etree.ElementTree as ET def ODFL100(tariff_id): try: pdf_path = ParseXML(tariff_id) download_path = ParseXML(tariff_id, 1) # 配置请求头模拟正常浏览器访问,绕过基础反爬 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } # 单次请求目标页面,自动校验请求状态 page_resp = requests.get(pdf_path, headers=headers) page_resp.raise_for_status() soup = BeautifulSoup(page_resp.text, "html.parser") target_pdf_link = "" # 遍历所有带href属性的a标签匹配目标PDF for a_tag in soup.find_all('a', href=True): current_href = a_tag['href'] # 自动适配相对/绝对路径,无需手动拼接域名 full_link = urljoin(pdf_path, current_href) if full_link.endswith('.pdf') and "rates-and-tariffs" in full_link: target_pdf_link = full_link break if not target_pdf_link: raise RuntimeError("页面中未找到符合规则的PDF下载链接") # 流式下载PDF到指定路径,内存占用更低,兼容性优于urlretrieve pdf_resp = requests.get(target_pdf_link, headers=headers, stream=True) pdf_resp.raise_for_status() with open(download_path, 'wb') as f: for chunk in pdf_resp.iter_content(chunk_size=8192): if chunk: f.write(chunk) print(f"PDF下载完成,保存路径:{download_path}") # 若你坚持使用urlretrieve,可替换为以下Python3兼容写法,需提前导入from urllib.request import urlretrieve # opener = urllib.request.build_opener() # opener.addheaders = [('User-Agent', headers['User-Agent'])] # urllib.request.install_opener(opener) # urlretrieve(target_pdf_link, download_path) except Exception as error: # 打印具体错误信息方便排查 print(f"运行异常:{str(error)}") raise
关键修改说明
- 补全缺失的
requests库导入,修正Python3环境下urllib相关方法的导入路径问题。 - 移除重复的页面请求,新增请求状态校验,请求失败时直接抛出明确错误,避免用错误响应内容做后续解析。
- 用标准库
urljoin替代手动拼接链接,自动适配各种格式的href属性,不会生成无效链接。 - 新增浏览器UA请求头,绕过站点基础反爬拦截,确保能拿到真实页面和PDF内容。
- 下载逻辑替换为requests流式写入,自动处理重定向、Cookie传递等场景,大文件下载时不会占用过高内存,兼容性比老旧的
urlretrieve更好。 - 完善异常处理逻辑,出错时直接打印具体错误信息,降低后续排查成本。
内容的提问来源于stack exchange,提问作者Pr0gramDark
相关产品推荐
相关产品推荐

