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

Python批量下载的PDF无法打开,如何修复代码问题

问题分析与修复方案

核心问题

你遇到的PDF无法打开的情况,大概率是下载的内容并非真实PDF文件——哪怕响应头标注了application/pdf,实际返回的可能是网站的错误页面(比如HTML),或者内容编码处理错误。

你的代码里的明显问题

第二个代码中,你调用了base64.b64decode(response.content)把内容解码,但最终写入文件的还是原始的response.content,等于解码操作完全没生效,这是无用的冗余代码。

修复步骤

1. 先确认下载内容的真实格式

下载一个文件后,用文本编辑器打开,看开头是否是%PDF-(PDF文件的标准开头)。如果是<html>或其他标签,说明网站需要额外的请求头或会话验证才能获取真实PDF。

2. 修正代码:处理会话与请求头

目标站点(BM&F Bovespa的FNET)通常需要维持会话状态,或者携带Referer头才能正常返回PDF。以下是修正后的代码:

import pandas as pd
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

# 禁用证书警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# 初始化会话,维持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',
    'Referer': 'https://fnet.bmfbovespa.com.br/fnet/publico/exibirDocumento?id='  # 基础Referer
})

# 加载Excel中的ID
df = pd.read_excel('prospectos_numero.xlsx')

for number in df['ID_num']:
    # 先访问文档页面,获取必要的会话Cookie
    doc_url = f'https://fnet.bmfbovespa.com.br/fnet/publico/exibirDocumento?id={number}'
    session.get(doc_url, verify=False)
    
    # 再请求下载链接
    download_url = f'https://fnet.bmfbovespa.com.br/fnet/publico/downloadDocumento?id={number}'
    response = session.get(download_url, verify=False)
    
    # 验证内容是否为PDF:检查开头是否是%PDF-
    is_pdf = response.content.startswith(b'%PDF-')
    if response.status_code == 200 and is_pdf:
        with open(f'{number}.pdf', 'wb') as file:
            file.write(response.content)
        print(f'文件 {number}.pdf 下载成功')
    else:
        # 打印前100个字符排查内容
        print(f'下载 {number} 失败,状态码: {response.status_code},内容预览: {response.content[:100]}')

3. 处理base64编码的情况

如果确认返回的内容是base64编码的PDF(比如响应内容是一串base64字符串),则需要将解码后的内容写入文件:

# 替换写入文件的部分
import base64
content = base64.b64decode(response.content)
if content.startswith(b'%PDF-'):
    with open(f'{number}.pdf', 'wb') as file:
        file.write(content)
    print(f'文件 {number}.pdf 解码并下载成功')

额外提示

  • 不要盲目信任Content-Type响应头,直接校验文件内容的特征是更可靠的方式。
  • 部分站点会对频繁请求做限制,如果遇到批量下载失败,可添加time.sleep(1)在循环中,避免请求过于频繁。

内容的提问来源于stack exchange,提问作者Vinícius de Oliveira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:22:15