Scrapy - 爬虫抓取重复链接
我正在爬取一个搜索结果页面,从中提取标题和链接信息。因为这是一个搜索页面,所以我也有指向下一页的链接,这些链接我已经在SgmlLinkExtractor中指定允许爬取。
问题描述是,在第一页,我找到了指向第二页和第三页的链接,爬取得很顺利。但是当它爬取第二页时,又发现了指向第一页(之前的页面)和第三页(下一页)的链接。所以它又爬取了第一页,这次的来源是第二页,结果就陷入了循环。
我使用的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) 我还尝试了一个自定义过滤器,我在网上找到的代码片段,但对它不是很了解。代码如下。访问ID和状态被捕获,但它并没有识别已经爬取过的页面。
注意:这个代码片段是从网上复制的,我对它没有太多细节。
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)
我的意图是让爬虫自己忽略已经爬取过的网页,而不是每次爬取时都要在一个列表中匹配这些已经爬取的页面。
请问对此有什么想法吗?
1 个回答
1
你没有看到你的小爬虫的代码示例,但可能在调用 Request
方法时,你传递了一个参数 dont_filter = True
。试着明确地写成 Request(dont_filter=False)
。这样可以告诉爬虫,它不需要重复相同的请求。