V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
drroot
V2EX  ›  问与答

爬虫: asyncio+aiohttp 比 scrapy 还快吗?

  •  1
     
  •   drroot · 2018-02-19 22:46:40 +08:00 · 6062 次点击
    这是一个创建于 2488 天前的主题,其中的信息可能已经有所发展或是发生改变。

    每天爬 1 百万网页,用 1000 个代理( 50%有效)

    获取的是 json 文件,把每个结果输出到同一个 csv 文件里

    对于异常或 timeout 的访问,希望自动尝试新代理,最多尝试三次

    asyncio+aiohttp 是否比 Scrapy 更快 也更稳定呢?

    第 1 条附言  ·  2018-02-20 10:30:12 +08:00
    因为所有 URLS 是已知的,所以不用去重

    需要在 7 个小时内爬完
    第 2 条附言  ·  2018-02-20 10:56:08 +08:00
    用的这台 VPS 只有 2GB 内存 现在用 concurrent.futures 的 multithreading,max_workers 多点就爆内存 OOM,设少点 7 小时跑不完任务
    14 条回复    2018-08-16 11:16:09 +08:00
    gouchaoer
        1
    gouchaoer  
       2018-02-19 23:58:25 +08:00 via Android
    首先 100w 数据量并不大,每个爬虫每 5s 访问一次的话只需要 65 个爬虫进程一天就能爬完 100w,假设我拿 200 个爬虫来爬,那这种程度的单机就能扛住,就阻塞的 requests 就 ok 了。。。so 大部分定制爬虫瓶颈不在 cpu
    gouchaoer
        2
    gouchaoer  
       2018-02-20 00:01:05 +08:00 via Android
    你输出到 csv 如何去重?结果需要保存到数据库,并且爬数据的时候去数据库看是否重复
    swirling
        3
    swirling  
       2018-02-20 10:20:04 +08:00
    @gouchaoer 从性能上分析得很好,我从另一个角度说两句. 对于 output 格式的统一处理, 如果你用 scrapy 是可以很容易切换文件或者是 database 的,只需要换 pipline. 对于 timeout 重试这些只需要配置就行了. 部署工具链一套全家桶, 我反正跑了快半年也没挂过. 你用 asyncio 要自己写的东西肯定更多. 除非你觉得你比别人聪明, 不然你出错的概率更大, 也更不稳定.
    gouchaoer
        4
    gouchaoer  
       2018-02-20 10:32:15 +08:00 via Android
    @swirling
    不是我太聪明,是大家把问题复杂化了,爬东西本身就是个简单的问题,scrapy 封装太厉害了,比如实现 lz 这个更换代理 3 次你 scrapy 怎么搞?去读文档写 hook 么?我手写的直接写逻辑就 ok 了。。。算了,反正你用起来爽就行
    drroot
        5
    drroot  
    OP
       2018-02-20 10:33:27 +08:00
    @gouchaoer 每条记录大小在 10KB 左右,所以 100 万网页,需要在 7 小时内下载 10GB 的数据
    drroot
        6
    drroot  
    OP
       2018-02-20 10:36:16 +08:00
    @swirling 现在是想先输出成 csv,以后从 csv 导入各种数据库再行处理,也很方便哒
    gouchaoer
        7
    gouchaoer  
       2018-02-20 10:39:52 +08:00 via Android
    @drroot 你不考虑爬虫只是考虑代理和带宽的话,用异步或者半协程的确能提高速度,go 和 php 甚至有 fullstack 的协程 httpclient,在低 cpu 下打满带宽,但是一般情况下搞爬虫的精力还在和反爬搏斗,你这种瓶颈在代理 ip 上,直接堆机器吧
    drroot
        8
    drroot  
    OP
       2018-02-20 10:47:20 +08:00
    @swirling Scrapy 有没办法把访问每个网址是否成功的状态返回,如果没有成功返回或者 timeout 或者有 exception,就把这个网址放入 pool,下次循环对这个 pool 里没有成功访问的网址重新运行?
    swirling
        9
    swirling  
       2018-02-20 10:53:59 +08:00
    https://github.com/aivarsk/scrapy-proxies
    直接撸个 middleware 上去. 如果觉得他不符合需求再自己写.
    gouchaoer
        10
    gouchaoer  
       2018-02-20 11:18:25 +08:00 via Android
    🙄看来我干了 2 年全职爬虫还是有积累的
    inflationaaron
        11
    inflationaaron  
       2018-02-20 23:45:18 +08:00
    这个还是看语言,我用 aiohttp + asyncio + uvloop 写的就是没有 Go 的多线程快。如果资源有限的话用手动管理内存可能更好一点?
    drroot
        12
    drroot  
    OP
       2018-02-22 14:46:15 +08:00
    @inflationaaron 相比 scrapy 呢?
    inflationaaron
        13
    inflationaaron  
       2018-02-22 23:29:25 +08:00
    @drroot 比 scrapy 简单,而且速度更快。说到底 scrapy 是用 Twisted 的,可以看看 uvloop 的 benchmark:

    https://magic.io/blog/uvloop-blazing-fast-python-networking/

    性能可以赶上单核 Go 了,但是没有办法利用多核就是硬伤。
    rocketman13
        14
    rocketman13  
       2018-08-16 11:16:09 +08:00
    你用 asyncio+aiohttp 遇到过什么坑吗?例如没有任何反爬措施的 api 会请求超时,同样的 api 如果用 request 就能随便拿到数据这种。。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2573 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:11 · PVG 23:11 · LAX 07:11 · JFK 10:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.