【问题标题】:Scrapy spider not terminating with use of CloseSpider extensionScrapy spider 未使用 CloseSpider 扩展终止
【发布时间】:2017-06-15 11:19:38
【问题描述】:

我已经设置了一个解析 xml 提要的 Scrapy 蜘蛛,处理大约 20,000 条记录。

出于开发目的,我想限制处理的项目数量。通过阅读 Scrapy 文档,我发现我需要使用 CloseSpider 扩展。

我已按照有关如何启用此功能的指南进行操作 - 在我的蜘蛛配置中,我有以下内容:

CLOSESPIDER_ITEMCOUNT = 1
EXTENSIONS = {
    'scrapy.extensions.closespider.CloseSpider': 500,
}

但是,我的蜘蛛永远不会终止 - 我知道 CONCURRENT_REQUESTS 设置会影响蜘蛛实际终止的时间(因为它将继续处理每个并发请求),但这仅设置为默认值 16,并且但我的蜘蛛会继续处理所有项目。

我尝试改用CLOSESPIDER_TIMEOUT 设置,但同样没有效果。

这是我运行蜘蛛时的一些调试信息:

2017-06-15 12:14:11 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: myscraper)
2017-06-15 12:14:11 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'myscraper', 'CLOSESPIDER_ITEMCOUNT': 1, 'FEED_URI': 'file:///tmp/myscraper/export.jsonl', 'NEWSPIDER_MODULE': 'myscraper.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['myscraper.spiders'], 'USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'}
2017-06-15 12:14:11 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
 'scrapy.extensions.telnet.TelnetConsole',
 'scrapy.extensions.feedexport.FeedExporter',
 'scrapy.extensions.logstats.LogStats',
 'scrapy.extensions.closespider.CloseSpider']
2017-06-15 12:14:11 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
2017-06-15 12:14:11 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']
2017-06-15 12:14:11 [scrapy.middleware] INFO: Enabled item pipelines:
['myscraper.pipelines.MyScraperPipeline']
2017-06-15 12:14:11 [scrapy.core.engine] INFO: Spider opened

可以看出,CloseSpider 扩展和CLOSESPIDER_ITEMCOUNT 设置正在应用中。

任何想法为什么这不起作用?

【问题讨论】:

  • 可以使用 CloseSpider Exception 来限制项数,
  • @parik 我也试过这个 - 但我不确定在哪里添加它?我将它添加到我的管道中,但这似乎只是终止了该项目 - 然后它继续对每个项目执行相同的操作。你能举个例子吗?
  • 好的,对于您的问题,请添加 CONCURRENT_REQUEST = 1 并让我知道它是否有效
  • @parik - 恐怕我已经试过了。

标签: python python-3.x scrapy scrapy-spider


【解决方案1】:

在 parik 的回答和我自己的研究的帮助下,我想出了一个解决方案。不过,它确实有一些无法解释的行为,我将对此进行介绍(感谢 cmets)。

在我的蜘蛛的myspider_spider.py 文件中,我有(为简洁而编辑):

import scrapy
from scrapy.spiders import XMLFeedSpider
from scrapy.exceptions import CloseSpider
from myspiders.items import MySpiderItem

class MySpiderSpider(XMLFeedSpider):
    name = "myspiders"
    allowed_domains = {"www.mysource.com"}
    start_urls = [
        "https://www.mysource.com/source.xml"
        ]
    iterator = 'iternodes'
    itertag = 'item'
    item_count = 0

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(settings)

    def __init__(self, settings):
        self.settings = settings

    def parse_node(self, response, node):
        if(self.settings['CLOSESPIDER_ITEMCOUNT'] and int(self.settings['CLOSESPIDER_ITEMCOUNT']) == self.item_count):
            raise CloseSpider('CLOSESPIDER_ITEMCOUNT limit reached - ' + str(self.settings['CLOSESPIDER_ITEMCOUNT']))
        else:
            self.item_count += 1
        id = node.xpath('id/text()').extract()
        title = node.xpath('title/text()').extract()
        item = MySpiderItem()
        item['id'] = id
        item['title'] = title

        return item

这行得通 - 如果我将 CLOSESPIDER_ITEMCOUNT 设置为 10,它会在处理 10 个项目后终止(因此,在这方面它似乎忽略了 CONCURRENT_REQUESTS - 这是出乎意料的)。

我在我的settings.py 中评论了这个:

#EXTENSIONS = {
#   'scrapy.extensions.closespider.CloseSpider': 500,
#}

所以,它只是使用CloseSpider 异常。但是,日志显示以下内容:

2017-06-16 10:04:15 [scrapy.core.engine] INFO: Closing spider (closespider_itemcount)
2017-06-16 10:04:15 [scrapy.extensions.feedexport] INFO: Stored jsonlines feed (10 items) in: file:///tmp/myspiders/export.jsonl
2017-06-16 10:04:15 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 600,
 'downloader/request_count': 2,
 'downloader/request_method_count/GET': 2,
 'downloader/response_bytes': 8599860,
 'downloader/response_count': 2,
 'downloader/response_status_count/200': 2,
 'finish_reason': 'closespider_itemcount',
 'finish_time': datetime.datetime(2017, 6, 16, 9, 4, 15, 615501),
 'item_scraped_count': 10,
 'log_count/DEBUG': 8,
 'log_count/INFO': 8,
 'response_received_count': 2,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 1,
 'scheduler/enqueued/memory': 1,
 'start_time': datetime.datetime(2017, 6, 16, 9, 3, 47, 966791)}
2017-06-16 10:04:15 [scrapy.core.engine] INFO: Spider closed (closespider_itemcount)

要突出显示的关键是第一行INFOfinish_reason - 在INFO 下显示的消息不是我在引发CloseSpider 异常时设置的消息。这意味着阻止蜘蛛的是CloseSpider 扩展,但我知道不是吗?非常混乱。

【讨论】:

    【解决方案2】:

    你也可以使用CloseSpider Exception来限制物品的数量,

    只要注意, CloseSpider 异常仅支持蜘蛛回调中。

    正如您在documentation 中看到的那样

    可以从蜘蛛回调中引发此异常以请求 蜘蛛被关闭/停止。支持的参数:

    some examples

    【讨论】:

    • 我对这个异常做了更多的试验,现在它正在工作 - 我将把它作为答案发布。不过它表现出奇怪的行为,我无法完全解释。
    • @BrynJ 是的,很奇怪,CloseSpider 扩展在一定数量的项目后没有关闭你的蜘蛛
    • 用我对奇怪行为的观察添加了我的答案。您的意见将不胜感激。
    • setting.py 中@BrynJ,ITEM_PIPELINES 中,item 数量是多于还是少于500?
    • 它的优先级设置为 500 - 但是,需要明确的是,我现在不会在我的管道中抛出 CloseSpider 异常,而是在主要异常中抛出它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    • 2017-03-19
    相关资源
    最近更新 更多