首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抓取内存错误(请求太多)Python2.7

抓取内存错误(请求太多)Python2.7
EN

Stack Overflow用户
提问于 2015-06-16 21:00:27
回答 2查看 1.3K关注 0票数 1

我一直在运行一个抓取爬虫在抓取一个大网站,我宁愿不提。我使用教程蜘蛛作为模板,然后创建了一系列启动请求并让它从那里爬行,使用如下所示:

代码语言:javascript
复制
def start_requests(self):
        f = open('zipcodes.csv', 'r')
        lines = f.readlines()
        for line in lines:
            zipcode = int(line)
            yield self.make_requests_from_url("http://www.example.com/directory/%05d" % zipcode)

首先,有超过10,000个这样的页面,然后这些队列中的每一个排列在一个相当大的目录上,其中还有几个页面要排队等等,而scrapy似乎喜欢保持“浅”,在内存中积累请求,而不是钻研它们,然后再备份。

这样做的结果是一个重复的大异常,结果如下:

代码语言:javascript
复制
  File "C:\Python27\lib\site-packages\scrapy\utils\defer.py", line 57, in <genexpr>
    work = (callable(elem, *args, **named) for elem in iterable)
--- <exception caught here> ---
  File "C:\Python27\lib\site-packages\scrapy\utils\defer.py", line 96, in iter_errback
    yield next(it)

.(更多的行).

代码语言:javascript
复制
  File "C:\Python27\lib\site-packages\scrapy\selector\lxmldocument.py", line 13, in _factory
    body = response.body_as_unicode().strip().encode('utf8') or '<html/>'
exceptions.MemoryError: 

很快,在一个爬虫需要几天的时间内,python可执行气球到1.8gigs和Scrapy的功能就不再起作用了(继续浪费我的代理使用费!)

有没有任何方法让Scrapy去排队、外化或迭代(我甚至不知道正确的单词)存储的请求,以防止这样的内存问题?

(我不太精通编程,除了拼凑我在这里或在文档中看到的东西,所以我没有能力排除引擎盖下的故障,可以说--经过几天的尝试和阅读,我也无法在W7上安装完整的python/django/scrapy作为64位。)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-17 03:00:40

您可以通过批处理您的urls,每次爬行器空转时只需要排队几个。这避免了大量请求在内存中排队。下面的示例只读取数据库/文件中的下一批urls,并将它们作为请求进行队列,直到所有先前的请求都已完成处理。

关于spider_idle信号的更多信息:http://doc.scrapy.org/en/latest/topics/signals.html#spider-idle

有关调试内存泄漏的更多信息:http://doc.scrapy.org/en/latest/topics/leaks.html

代码语言:javascript
复制
from scrapy import signals, Spider
from scrapy.xlib.pydispatch import dispatcher


class ExampleSpider(Spider):
    name = "example"
    start_urls = ['http://www.example.com/']

    def __init__(self, *args, **kwargs):
        super(ExampleSpider, self).__init__(*args, **kwargs)
        # connect the function to the spider_idle signal
        dispatcher.connect(self.queue_more_requests, signals.spider_idle)

    def queue_more_requests(self, spider):
        # this function will run everytime the spider is done processing
        # all requests/items (i.e. idle)

        # get the next urls from your database/file
        urls = self.get_urls_from_somewhere()

        # if there are no longer urls to be processed, do nothing and the
        # the spider will now finally close
        if not urls:
            return

        # iterate through the urls, create a request, then send them back to
        # the crawler, this will get the spider out of its idle state
        for url in urls:
            req = self.make_requests_from_url(url)
            self.crawler.engine.crawl(req, spider)

    def parse(self, response):
        pass
票数 1
EN

Stack Overflow用户

发布于 2015-06-16 21:07:12

当在整个互联网上递归链接时,您将无法达到关闭。您需要以某种方式限制递归。不幸的是,代码中没有显示您要这样做的部分。最简单的方法是为挂起的链接列表设置一个固定的大小来爬行,只是不要在列表中添加任何东西,直到它小于这个上限。更高级的解决方案将根据挂起链接在父页面中的周围上下文为其指定优先级,然后对挂起链接的排序、固定最大大小优先级列表进行排序。

但是,与其试图编辑或黑掉现有的代码,不如看看内置设置是否可以完成您想要的任务。有关参考,请参阅此文档页:http://doc.scrapy.org/en/latest/topics/settings.html。看起来,值为1或更多的DEPTH_LIMIT设置将限制您在起始页面上递归的深度。

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

https://stackoverflow.com/questions/30878104

复制
相关文章

相似问题

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