(请教)如何提高爬虫的效率/采集速度 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Nick2VIPUser
V2EX    程序员

(请教)如何提高爬虫的效率/采集速度

  •  1
     
  •   Nick2VIPUser
    nickliqian 2018-01-04 11:55:55 +08:00 11421 次点击
    这是一个创建于 2838 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近做了一个爬虫任务,大概需要采集百万级的页面。 使用如下技术:

    python3 requests xpath(解析) 多线程(threading) 代理 ip 池(95%有效,10 次 /1s 最多) redis(请求队列, 去重) mysql(储存) 

    同时做好容错处理(重连)/反爬机制应对。 经过几次测试:控制

     [线程数量] [进程数量] [重连等待时间] [报错等待时间] 

    得出一组每分钟采集最多数量的方案。 似乎遇到了瓶颈,此时不知道如何去优化采集速度。 没有想到的等会补充。。。 请教有经验的大神指点一下思路!谢谢各位了!!!

    第 1 条附言    2018-01-04 14:42:31 +08:00
    回复太快被限制 1800s 了。
    珍惜附言机会,这里补充一下:

    1. 当前方案的问题主要来自
    采集速度并不理想,按照现行速度,使用一台云主机,带宽固定
    每天可能只有 6 ~ 8 万条左右,爬完几百万条可能需要 2~3 个月
    在不增加物理设备和额外带宽的前提下希望尽可能从技术 /代码上提高采集速度

    2. 目标站反爬措施敏感。在这块做好容错处理和延时,也会使程序耗费额外一定时间。
    经过使用不同的延时策略,发现延时过低也会使得采集速度变慢。

    3. 准备尝试一下使用异步网络请求模块,对比采集速度。
    51 条回复    2018-01-05 10:54:36 +08:00
    ilovebaicai
        1
    ilovebaicai  
       2018-01-04 11:59:04 +08:00   1
    Scrpy+redis 是一个选择。![scrapy-redis]( https://github.com/rmax/scrapy-redis)
    ilovebaicai
        2
    ilovebaicai  
       2018-01-04 12:00:06 +08:00   1
    抱歉,手抖,少打了个 a。
    wzwwzw
        3
    wzwwzw  
       2018-01-04 12:03:58 +08:00   1
    如果不用 scrapy 的话,就用
    - aiohttp
    - asyncio
    - aiosocks
    - Pool
    毕竟爬虫大部分时间都是在等待请求,所以异步应该会快很多。

    数量多的话还是推荐 scrapy ,分布式 scrapy-redis .
    exiaohao
        4
    exiaohao  
       2018-01-04 12:06:35 +08:00   1
    把采集任务丢给 celery 处理
    dhcn
        5
    dhcn  
       2018-01-04 12:41:29 +08:00   1
    pyspider,帮你完成包括人物分发在内的大多数技术基础设施工作
    so1n
        6
    so1n  
       2018-01-04 13:45:17 +08:00   1
    可以改用进程+协程
    zhchyu999
        7
    zhchyu999  
       2018-01-04 14:00:14 +08:00   1
    难道没人吐槽“代理 ip 池(95%有效,10 次 /1s 最多)”这个么
    BiggerLonger
        8
    BiggerLonger  
       2018-01-04 14:03:45 +08:00   1
    grequests
    harker
        9
    harker  
       2018-01-04 14:13:31 +08:00
    当前方案有问题么?百万级应该还能应付吧
    Nick2VIPUser
        10
    Nick2VIPUser  
    OP
       2018-01-04 14:17:18 +08:00
    @ilovebaicai
    @wzwwzw
    非常感谢,我尝试分别用 scrapy 和 async/await 做一下测试,然后再对比一下效率!
    qsnow6
        11
    qsnow6  
       2018-01-04 14:18:20 +08:00   1
    百万级应该没啥问题啊,大部分时间都是在网络耗时上面。
    不过,切换线程是有开销的,如果想进一步提升性能的话,建议用异步 or 协程。
    asuraa
        12
    asuraa  
       2018-01-04 14:19:12 +08:00   1
    百万级别重要的我觉得是

    1. 代理
    2. 断点续传
    3. 非阻塞多线程
    asuraa
        13
    asuraa  
       2018-01-04 14:19:53 +08:00   1
    Nick2VIPUser
        14
    Nick2VIPUser  
    OP
       2018-01-04 14:20:47 +08:00
    @exiaohao
    @so1n
    实际上我才使用十几个线程并发,cpu 资源远远够用,感觉可能是并发请求量或者是带宽的问题。
    Nick2VIPUser
        15
    Nick2VIPUser  
    OP
       2018-01-04 14:21:26 +08:00
    @dhcn
    这个框架没用使用过,会考虑了解一下特性以作比较!谢谢!
    Nick2VIPUser
        16
    Nick2VIPUser  
    OP
       2018-01-04 14:23:06 +08:00
    @BiggerLonger
    requests 换为 frequests 的话代码可能会变动比较大吧?刚刚只是粗略的看了一下 frequests 的 demo。
    Nick2VIPUser
        17
    Nick2VIPUser  
    OP
       2018-01-04 14:25:17 +08:00
    @qsnow6
    谢谢您,主要想提升采集速度,测试过 10/15/20 个线程的采集速度,结果发现 10 个线程的采集速度是最快的,非常困惑。这里每次请求都使用不同的经过测试的代理 IP,不知道是不是带宽限制导致。
    MontagePa
        18
    MontagePa  
       2018-01-04 14:25:43 +08:00   1
    celery 这个,然后你再多线程,考虑好去重就行。
    qsnow6
        19
    qsnow6  
       2018-01-04 14:28:05 +08:00   2
    @Nick2VIPUser 不是带宽限制,应该是切换线程的问题;

    多线程跑的话,一般情况下 10-12 左右是最快的,更增加更多的线程速度反而会下降。
    liupanhi
        20
    liupanhi  
       2018-01-04 14:29:23 +08:00   1
    @wzwwzw 长见识了,这么多好东西!
    NxnXgpuPSfsIT
        21
    NxnXgpuPSfsIT  
       2018-01-04 14:37:40 +08:00   1
    @Nick2VIPUser 可以试试 Trip, 替换 requests 比较方便,github.com/littlecodersh/trip
    急用的话可以直接 gevent 碰碰运气。
    qsnow6
        22
    qsnow6  
       2018-01-04 14:55:13 +08:00   1
    给个参考值,scrapy 单进程可以达到 7200 pages/min
    lhx2008
        23
    lhx2008  
       2018-01-04 15:02:50 +08:00 via Android   1
    每天 6-8 万就是每秒才爬 1 个,开了 10 个线程的话就是平均一个线程 10s 爬一条,这也太不理想了吧,每个线程 1s 爬一条,一天就 80 万了
    bazingaterry
        24
    bazingaterry  
       2018-01-04 15:06:43 +08:00   1
    上 scrapy,而且掏代理池吧
    2ME
        25
    2ME  
       2018-01-04 15:07:31 +08:00   1
    你服务器如果不是小水管的话 你爬的是大文本吗? 大文本的话主要是 IO 影响效率 和线程关系并不大 还有你 1 条记录需要爬取几个页面 以及你的 IP 池质量如何 如果是 1 个页面并且爬取目标不是大文本,ip 池质量优异的话 这个速度可能慢了点 如果你为了对抗反爬虫 sleep 的时间比较久还是正常的
    Zzzzzzzzz
        26
    Zzzzzzzzz  
       2018-01-04 15:09:10 +08:00   1
    铺节点+队列+代理池, 问题是你得考虑下目标站能不能扛住你的 CC
    windfarer
        27
    windfarer  
       2018-01-04 15:10:35 +08:00   1
    百万级又不多,单机 scrapy 都够用了吧,主要代理要好
    Nick2VIPUser
        28
    Nick2VIPUser  
    OP
       2018-01-04 16:35:56 +08:00
    @zhchyu999
    这个为什么会被吐槽呀?公司有自己的代理池,但是数量较少;目标站点反爬策略比较敏感,所以使用付费的代理 IP 池,每次请求都会使用不同的 IP。
    Nick2VIPUser
        29
    Nick2VIPUser  
    OP
       2018-01-04 16:37:43 +08:00
    @qsnow6 不知道是不是线程一多了网络堵塞导致的采集速度过慢。
    Nick2VIPUser
        30
    Nick2VIPUser  
    OP
       2018-01-04 16:39:18 +08:00
    @luodaoyi
    代理 /断点续爬 /去重都做了,非阻塞的意思就是用协程或是异步?我去看看您发的链接 谢谢
    Nick2VIPUser
        31
    Nick2VIPUser  
    OP
       2018-01-04 16:58:54 +08:00
    @qsnow6
    @lhx2008
    @bazingaterry
    这个网站产生的详情页面的 url 和 cookie 有效期都很短,
    针对同一个 cookie 在短时间内高频率(大概是小于 1 次 /1s )的访问会立即失效
    大概是用来区分是否是机器人

    其实为什么每秒才爬一个,是因为对于 10 个线程每个线程都做了延时。每个线程获得一个新的 cookie 后每次请求都会间隔 3 秒,否则就会大量的报异常。这样的话,整体来说最优的情况每秒也只发出了 3 个请求,还没算上`去重入库解析异常处理`的时间。

    现在思路也比较清晰,就是提高并发量,尝试加了线程和进程,并没有效果。
    所以在研究把异步网络加上来。
    Nick2VIPUser
        32
    Nick2VIPUser  
    OP
       2018-01-04 17:14:34 +08:00
    @2ME 除了 sleep,还设置了 Connect time out 和 Read time out ( Proxy Connect time out 异常较少),同时也发现 Read time out 频繁发生,是否是从代理 ip 读取数据的时候超时,也就意味代理发送请求失败或者回传给本地失败?
    2ME
        33
    2ME  
       2018-01-04 17:44:33 +08:00   1
    @Nick2VIPUser 那就是你代理 ip 质量太差了 加钱数据可及 readtimeout 频繁 每天抓 6-8 万很正常了
    2ME
        34
    2ME  
       2018-01-04 17:48:00 +08:00   1
    @Nick2VIPUser 你 debug 一下基本就会发现绝大多数时间都浪费在超时了 即使是小水管都够呛能跑满带宽
    gouchaoer
        35
    gouchaoer  
       2018-01-04 17:54:08 +08:00   1
    第一代理 ip 不够
    gouchaoer
        36
    gouchaoer  
       2018-01-04 17:54:43 +08:00   1
    第一次看到爬虫自己是瓶颈的,大家都是怕爬坏了别人
    Nick2VIPUser
        37
    Nick2VIPUser  
    OP
       2018-01-04 18:07:54 +08:00
    @Zzzzzzzzz
    @windfarer
    目前还没有用 scrapy,并发太高,怕抓回来一堆异常。也在慢慢的加并发量,尽量不给网站造成太大压力。
    Nick2VIPUser
        38
    Nick2VIPUser  
    OP
       2018-01-04 18:09:32 +08:00
    @2ME 有道理,我增加额外的 ip 代理测试一下,感谢!
    Nick2VIPUser
        39
    Nick2VIPUser  
    OP
       2018-01-04 18:11:23 +08:00
    @gouchaoer 硬性条件没有提升起来呀,如果不考虑其他要花钱 /额外设备的条件,固定一台主机固定带宽,如果要增加速度还有什么办法?
    qsnow6
        40
    qsnow6  
       2018-01-04 18:35:42 +08:00 via iPhone
    加钱买多点代理就行了
    Nick2VIPUser
        41
    Nick2VIPUser  
    OP
       2018-01-04 19:03:42 +08:00 via iPhone
    @qsnow6 您是否了解质量好点的代理 ip,如果方便透露可以讲一下,目前付费购买的这家感觉质量还是提不上来...
    qsnow6
        42
    qsnow6  
       2018-01-04 19:10:18 +08:00   1
    WuMingyu
        43
    WuMingyu  
       2018-01-04 19:35:12 +08:00 via iPhone   1
    用协程的话可以试试这个 https://github.com/6ugman/ant_nest,速度比 scrapy 快?(不确定,没有精确测试)不过很可能有 bug
    anasplrt34
        44
    anasplrt34  
       2018-01-04 20:33:08 +08:00   1
    爬过十亿级数据的来吐个槽 要想速度快 加机器 加 IP 只有两条路 其他的比如什么优化什么异步多进程多协程线程都没什么作用 就比如一个网站限制单个 IP 一秒访问一次 你代码写出花来一秒也只能请求一次 这不是客户端也不算服务端 这是爬虫最大的问题 所以还是加钱吧
    Nick2VIPUser
        45
    Nick2VIPUser  
    OP
       2018-01-04 20:49:10 +08:00 via iPhone
    @qsnow6 谢谢!!
    Nick2VIPUser
        46
    Nick2VIPUser  
    OP
       2018-01-04 20:50:43 +08:00 via iPhone
    @anasplrt34 您很幽默,说到点上了,我折腾了一天,现在才想清楚,不过收获很大,谢谢!!
    Nick2VIPUser
        47
    Nick2VIPUser  
    OP
       2018-01-04 20:51:46 +08:00 via iPhone
    @WuMingyu 好的,谢谢!今天一天收获了好多好东西
    easylee
        48
    easylee  
       2018-01-04 23:41:45 +08:00
    来学习了,Mark~
    anexplore
        49
    anexplore  
       2018-01-04 23:50:58 +08:00
    如果你每个线程都要休息 3s 的话,为啥要搞多线程呢?一个线程不就行了嘛,单线程异步 IO + 代理 IP 即可,根据带宽以及代理量控制并发,
    PythonAnswer
        50
    PythonAnswer  
       2018-01-05 00:41:45 +08:00 via Android
    协程 节约点资源。

    不过你的 ip 池质量不行,速度提高不了。
    goodryb
        51
    goodryb  
       2018-01-05 10:54:36 +08:00
    为啥不能增加物理资源,开个 10 台机器,效率不就提高 10 倍了,有时候真不要死脑经,先把事情解决了再说。

    按照你的说法,假设 1 台主机需要 3 个月( 90 天),提高 10 倍之后,就需要 9 天,一周多就搞完了。

    如果你今天在这里问了这么多,回去修改代码,换框架,验证,一周后搞出个新程序来,效率提高了 10 倍,那你需要的时间是 7+9 = 16 天

    所以呢,技术不够,机器来凑,云主机按量付费也没多少,如果你爬回来的数据连这点机器的钱都不值得,那我估计更不值得你投入这么大的人力去搞这个东西。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2818 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 13:43 PVG 21:43 LAX 06:43 JFK 09:43
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86