Python中Scrapy出现failure时如何执行close_spider

最近用 scrapy,因为网站限制,经常抓到一定数量的时候出现:

2018-01-25 23:12:42 [scrapy.core.scraper] ERROR: Error downloading <GET https://XXX.com/id=139988706>;: [<twisted.python.failure.Failure twisted.internet.error.ConnectionDone: Connection was closed cleanly.>]


IP 被限制了,这时 scrapy 会继续的去尝试抓取剩下的页面,耗费时间
我是想如果发现这种情况,就主动发起 close_spider,结束抓取。
请问大婶们,该在哪里进行配置?

yield scrapy.Request(url,self.parse_item) ——这里可以吗?如何配置?
Python中Scrapy出现failure时如何执行close_spider


8 回复

在Scrapy中,当爬虫因异常或主动关闭时,可以通过close_spider信号来执行清理操作。如果需要在爬虫失败时执行特定逻辑,可以结合spider_closed信号和爬虫的close_reason属性来判断。

下面是一个完整的示例,演示如何在爬虫失败时执行close_spider逻辑:

import scrapy
from scrapy import signals
from scrapy.exceptions import CloseSpider

class MySpider(scrapy.Spider):
    name = 'my_spider'
    start_urls = ['http://example.com']

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super().from_crawler(crawler, *args, **kwargs)
        # 连接spider_closed信号
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        return spider

    def parse(self, response):
        # 模拟失败情况:例如检查特定条件后主动关闭爬虫
        if 'error' in response.text:
            # 使用CloseSpider异常来关闭爬虫,并指定原因
            raise CloseSpider(reason='检测到错误页面')

    def spider_closed(self, spider, reason):
        # 检查关闭原因
        if reason == 'finished':
            print("爬虫正常结束")
        else:
            print(f"爬虫因失败关闭: {reason}")
            # 这里执行失败时的清理或记录操作
            self.handle_failure(reason)

    def handle_failure(self, reason):
        # 自定义失败处理逻辑
        # 例如:记录日志、发送通知、清理临时文件等
        with open('spider_failure.log', 'a') as f:
            f.write(f'Spider closed with reason: {reason}\n')
        print(f"已记录失败原因: {reason}")

# 运行爬虫的配置示例(通常写在settings.py或启动脚本中)
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

process = CrawlerProcess(get_project_settings())
process.crawl(MySpider)
process.start()

关键点:

  1. 连接信号:在from_crawler方法中连接spider_closed信号到自定义方法。
  2. 判断关闭原因spider_closed方法的reason参数会传递爬虫关闭的原因。常见原因包括:
    • 'finished':正常完成
    • 'shutdown':手动关闭
    • 自定义原因字符串(如示例中的'检测到错误页面'
  3. 主动触发失败:可以通过抛出CloseSpider异常并指定原因来主动关闭爬虫。
  4. 失败处理:在spider_closed中根据reason执行不同的清理或记录操作。

一句话总结: 通过spider_closed信号和close_reason判断失败状态并执行对应清理。

raise CloseSpider()

scrapy.Request()有个参数 errback。比如 scrapy.Request(self.url, self.parse, errback=self.handle_error, dont_filter=True) ,当出现错误时就会调用 handle_error()这个函数,在里面关爬虫就可以了。 具体用法可以去官方文档看 Requests and Responses 一节,也可以通过搜索框搜索 errback。

同意楼上,也可以加一个中间件结束

赞同 5 楼的积极解决问题的方案

收到,谢谢大家。
通过大家的回复,我学习到了,自己对 scrapy 的了解仅仅是点,应该好好学习官方文档形成一个大的知识面。

5 楼的方案之前用过,因为价格原因,大大超出了预算。(我要抓取的数据是千万级反复过滤)

回到顶部