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

Scrapy下载中间件处理文件请求及放行指定请求的问题

Scrapy下载中间件处理文件请求及放行指定请求的问题

我明白你现在的困境:用Selenium登录获取cookie后,下载中间件拦截了所有请求,但处理PDF下载请求时直接返回None却没法正常下载,同时你想知道怎么放行特定请求(比如文件下载请求),不让中间件用Selenium去处理它们。

问题根源分析

你之前的做法有两个核心问题:

  1. 用Selenium访问PDF链接时,driver.page_source拿到的是浏览器渲染后的PDF阅读器页面(HTML内容),不是原始的二进制PDF文件,所以返回这样的Response完全没法用于文件下载。
  2. 直接返回None虽然会让Scrapy继续处理请求,但此时请求没有带上登录后的cookie,导致请求可能被服务器拒绝,所以下载失败。

解决方案

要实现放行指定请求(比如PDF下载)并正常下载,你需要做两件事:

  • 对PDF类请求,跳过Selenium的处理逻辑,直接让Scrapy的默认下载器去请求资源。
  • 把Selenium中已登录的cookie同步到Scrapy的请求里,确保请求带上登录状态。

修改后的中间件代码示例

from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException, NoSuchElementException

def process_request(self, request, spider):
    # 先判断是否是PDF下载请求,如果是,直接同步cookie后放行
    if "pdf" in request.url:
        spider.logger.info("放行PDF下载请求,同步登录cookie")
        # 把Selenium driver中的cookie同步到Scrapy请求中
        cookies = spider.driver.get_cookies()
        cookie_dict = {cookie['name']: cookie['value'] for cookie in cookies}
        request.cookies.update(cookie_dict)
        # 返回None,让Scrapy默认下载器处理这个请求
        return None
    
    # 非PDF请求,继续用Selenium处理
    try:
        spider.driver.get(request.url)
        detail_code = spider.driver.page_source
        spider.logger.info("当前正在拦截详细页请求")
        res = HtmlResponse(
            url=request.url,
            encoding='utf-8',
            body=detail_code,
            request=request,
            headers={"key": spider.key}
        )
        return res
    except TimeoutException:
        spider.logger.error("time out -> 访问超时")
    except NoSuchElementException:
        spider.logger.error("no such element -> 没有此元素")
    return None

关键说明

  1. 同步Cookie的逻辑:通过driver.get_cookies()获取当前登录状态下的所有cookie,转成Scrapy请求能识别的字典格式,更新到request.cookies里,这样放行后的请求就带上了登录状态,服务器会允许下载。
  2. 返回None的作用:当中间件的process_request返回None时,Scrapy会把这个请求传递给下一个中间件,最终交给默认的下载器去处理,这样就能正常获取二进制的PDF文件,配合你已经配置好的file_urls和files字段,FilesPipeline就能自动完成文件下载和保存。
  3. 请求判断逻辑:你可以根据实际需求调整判断条件,比如检查request.url是否以.pdf结尾,或者检查请求的Accept头是否包含application/pdf,这样能更精准地识别文件下载请求。

额外注意事项

确保你已经在settings.py中启用了FilesPipeline:

ITEM_PIPELINES = {
    'scrapy.pipelines.files.FilesPipeline': 1,
}
# 还要配置文件保存路径
FILES_STORE = './downloaded_files'

备注:内容来源于stack exchange,提问作者alley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 13:10:31