首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免爬虫中的重复

如何避免爬虫中的重复
EN

Stack Overflow用户
提问于 2011-04-05 22:02:21
回答 1查看 1.9K关注 0票数 2

我用python中的scrapy框架编写了一个爬虫来选择一些链接和元tags.It,然后爬行起始urls,并将数据以JSON编码的格式写入到file.The上。问题是,当爬虫使用相同的起始urls运行两三次时,文件中的数据会被复制.To避免这一点我使用了scrapy中的一个下载中间件,即:http://snippets.scrapy.org/snippets/1/

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

代码语言:javascript
复制
SPIDER_MIDDLEWARES = {'a11ypi.removeDuplicates.IgnoreVisitedItems':560} 

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

代码语言:javascript
复制
visit_id = Field()  
visit_status = Field()

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

我对pipelines.py文件中的文件进行了写入,如下所示:

代码语言:javascript
复制
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

我的爬虫代码如下:

代码语言:javascript
复制
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  

请告诉我该怎么做。

EN

回答 1

Stack Overflow用户

发布于 2012-01-16 14:54:20

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

代码语言:javascript
复制
 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模式。如果您想跳过使用特定规则提取的链接,只需执行

代码语言:javascript
复制
Rule(SgmlLinkExtractor(allow=('url_regex1', 'url_regex2' )),  callback='my_callback', process_request = setVisitFilter)

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

另外,我不知道它是否适用于0.14和更高版本,因为在sqlite db中存储爬行器上下文的一些代码已经更改。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5553115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档