糟糕的性能改进和内存消耗

2024-10-03 23:18:15 发布

您现在位置:Python中文网/ 问答频道 /正文

服务器

  • 6 GB内存
  • 4核Intel Xeon 2.60GHz
  • 32个并发请求
  • CSV格式的1m URL
  • 下游700 Mbit/s
  • 96%内存消耗

在调试模式打开的情况下,大约400000个url之后,刮取停止,很可能是因为服务器内存不足。 没有调试模式,它需要5天,这是相当慢的我和 它需要更多的记忆(96%)

欢迎任何提示:)

import scrapy
import csv

def get_urls_from_csv():
    with open('data.csv', newline='') as csv_file:
        data = csv.reader(csv_file, delimiter=',')
        scrapurls = []
        for row in data:
            scrapurls.append("http://"+row[2])
        return scrapurls

class rssitem(scrapy.Item):
    sourceurl = scrapy.Field()
    rssurl = scrapy.Field()


class RssparserSpider(scrapy.Spider):
    name = "rssspider"
    allowed_domains = ["*"]
    start_urls = ()

    def start_requests(self):
        return [scrapy.http.Request(url=start_url) for start_url in get_urls_from_csv()]

    def parse(self, response):
        res = response.xpath('//link[@type="application/rss+xml"]/@href')
        for sel in res:
            item = rssitem()
            item['sourceurl']=response.url
            item['rssurl']=sel.extract()
            yield item

        pass

Tags: csv内存in服务器urlfordataresponse
2条回答
import csv
from collections import namedtuple

import scrapy


def get_urls_from_csv():
    with open('data.csv', newline='') as csv_file:
        data = csv.reader(csv_file, delimiter=',')
        for row in data:
            yield row[2]


# if you can use something else than scrapy
rssitem = namedtuple('rssitem', 'sourceurl rssurl')


class RssparserSpider(scrapy.Spider):
    name = "rssspider"
    allowed_domains = ["*"]
    start_urls = ()

    def start_requests(self): # remember that it returns generator
        for start_url in get_urls_from_csv():
            yield scrapy.http.Request(url="http://{}".format(start_url))

    def parse(self, response):
        res = response.xpath('//link[@type="application/rss+xml"]/@href')
        for sel in res:
            yield rssitem(response.url, sel.extract())
        pass

正如我所说的,您应该使用generators来避免在内存中创建对象列表(what-does-the-yield-keyword-do-in-python),使用生成器对象是惰性创建的,这样就不会同时在内存中创建所有对象的大列表:

def get_urls_from_csv():
    with open('data.csv', newline='') as csv_file:
        data = csv.reader(csv_file, delimiter=',')
        for row in data:
            yield "http://"+row[2]) # yield each url lazily


class rssitem(scrapy.Item):
    sourceurl = scrapy.Field()
    rssurl = scrapy.Field()


class RssparserSpider(scrapy.Spider):
    name = "rssspider"
    allowed_domains = ["*"]
    start_urls = ()

    def start_requests(self):
        # return a generator expresion.
        return (scrapy.http.Request(url=start_url) for start_url in get_urls_from_csv())

    def parse(self, response):
        res = response.xpath('//link[@type="application/rss+xml"]/@href')
        for sel in res:
            item = rssitem()
            item['sourceurl']=response.url
            item['rssurl']=sel.extract()
            yield item

就性能而言,Broad Crawls上的文档建议尝试increase concurrency是:

Concurrency是并行处理的请求数。有全局限制和每个域限制。 Scrapy中默认的全局并发限制不适合并行爬网多个不同的域,因此您需要增加它。增加多少将取决于你的爬虫将有多少CPU可用。一个好的起点是100,但是找到这个问题的最好方法是做一些试验,并确定你的废进程在什么样的并发性下会得到CPU的限制。为了获得最佳性能,您应该选择CPU使用率在80-90%之间的并发。

要提高全局并发性,请执行以下操作:

^{pr2}$

强调我的。在

还有Increase Twisted IO thread pool maximum size

目前Scrapy使用线程池以阻塞方式进行DNS解析。在更高的并发级别下,爬网可能会很慢,甚至会导致DNS解析程序超时。增加处理DNS查询的线程数的可能解决方案。DNS队列的处理速度将更快,从而加快连接的建立和总体爬网。

要增加最大线程池大小,请使用:

 REACTOR_THREADPOOL_MAXSIZE = 20

相关问题 更多 >