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

使用Scrapy批量下载网站PDF文件失败求助

解决Scrapy下载PDF文件不符预期的问题

常见问题排查与修复步骤

1. 检查PDF链接提取是否正确

你大概率提取了跳转页/预览页的链接而非PDF文件的直接下载链接。很多网站会把PDF放在详情页里,直接抓取详情页URL下载得到的只会是HTML页面,不是目标PDF。

  • 手动打开目标网站,右键检查PDF下载按钮,查看其href属性,确认是否指向带.pdf后缀的真实地址
  • 修改Spider的链接提取逻辑,确保抓取的是直接下载链接:
    # 错误示例:抓取了跳转链接
    links = response.css('a.pdf-preview::attr(href)').getall()
    # 正确示例:筛选带.pdf后缀的链接,或直接抓取下载按钮的真实地址
    links = [response.urljoin(link) for link in response.css('a.download-btn::attr(href)').getall() if link.endswith('.pdf')]
    

2. 验证下载请求的响应内容

在Spider中添加日志,打印每个链接的响应头部,确认Content-Type是否为application/pdf:

def parse(self, response):
    links = [...] # 你的链接提取逻辑
    for link in links:
        yield scrapy.Request(
            link,
            callback=self.save_pdf,
            meta={'target_link': link}
        )

def save_pdf(self, response):
    # 打印响应类型,排查是否为PDF
    content_type = response.headers.get('Content-Type', b'')
    self.logger.info(f"链接 {response.meta['target_link']} 的内容类型: {content_type}")
    if b'application/pdf' in content_type:
        filename = response.url.split('/')[-1]
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.logger.info(f"已保存PDF: {filename}")
    else:
        self.logger.warning(f"非PDF内容,跳过链接: {response.meta['target_link']}")

3. 处理动态加载的PDF链接

如果网站用JavaScript渲染PDF下载链接,普通Scrapy请求无法抓取真实地址:

  • 改用scrapy-splash或playwright等工具渲染页面后再提取链接
  • 查看浏览器网络请求记录,找到PDF下载的真实API接口,直接请求该接口获取文件

4. 分析运行日志的关键信息

从你的运行日志里重点关注:

  • 每个请求的返回状态码(200不代表是PDF,跳转页也会返回200)
  • 响应的Content-Length,PDF文件通常比HTML页面体积大很多
  • 是否存在302重定向,重定向后的地址可能并非PDF文件

修正后的示例Spider代码

import scrapy

class PdfDownloadSpider(scrapy.Spider):
    name = 'toscrape-css2'
    start_urls = ['你的目标网站URL']

    def parse(self, response):
        # 提取所有带.pdf后缀的直接下载链接
        pdf_links = response.css('a[href$=".pdf"]::attr(href)').getall()
        for link in pdf_links:
            absolute_url = response.urljoin(link)
            yield scrapy.Request(absolute_url, callback=self.download_pdf)

    def download_pdf(self, response):
        # 确认是PDF格式再保存
        if response.headers.get('Content-Type') == b'application/pdf':
            filename = response.url.split('/')[-1]
            with open(filename, 'wb') as f:
                f.write(response.body)
            self.logger.info(f"成功下载PDF: {filename}")
        else:
            self.logger.error(f"非PDF内容,链接: {response.url}")

内容的提问来源于stack exchange,提问作者user2813283

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:45:02