【问题标题】:How to change depth limit while crawling with scrapy?使用scrapy爬行时如何更改深度限制?
【发布时间】:2019-12-05 12:43:00
【问题描述】:

我想在我的蜘蛛中禁用深度检查和迭代,或者在爬行时更改深度限制。这是我的一些代码:

    def start_requests(self):
        if isinstance(self.vuln, context.GenericVulnerability):
            yield Request(
                self.vuln.base_url,
                callback=self.determine_aliases,
                meta=self._normal_meta,
            )
        else:
            for url in self.vuln.entrypoint_urls:
                yield Request(
                    url, callback=self.parse, meta=self._patch_find_meta
                )


    @inline_requests
    def determine_aliases(self, response):
        vulns = [self.vuln]
        processed_vulns = set()
        while vulns:
            vuln = vulns.pop()
            if vuln.vuln_id is not self.vuln.vuln_id:
                response = yield Request(vuln.base_url)
            processed_vulns.add(vuln.vuln_id)
            aliases = context.create_vulns(*list(self.parse(response)))
            for alias in aliases:
                if alias.vuln_id in processed_vulns:
                    continue
                if isinstance(alias, context.GenericVulnerability):
                    vulns.append(alias)
                else:
                    logger.info("Alias discovered: %s", alias.vuln_id)
                    self.cves.add(alias)
        yield from self._generate_requests_for_vulns()


    def _generate_requests_for_vulns(self):
        for vuln in self.cves:
            for url in vuln.entrypoint_urls:
                yield Request(
                    url, callback=self.parse, meta=self._patch_find_meta
                )

我的程序是这样的,用户可以给出他们需要/想要的深度限制作为输入。在某些情况下,我的默认解析方法允许递归爬取链接。

determine_aliases 是一种预处理方法,_generate_requests_for_vulns 生成的请求用于实际解决方案。

如您所见,我从响应中抓取了我需要的数据,并将其存储在来自确定别名的蜘蛛类中的一个集合属性“cves”中。完成后,我会从 _generate_requests_for_vulns 生成带有该数据的请求。

这里的问题是,要么产生来自确定别名的请求,要么调用确定别名作为回调迭代深度。因此,当我从 _generate_requests_for_vulns 发出请求以进行进一步爬取时,我的深度限制比预期的要快。

请注意,实际的爬取解决方案是从 _generate_requests_for_vulns 生成的请求开始的,因此给定的深度限制应仅适用于这些请求。

【问题讨论】:

  • 达到深度限制时会发生什么?您是否获得最大递归限制? stackoverflow.com/questions/3323001/…
  • @HåkenLid 当我达到深度限制时,Scrapy 会忽略在该深度可能产生的任何进一步请求。我没有得到递归限制。

标签: python scrapy


【解决方案1】:

我最终通过创建一个将深度重置为 0 的中间件解决了这个问题。我在请求中传递了一个元参数,其中“reset_depth”为 True,中间件根据该参数更改请求的深度参数。

class DepthResetMiddleware(object):

    def process_spider_output(self, response, result, spider):
        for r in result:
            if not isinstance(r, Request):
                yield r
                continue
            if (
                "depth" in r.meta
                and "reset_depth" in r.meta
                and r.meta["reset_depth"]
            ):
                r.meta["depth"] = 0
            yield r

请求应该以某种方式从蜘蛛产生,如下所示:

yield Request(url, meta={"reset_depth": True})

然后将中间件添加到您的设置中。顺序很重要,因为这个中间件应该在 DepthMiddleware 之前执行。由于默认的 DepthMiddleware 顺序是 900,因此我在 CrawlerProcess 中将 DepthResetMiddleware 的顺序设置为 850,如下所示:

"SPIDER_MIDDLEWARES": {
    "patchfinder.middlewares.DepthResetMiddleware": 850
}

不知道这是否是最好的解决方案,但它有效。另一种选择可能是扩展 DepthMiddleware 并在其中添加此功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多