Scrapy下载中间件处理文件请求及放行指定请求的问题
Scrapy下载中间件处理文件请求及放行指定请求的问题
我明白你现在的困境:用Selenium登录获取cookie后,下载中间件拦截了所有请求,但处理PDF下载请求时直接返回None却没法正常下载,同时你想知道怎么放行特定请求(比如文件下载请求),不让中间件用Selenium去处理它们。
问题根源分析
你之前的做法有两个核心问题:
- 用Selenium访问PDF链接时,
driver.page_source拿到的是浏览器渲染后的PDF阅读器页面(HTML内容),不是原始的二进制PDF文件,所以返回这样的Response完全没法用于文件下载。 - 直接返回
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
关键说明
- 同步Cookie的逻辑:通过
driver.get_cookies()获取当前登录状态下的所有cookie,转成Scrapy请求能识别的字典格式,更新到request.cookies里,这样放行后的请求就带上了登录状态,服务器会允许下载。 - 返回
None的作用:当中间件的process_request返回None时,Scrapy会把这个请求传递给下一个中间件,最终交给默认的下载器去处理,这样就能正常获取二进制的PDF文件,配合你已经配置好的file_urls和files字段,FilesPipeline就能自动完成文件下载和保存。 - 请求判断逻辑:你可以根据实际需求调整判断条件,比如检查
request.url是否以.pdf结尾,或者检查请求的Accept头是否包含application/pdf,这样能更精准地识别文件下载请求。
额外注意事项
确保你已经在settings.py中启用了FilesPipeline:
ITEM_PIPELINES = { 'scrapy.pipelines.files.FilesPipeline': 1, } # 还要配置文件保存路径 FILES_STORE = './downloaded_files'
备注:内容来源于stack exchange,提问作者alley
相关产品推荐
相关产品推荐

