【问题标题】:Scrapy - Spider crawls duplicate urlsScrapy - Spider 抓取重复的网址
【发布时间】:2013-02-12 19:57:26
【问题描述】:

我正在抓取一个搜索结果页面,并从同一页面中抓取标题和链接信息。作为一个搜索页面,我也有指向下一页的链接,这是我在 SgmlLinkExtractor 中指定允许的。

问题的描述是,在第 1 页,我找到了 Page2 和 Page3 的链接来爬取,它做得很好。但是当它爬到第 2 页时,它又会有指向 Page1(上一页)和 Page3(下一页)的链接。所以它再次爬取 Page1 与引荐来源为 Page2 并进入循环。

我使用的scrapy版本是0.17。

我在网上搜索了答案并尝试了以下方法, 1)

Rule(SgmlLinkExtractor(allow=("ref=sr_pg_*")), callback="parse_items_1", unique= True, follow= True),

但唯一的命令未被识别为有效参数。

2) 我试图在设置中将默认过滤器指定为 DUPEFILTER_CLASS = RFPDupeFilter

    DUPEFILTER_CLASS = RFPDupeFilter
NameError: name 'RFPDupeFilter' is not defined

3)我也尝试过自定义过滤器,我在网上找到了sn-p,但不太了解它。代码如下。访问 id 和状态被捕获,但它不能识别已爬取的页面。

注意:sn-p 是从网上复制的,我没有太多细节,

from scrapy import log
from scrapy.http import Request
from scrapy.item import BaseItem
from scrapy.utils.request import request_fingerprint
from Amaze.items import AmazeItem

class IgnoreVisitedItems(object):
    FILTER_VISITED = 'filter_visited'
    VISITED_ID = 'visited_id'
    CONTEXT_KEY = 'visited_ids'

    def process_spider_output(self, response, result, spider):
        context = getattr(spider, 'context', {})
        visited_ids = context.setdefault(self.CONTEXT_KEY, {})
        ret = []
        for x in result:
            visited = False
            if isinstance(x, Request):
                if self.FILTER_VISITED in x.meta:
                    visit_id = self._visited_id(x)
                    if visit_id in visited_ids:
                        log.msg("Ignoring already visited: %s" % x.url,
                                level=log.INFO, spider=spider)
                        visited = True
            elif isinstance(x, BaseItem):
                visit_id = self._visited_id(response.request)
                if visit_id:
                    visited_ids[visit_id] = True
                    x['visit_id'] = visit_id
                    x['visit_status'] = 'new'
            if visited:
                ret.append(MyItem(visit_id=visit_id, visit_status='old'))
            else:
                ret.append(x)
        return ret

    def _visited_id(self, request):
        return request.meta.get(self.VISITED_ID) or request_fingerprint(request)

我的目的是让蜘蛛本身忽略已经抓取的网页,而不是将抓取的页面放在列表中,并在每次抓取或不抓取页面时与列表匹配。

请对此有任何想法。

【问题讨论】:

  • 你能发布一些示例网址吗?
  • 这是我要抓取的页面,amazon.com/s/…,我允许的链接是“allow=("ref=sr_pg_*")”,因此它与第 2 页的链接和3.有没有办法只选择指定条件的1个链接。如果需要更多详细信息,请告诉我。
  • 在进行一些更改以添加导入库 from scrapy.dupefilter import RFPDupeFilter from scrapy.utils.request import request_fingerprint 后,RFPDupefileter 被识别,但抓取重复过滤器的问题不起作用。另外,我已经更正了链接提取器中“唯一”参数的声明,但即使是重复也没有帮助。

标签: python scrapy web-crawler


【解决方案1】:

您没有看到您的 Spider 的代码示例,但是,您可能在调用 Request 方法时传递了参数 dont_filter = True。尝试明确指定Request(dont_filter=False)。这向 Spider 指出,他不必重复相同的请求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多