2015-11-20 101 views
2

因此,我建立了一个scrapy蜘蛛爬过网站内的所有内部链接。但是,当我运行蜘蛛时,有一些网站的大部分网站与网站内容无关。例如,一个网站运行詹金斯,而我的蜘蛛花费大量时间浏览与网站无关的这些网页。防止scrapy蜘蛛爬行网站的一部分太长

一种方法是创建一个黑名单并添加一些路径,如詹金斯,但我想知道是否有更好的方式来处理这个问题。

class MappingItem(dict, BaseItem): 
    pass 

class WebsiteSpider(scrapy.Spider): 
    name = "Website" 

    def __init__(self): 
     item = MappingItem() 
     self.loader = ItemLoader(item) 
     self.filter_urls = list() 

    def start_requests(self): 
     filename = "filename.csv" 
     try: 
      with open(filename, 'r') as csv_file: 
       reader = csv.reader(csv_file) 
       header = next(reader) 
       for row in reader: 
        seed_url = row[1].strip() 
        base_url = urlparse(seed_url).netloc 
        self.filter_urls.append(base_url) 
        request = Request(seed_url, callback=self.parse_seed) 
        request.meta['base_url'] = base_url 

        yield request 
     except IOError: 
      raise CloseSpider("A list of websites are needed") 

    def parse_seed(self, response): 
     base_url = response.meta['base_url'] 
     # handle external redirect while still allowing internal redirect 
     if urlparse(response.url).netloc != base_url: 
      return 
     external_le = LinkExtractor(deny_domains=base_url) 
     external_links = external_le.extract_links(response) 
     for external_link in external_links: 
      if urlparse(external_link.url).netloc in self.filter_urls: 
       self.loader.add_value(base_url, external_link.url) 

     internal_le = LinkExtractor(allow_domains=base_url) 
     internal_links = internal_le.extract_links(response) 

     for internal_link in internal_links: 
      request = Request(internal_link.url, callback=self.parse_seed) 
      request.meta['base_url'] = base_url 
      request.meta['dont_redirect'] = True 
      yield request 
+0

您是否正在使用链接提取?显示您的蜘蛛代码的相关部分可能有助于在这里帮助。谢谢! – alecxe

回答

0

这听起来像链接提取的deny_domains说法是东西给你使用的域的“黑名单”,不遵循:

deny_domains(STR或列表) - 单个值或字符串列表 包含将不被考虑用于提取链接的域

+0

这似乎是一个解决方案,但问题是,即使在我面对蜘蛛大部分时间花费的这个“洼地”时,我也不得不手动添加所有形式的sink孔。 –

+0

我想过规避这种情况的一种方法是通过限制您可以在特定路径上进行的访问次数,但问题在于,如果内容稳定,可能会有太多的误报漏洞。例如,如果蜘蛛在www.website.com/jenkins/上花费了数千次请求,那么它应该终止,但是如果“www.website.com/articles/”和成千上万篇文章,蜘蛛应该发送因为它们是相关材料。我想我需要做的是找到某种模式,可以区分有用和无用的网页。 –

+0

@THISUSERNEEDSHELP明白了。你应该围绕它创建一些自定义逻辑 - 例如,有一个域优先级映射可以定义一个域的相关性和一个计数器字典('defaultdict(int)'我想),你会用它来计算按域访问。然后,您可以使用某种相关性来请求计数规则,以确定是否需要停止抓取特定域。这听起来像是你需要一个定制的中间件......只是一种感觉。 – alecxe