加快网络刮刀

时间:2013-06-10 17:42:33

标签: python performance web-scraping scrapy scrapy-spider

我使用scrapy使用非常简单的网络抓取工具抓取23770个网页。我对scrapy甚至python都很陌生,但设法编写了一个完成这项工作的蜘蛛。然而,它确实很慢(爬行23770页需要大约28个小时)。

我查看了scrapy网页和邮件列表以及stackoverflow,但我似乎无法找到编写快速抓取工具的一般性建议,这对于初学者来说是可以理解的。也许我的问题不是蜘蛛本身,而是我运行它的方式。欢迎所有建议!

如果需要,我已在下面列出了我的代码。

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item, Field
import re

class Sale(Item):
    Adresse = Field()
    Pris = Field()
    Salgsdato = Field()
    SalgsType = Field()
    KvmPris = Field()
    Rum = Field()
    Postnummer = Field()
    Boligtype = Field()
    Kvm = Field()
    Bygget = Field()

class HouseSpider(BaseSpider):
    name = 'House'
    allowed_domains = ["http://boliga.dk/"]
    start_urls = ['http://www.boliga.dk/salg/resultater?so=1&type=Villa&type=Ejerlejlighed&type=R%%C3%%A6kkehus&kom=&amt=&fraPostnr=&tilPostnr=&iPostnr=&gade=&min=&max=&byggetMin=&byggetMax=&minRooms=&maxRooms=&minSize=&maxSize=&minsaledate=1992&maxsaledate=today&kode=&p=%d' %n for n in xrange(1, 23770, 1)]

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select("id('searchresult')/tr")
        items = []      
        for site in sites:
            item = Sale()
            item['Adresse'] = site.select("td[1]/a[1]/text()").extract()
            item['Pris'] = site.select("td[2]/text()").extract()
            item['Salgsdato'] = site.select("td[3]/text()").extract()
            Temp = site.select("td[4]/text()").extract()
            Temp = Temp[0]
            m = re.search('\r\n\t\t\t\t\t(.+?)\r\n\t\t\t\t', Temp)
            if m:
                found = m.group(1)
                item['SalgsType'] = found
            else:
                item['SalgsType'] = Temp
            item['KvmPris'] = site.select("td[5]/text()").extract()
            item['Rum'] = site.select("td[6]/text()").extract()
            item['Postnummer'] = site.select("td[7]/text()").extract()
            item['Boligtype'] = site.select("td[8]/text()").extract()
            item['Kvm'] = site.select("td[9]/text()").extract()
            item['Bygget'] = site.select("td[10]/text()").extract()
            items.append(item)
        return items

谢谢!

4 个答案:

答案 0 :(得分:26)

以下是一系列要尝试的事项:

  • 使用最新的scrapy版本(如果尚未使用)
  • 检查是否使用了非标准中间件
  • 尝试增加CONCURRENT_REQUESTS_PER_DOMAINCONCURRENT_REQUESTS设置(docs
  • 关闭记录LOG_ENABLED = Falsedocs
  • 在循环中尝试yield项目,而不是将项目收集到items列表中并返回
  • 使用本地缓存DNS(请参阅this thread
  • 检查此网站是否使用下载阈值并限制下载速度(请参阅this thread
  • 在蜘蛛运行期间记录cpu和内存使用情况 - 看看是否有任何问题
  • 尝试在scrapyd服务
  • 下运行相同的蜘蛛
  • 查看grequests + lxml是否会表现更好(询问您是否需要任何帮助来实施此解决方案)
  • 尝试在Scrapy上投放pypy,请参阅Running Scrapy on PyPy

希望有所帮助。

答案 1 :(得分:5)

查看您的代码,我会说大部分时间都花在网络请求上,而不是处理响应。 @alecxe提供的所有提示都在他的回答中提供,但我建议HTTPCACHE_ENABLED设置,因为它会缓存请求并避免再次执行。它将有助于跟踪爬网甚至离线开发。请参阅文档中的更多信息:http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#module-scrapy.contrib.downloadermiddleware.httpcache

答案 2 :(得分:0)

我还使用优化的C#进行网页报废,最终导致CPU绑定,所以我将切换到C.

解析HTML会破坏CPU数据缓存,并且非常确定您的CPU根本不使用SSE 4.2,因为您只能使用C / C ++访问此功能。

如果你进行数学计算,你很快就会受到计算限制但不受内存限制。

答案 3 :(得分:0)

一种加快抓取速度的解决方法是适当配置start_urls

例如,如果我们的目标数据位于文档编号范围为http://apps.webofknowledge.com/doc=11的{​​{1}}中,则可以按以下方式配置1000

start_urls

通过这种方式,请求将从 start_urls = [ "http://apps.webofknowledge.com/doc=250", "http://apps.webofknowledge.com/doc=750", ] 开始到250,同时从251,249750,因此与{{1} }。