gpt4 book ai didi

python - 如何避免爬虫中的重复

转载 作者:太空宇宙 更新时间:2023-11-04 06:28:31 32 4
gpt4 key购买 nike

我使用 python 中的 scrapy 框架编写了一个爬虫来选择一些链接和元标记。然后爬取起始 url 并将数据以 JSON 编码格式写入文件。问题是当爬虫运行两个或者使用相同的起始 url 三次,文件中的数据会重复。为了避免这种情况,我在 scrapy 中使用了一个下载器中间件,它是这样的:http://snippets.scrapy.org/snippets/1/

我所做的是将上面的代码复制并粘贴到我的 scrapy 项目中的一个文件中,并通过添加以下行在 settings.py 文件中启用它:

SPIDER_MIDDLEWARES = {'a11ypi.removeDuplicates.IgnoreVisitedItems':560} 

其中“a11ypi.removeDuplicates.IgnoreVisitedItems”是类路径名称,最后我进入并修改了我的 items.py 文件并包含以下字段

visit_id = Field()  
visit_status = Field()

但这行不通,爬虫在运行两次时仍然产生相同的结果并将其附加到文件

我在我的 pipelines.py 文件中写入文件如下:

import json 

class AYpiPipeline(object):
def __init__(self):
self.file = open("a11ypi_dict.json","ab+")


# this method is called to process an item after it has been scraped.


def process_item(self, item, spider):
d = {}

i = 0
# Here we are iterating over the scraped items and creating a dictionary of dictionaries.
try:
while i<len(item["foruri"]):
d.setdefault(item["foruri"][i],{}).setdefault(item["rec"][i],{})[item["foruri_id"][i]] = item['thisurl'] + ":" +item["thisid"][i]
i+=1
except IndexError:
print "Index out of range"

json.dump(d,self.file)
return item

而我的爬虫代码如下:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from a11ypi.items import AYpiItem

class AYpiSpider(CrawlSpider):
name = "a11y.in"
allowed_domains = ["a11y.in"]

# This is the list of seed URLs to begin crawling with.
start_urls = ["http://www.a11y.in/a11ypi/idea/fire-hi.html"]

# This is the callback method, which is used for scraping specific data
def parse(self,response):
temp = []
hxs = HtmlXPathSelector(response)
item = AYpiItem()
wholeforuri = hxs.select("//@foruri").extract() # XPath to extract the foruri, which contains both the URL and id in foruri
for i in wholeforuri:
temp.append(i.rpartition(":"))

item["foruri"] = [i[0] for i in temp] # This contains the URL in foruri
item["foruri_id"] = [i.split(":")[-1] for i in wholeforuri] # This contains the id in foruri
item['thisurl'] = response.url
item["thisid"] = hxs.select("//@foruri/../@id").extract()
item["rec"] = hxs.select("//@foruri/../@rec").extract()
return item

请提出建议。

最佳答案

试着理解为什么要这样写代码段:

 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

请注意第 2 行,您实际上需要在 Request.meta 中输入一个名为 FILTER_VISITED 的键,以便中间件删除请求。原因是善意的,因为您访问过的每个 url 都将被跳过,如果您不这样做,您将根本没有要遍历的 url。因此,FILTER_VISITED 实际上允许您选择要跳过的 url 模式。如果您想跳过使用特定规则提取的链接,只需执行

Rule(SgmlLinkExtractor(allow=('url_regex1', 'url_regex2' )),  callback='my_callback', process_request = setVisitFilter)

def setVisitFilter(request):
request.meta['filter_visited'] = True
return request

P.S 我不知道它是否适用于 0.14 及更高版本,因为一些代码已更改以将蜘蛛上下文存储在 sqlite 数据库中。

关于python - 如何避免爬虫中的重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5553115/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com