我编写了以下代码来抓取电子邮件地址(用于测试):
import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.selector import Selector
from crawler.items import EmailItem
class LinkExtractorSpider(CrawlSpider):
name = 'emailextractor'
start_urls = ['http://news.google.com']
rules = ( Rule (LinkExtractor(), callback='process_item', follow=True),)
def process_item(self, response):
refer = response.url
items = list()
for email in Selector(response).re("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"):
emailitem = EmailItem()
emailitem['email'] = email
emailitem['refer'] = refer
items.append(emailitem)
return items
不幸的是,似乎没有正确关闭对请求的引用,因为使用scrapy telnet控制台,请求的数量增加了5k / s。大约3分钟并刮掉1万页后,我的系统开始交换(8GB RAM)。任何人都知道这是怎么回事?我已经尝试删除引用并使用“复制”字符串
emailitem['email'] = ''.join(email)
没有成功。抓取后,将这些项目保存到BerkeleyDB中,以计数它们的出现(使用管道),因此之后应该删除引用。
返回一组项目和分别产生每个项目之间有什么区别?
编辑:
经过一段时间的调试后,我发现请求没有被释放,最终导致:
$> nc localhost 6023
>>> prefs()
Live References
Request 10344 oldest: 536s ago
>>> from scrapy.utils.trackref import get_oldest
>>> r = get_oldest('Request')
>>> r.url
<GET http://news.google.com>
实际上是起始网址。有人知道问题出在哪里吗?缺少对Request对象的引用在哪里?
编辑2:
在服务器(具有64GB RAM)上运行约12个小时后,使用的RAM约为16GB(使用ps,即使ps不是正确的工具)。问题是,自几个小时以来,已抓取的页面数明显减少,并且已抓取的项目数保持为0:
INFO: Crawled 122902 pages (at 82 pages/min), scraped 3354 items (at 0 items/min)
EDIT3:我做了objgraph分析,结果如下图所示(感谢@Artur Gaspar):
看来我没有影响力吗?
对我来说,最终的答案是将基于磁盘的队列与工作目录一起用作运行时参数。
这会将以下代码添加到settings.py中:
DEPTH_PRIORITY = 1
SCHEDULER_DISK_QUEUE = 'scrapy.squeue.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeue.FifoMemoryQueue'
之后,使用以下命令行启动搜寻器,使更改在给定目录中持久存在:
scrapy抓取{spidername} -s JOBDIR = crawls / {spidername}有关详细信息,请参见scrapy文档
这种方法的其他好处是,可以随时暂停和恢复爬网。我的蜘蛛现在运行超过11天,阻塞了约15GB内存(用于磁盘FIFO队列的文件缓存内存)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句