V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Yingruoyuan
V2EX  ›  Python

scrapy 下载图片到 4w 张左右总是会卡住

  •  
  •   Yingruoyuan · 2017-06-03 11:30:10 +08:00 · 4445 次点击
    这是一个创建于 2740 天前的主题,其中的信息可能已经有所发展或是发生改变。

    已经从本地直接获取图片 url,大概有 20w 个左右,在下载到 4w 左右 scrapy 总是卡住,开始以为是内存泄漏,后来检测内存和 cpu 使用率,在卡住的时候并没有发现异常,下载部分代码如下:

    def parse(self, response):
        //get local list_img_urls
        item = DownloaderItem()
        item['image_urls'] = list_img_urls
        yield item
    

    有人遇到过这种情况吗?望不吝相助

    15 条回复    2017-06-08 12:52:23 +08:00
    yangxin0
        1
    yangxin0  
       2017-06-03 12:43:55 +08:00   ❤️ 1
    scrapy 的设计是 spider 是去爬取 HTML 页面的,然后转换成 Item, 然后通过 pipeline 去下载 item 关联的照片。 我每天下载 150 万张照片无压力。
    Yc1992
        2
    Yc1992  
       2017-06-03 12:50:03 +08:00 via Android
    去重的部分在内存里,太多就会缓存到磁盘,那就慢了
    ooh
        3
    ooh  
       2017-06-03 12:52:00 +08:00
    图片下载应该是 ImagesPipeline ?
    rabbbit
        4
    rabbbit  
       2017-06-03 13:26:30 +08:00
    DOWNLOAD_TIMEOUT 和 CONCURRENT_REQUESTS 怎么设置的,
    是不是无响应的链接超过并发数限制了?
    imn1
        5
    imn1  
       2017-06-03 13:33:53 +08:00
    抓到两个集图的
    Yingruoyuan
        6
    Yingruoyuan  
    OP
       2017-06-03 19:49:03 +08:00
    @Yc1992 我是在空目录下重新下载的,img_url 里一般也不会有重复的

    @ooh 是的,是用的继承 ImagesPipeline 的方法
    @rabbbit DOWNLOAD_TIMEOUT = 30,CONCURRENT_REQUESTS 这个用的默认的,应该是 8 个吧
    Yingruoyuan
        7
    Yingruoyuan  
    OP
       2017-06-03 20:38:10 +08:00
    @rabbbit 刚才是我看错了,CONCURRENT_REQUESTS 默认的是 16 个,我尝试了把 RETRY_ENABLED = False,并且缩短了 download_timeout,但是并没有明显改善,但是我发现虽然 top 监控的内存占用率并没有提高,但是在卡住的那段时间里,输入命令等会变得很卡,我在找是不是和服务器性能哪里有关的原因导致的
    litter123
        8
    litter123  
       2017-06-03 20:59:48 +08:00
    @Yingruoyuan 查看连接数,netstat -an
    Yc1992
        9
    Yc1992  
       2017-06-03 22:11:40 +08:00
    @Yingruoyuan scrapy 为了去重,会把 url 缓存在内存中,超过一定数量,就只能写磁盘了,那时候 io 超高就卡死了,这是我遇到过的情况。
    Yingruoyuan
        10
    Yingruoyuan  
    OP
       2017-06-04 15:29:50 +08:00
    @litter123 我对 netstat 命令不大熟悉,可以给个提示应该怎么查看 scrapy 的异常连接吗?
    @Yc1992 哦,这种情况,我以前没有遇到过,请教下这种情况是怎么去 debug 呢?
    Yc1992
        11
    Yc1992  
       2017-06-04 16:50:58 +08:00
    @Yingruoyuan 看 io,看内存占用
    zsz
        12
    zsz  
       2017-06-04 18:06:42 +08:00
    @Yingruoyuan

    仔细检查进程资源占用情况

    top: 看 cpu,内存
    iotop,iostat:看磁盘 io 情况
    nmon:看系统网络资源情况
    nload:看网卡流量情况
    ss,netstat:看网络连接


    加我们的群问效率高些,一群工程师组建的面向初学者的
    Python Linux 学习群,qq 群号:278529278,
    Php Linux 学习群,qq 群号:476648701,
    非商业性质,拒绝广告,只接收真正想学这方面技术的朋友,交流学习,申请请说明来自 v2ex
    Yingruoyuan
        13
    Yingruoyuan  
    OP
       2017-06-04 21:49:44 +08:00
    @Yc1992 好的,谢谢,我去检查下 io
    @zsz 谢谢
    Yingruoyuan
        14
    Yingruoyuan  
    OP
       2017-06-05 16:05:47 +08:00
    @all,
    感谢各位提供帮助,问题应该还是出在内存上,由于我是可以直接拿到那几十万的 url 的,这些请求会进入到在 scrapy 的请求队列中,占用内存,直至最后服务器内存不够 down 掉;
    我在网上查了下资料,scrapy 的调度器来控制队列,但是似乎不 hack 源码没有办法控制调度器对队列的操作;
    最后我的解决方法是在数据库就把数据切片,切成 2w 套循环,就不会出现内存不够的问题了;
    希望后来的大神有更优雅的方法可以指教。我会持续关注这个问题
    noobpythoner
        15
    noobpythoner  
       2017-06-08 12:52:23 +08:00
    可以使用 scrapy_redis 来完成,所有的去重都是通过 redis 来完成的,还能够做到状态保持,如果需要可以实现分布式,redis 的内容类似下面,
    redis > keys *
    1) "***:dupefilter"
    2) "***:items"
    3) "***:requests"

    或者可以迭代的读取数据库的内容,下一次请求之前从内存中删除上一次的请求地址,类似 https://www.ibm.com/developerworks/cn/xml/x-hiperfparse/
    这个方法我自己没有试过,但是应该是可行的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1520 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:56 · PVG 07:56 · LAX 15:56 · JFK 18:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.