You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:57:17