2016-07-23 99 views
0

我创建了一个非常缓慢的新Scrapy蜘蛛。它每秒只能抓取两页,而我创建的其他Scrapy抓取工具的抓取速度更快。缓慢的Scrapy刮刀的原因

我想知道它是什么可能导致此问题,以及如何解决这个问题。代码与其他蜘蛛并没有太大区别,我不确定它是否与问题有关,但如果您认为它可能涉及到,我会添加它。

事实上,我的印象是请求不是异步的。我从来没有遇到过这样的问题,我对Scrapy相当陌生。

编辑

这里的蜘蛛:

class DatamineSpider(scrapy.Spider): 
    name = "Datamine" 
    allowed_domains = ["domain.com"] 
    start_urls = (
     'http://www.example.com/en/search/results/smth/smth/r101/m2108m', 
    ) 

    def parse(self, response): 
     for href in response.css('.searchListing_details .search_listing_title .searchListing_title a::attr("href")'): 
      url = response.urljoin(href.extract()) 
      yield scrapy.Request(url, callback=self.parse_stuff) 
     next_page = response.css('.pagination .next a::attr("href")') 
     next_url = response.urljoin(next_page.extract()[0]) 
     yield scrapy.Request(next_url, callback=self.parse) 

    def parse_stuff(self, response): 
     item = Item() 
     item['value'] = float(response.xpath('//*[text()="Price" and not(@class)]/../../div[2]/span/text()').extract()[0].split(' ')[1].replace(',','')) 
     item['size'] = float(response.xpath('//*[text()="Area" and not(@class)]/../../div[2]/text()').extract()[0].split(' ')[0].replace(',', '.')) 
     try: 
      item['yep'] = float(response.xpath('//*[text()="yep" and not(@class)]/../../div[2]/text()').extract()[0]) 
     except IndexError: 
      print "NO YEP" 
     else: 
      yield item 
+0

有很多事情可能会导致这种情况。你能提供蜘蛛源和抓取日志吗?如果您正在运行unix系统,则可以执行scrapy crawl spider 2&1 spider.log',然后在此处发布该日志。 – Granitosaurus

+0

我加了蜘蛛,我会尽快添加日志,(我现在正在运行它)。当我看日志时,速度在45到80页/分钟之间。 ;( – AimiHat

+0

你可以尝试发现是代码是慢速分析代码,像https://github.com/rkern/line_profiler – Ceppo93

回答

1

只有两个可能的原因,因为你的蜘蛛表明你很小心/经历。

  1. 您的目标网站的响应时间是非常低的
  2. 每个页面都有1-2只上市的网页(您使用parse_stuff()解析的)。

极有可能后者是原因。响应时间为半秒是合理的。这意味着通过遵循分页(下一个)链接,您将实际上每秒抓取2个索引页。由于您正在浏览 - 我猜 - 作为单个域名,您的最大并发数将是〜min(CONCURRENT_REQUESTS, CONCURRENT_REQUESTS_PER_DOMAIN)。默认设置通常为8。但是,您将无法利用此并发性,因为您不会足够快地创建列表网址。如果.searchListing_details .search_listing_title .searchListing_title a::attr("href")表达式仅创建一个URL,则创建列表URL的速率仅为2 /秒,而要充分利用并发级别为8的下载器,则应该创建至少7个URL /索引页面。

唯一不错的解决方案是“索引”索引并开始爬行,例如,通过设置许多不重叠的多个类别start_urls。例如。您可能想要并行抓取电视机,洗衣机,立体声音响或任何其他类别。如果你有4个这样的类别,并且Scrapy每秒钟为他们的“下一个”按钮点击2次,那么你将创建8个列表页面/秒,粗略地说,你会更好地利用你的下载器。

P.S. next_page.extract()[0] == next_page.extract_first()

离线讨论后进行更新:是的......除了速度较慢(无论是由于节流还是由于其服务器容量),我没有在此网站上看到任何奇怪的现象。一些特定的技巧要走得更快。击中指数4倍那样快通过设置4 start_urls而不是1

start_urls = (
    'http://www.domain.com/en/search/results/smth/sale/r176/m3685m', 
    'http://www.domain.com/en/search/results/smth/smth/r176/m3685m/offset_200', 
    'http://www.domain.com/en/search/results/smth/smth/r176/m3685m/offset_400', 
    'http://www.domain.com/en/search/results/smth/smth/r176/m3685m/offset_600' 
) 

然后使用更高的并发,以允许沿平行于装载多个URL。基本上通过将其设置为一个很大的值来“去激活”CONCURRENT_REQUESTS_PER_DOMAIN,例如, 1000,然后通过将CONCURRENT_REQUESTS设置为30来调整并发性。默认情况下,并发性会受到CONCURRENT_REQUESTS_PER_DOMAIN至8的限制,例如,您的情况下,列表页面的响应时间大于1.2秒,意味着每个页面最多有6个列表页面第二次爬行速度。所以打电话给你的蜘蛛是这样的:

scrapy crawl MySpider -s CONCURRENT_REQUESTS_PER_DOMAIN=1000 -s CONCURRENT_REQUESTS=30 

它应该会做得更好。

还有一件事。我从您的目标网站观察到,您可以从索引页面中获取所需的全部信息,包括Price,Areayep,而无需“点击”任何列表页面。由于您不需要使用for href...循环下载所有这些列表页面,因此这会立即提升10倍的爬网速度。只是从索引页面解析列表。

+0

谢谢你长期和详细的答案。每个页面有大约10个列表页面,蜘蛛仍然设法达到每分钟1页的速度。网站本身可能会限制我的请求吗?我找不到合理的解释 – AimiHat