一天抓一百多万张网页

  • 简要[1]
  • 优化存储硬盘[2]
  • 优化内存,URL去重[3]
  • 网络性能,抓取技术细节调优[4]
  • 反抓取访问频率限制[5]
  • 总结[6]
  • 问题答解[7]

原文


  1. 本篇只关注如何让爬虫的抓取性能最大化上,没有使用scrapy等爬虫框架,就是多线程+Python requests库搞定。
    对一个网站定向抓取几十万张页面一般只用解决访问频率限制问题就好了。对机器内存,硬盘空间,URL去重,网络性能,抓取间隙时间调优一般都不会在意。如果要设计一个单台每天抓取上百万张网页,共有一亿张页面的网站时,访问频率限制问题就不是最棘手的问题了,上述每一项都要很好解决才行。硬盘存储,内存,网络性能等问题我们一项项来拆解。

  2. 优化存储硬盘
    千万级网页的抓取是需要先设计的,先来做一个计算题。共要抓取一亿张页面,一般一张网页的大小是400KB左右,一亿张网页就是1亿X200KB=36TB。这么大的存储需求,一般的电脑和硬盘都是没法存储的。所以肯定要对网页做压缩后存储,可以用zlib压缩,也可以用压缩率更好的bz2或pylzma 。但是这样还不够,要对网页特殊处理一下,可以把网页的头和尾都去掉,只要body部分再压缩。因为一张html页面里<head></head>和<footer></footer>大都是公共的头尾信息和js/css代码,对你以后做正文内容抽取不会影响。

  3. 优化内存,URL去重
    1.放在set()里面,一亿个URL就要占用4G内存;
    2.https://www.tianyancha.com/company/23402373的后缀:23402373放进set()里23402373只占8个字节,一亿个URL占700多M内存;
    3.使用BloomFilter算法,非常适用海量数据的排重过滤,占用极少的内存,查询效率也非常的高,它的原理是把一个字符串映射到一个bit上,刚才23402373占8个字节,现在只占用1个bit(1字节=8bit),内存节省了近64倍,以前700M内存,现在只需要10多M了。
    安装
    pip install bloom_filter
    from bloom_filter import BloomFilter
    生成一个装1亿大小的
    bloombloom = BloomFilter(max_elements=100000000, error_rate=0.1)
    向bloom添加URL
    bloom.add('https://www.tianyancha.com/company/23402373')
    判断URL是否在
    'https://www.tianyancha.com/company/23402373' in bloombloom:
    bloombloom.contains('https://www.tianyancha.com/company/23402373')

  4. 网络性能,抓取技术细节调优
    1.《爬虫小偏方:绕开登陆和访问频率控制
    2.《 爬虫小偏方二:修改referer后可以不用登录了》。
    3.多IP抓取,多IP抓取又分IP代理池和adsl拨号两种
    adsl拨号的方式
    IP代理池相对于adsl来说,我觉得收费太贵了(一个代理IP收费4分钱,8640个IP一天就要345元)。要稳定大规模抓取肯定是要用付费的,adsl一个月也就100多块钱。
    adsl的特点
    是可以短时间内重新拨号切换IP,IP被禁止了重新拨号一下就可以了。
    有哪些可以adsl拨号的野云主机?
    百度搜"vps adsl",每次拨号的IP,有真实二三十万IP的就算不错了。
    选adsl的一个注意事项
    有的厂商拨号IP只能播出C段和D段IP,110(A段).132(B段).3(C段).2(D段),A和B段都不会变,靠C,D段IP高频次抓取对方网站,有可能对方网站把整个C/D段IP都封掉。C/D段加一起255X255就是6万多个IP全都报废,所以要选拨号IP范围较宽的厂商。
    adsl拨号Python代码
    怎么拨号厂商都会提供的,建议是用厂商提供的方式,以下为示例
    windows下用os调用rasdial拨号:
    import os
    拨号断开
    os.popen('rasdial 网络链接名称 /disconnect')
    每次断开拨号后,要等待几秒钟再拨号,太短时间内再拨号有可能又拨到上一个IP,还有可能拨号失败
    time.sleep(6)
    拨号
    os.popen('rasdial 网络链接名称 adsl账号 adsl密码')
    linux下拨号:
    import os
    拨号断开
    code = os.system('ifdown 网络链接名称')
    每次断开拨号后,要等待几秒钟再拨号,太短时间内再拨号有可能又拨到上一个IP,还有可能拨号失败
    time.sleep(6)
    拨号
    code = os.system('ifup 网络链接名称')

  5. 反抓取访问频率限制
    上面步骤做完了,每天能达到抓取五万网页的样子,要达到百万级规模,还需把网络性能和抓取技术细节调优。
    1.调试开多少个线程,多长时间拨号切换IP一次最优。
    先开一个线程,一直抓取到IP被屏蔽,记录下抓取耗时,总抓取次数,和成功抓取次数,如图:


    分析上述图片得出,当有6个线程时,是比较好的情况。耗时6秒,成功抓取80-110次。虽然8个线程只耗时4秒,成功抓取次数已经在下降了。so线程数可以设定为开6个,最后每总抓取120次就重新拨号。注意:尽量不要使用时间重新拨号,因为网络延迟等各类问题导致6秒内抓取次数不定。
    2.requests请求优化
    设置超时时间
    野云主机本身性能就不稳定,追求抓取效率设置短一点的时间如timeout=1.5
    3.adsl拨号等待时间
    上面步骤已算把单台机器的抓取技术问题优化到一个高度了,还剩一个优化野云主机的问题。就是每次断开拨号后,要等待几秒钟再拨号,太短时间内再拨号有可能又拨到上一个IP,还有可能拨号失败,所以要等待6秒钟(测试值)。所以要把拨号代码改一下:
    import os
    断开拨号
    os.popen('rasdial 网络名称 /disconnect')
    time.sleep(6)
    拨号
    os.popen('rasdial 网络名称 adsl账号名 adsl密码')
    4.检测是否连通(拨号完成,不能马上使用)
    用ping功能检测:
    import os
    code = os.system('ping www.baidu.com')

  6. 总结
    一组抓取的耗时是6秒,拨号耗时10秒,总耗时16秒。一天86400秒,就是5400组抓取,上面说了一组抓取是120次。一天就可以抓取5400X120=64万张网页。
    如果你把adsl拨号耗时再优化一点,每次再节约2-3秒,就趋近于百万抓取量级了。
    另外野云主机一个月才100多,很便宜,所以你可以再开一台adsl拨号主机,用两台一起抓取,一天就能抓一百多万张网页。几天时间就能镜像一个过千万网页的网站。

  7. 问题答解
    1.为什么不用异步抓取?
    没必要,这里的整个抓取关键是网络性能,而不是程序性能。用异步把程序性能提高了,单位时间的抓取次数是提高了,但是这样反而会击中对方网站的访问频率控制策略。
    2.要计算对方的带宽压力,不要抓取太过分了
    抓取归抓取,但不要影响对方网站,把对方网站带宽都打满了。
    一个中小型网站的带宽在5M以内,大一点的网站带宽可能10-30M,超大型的另算。
    一张网页300KB,对方一般会压缩后传输给浏览器,就按压缩后30KB算,你的爬虫一秒请求20次,带宽就是600KB。可能一个网站每天都有几十个爬虫都在爬,我们按有10个爬虫在同时抓取,就是这些爬虫一秒内就要消耗600KBX10=6M带宽。
    再加上还有正规爬虫,人家网站上的正常用户访问这些,算下来可能一共要消耗10M带宽。一般的大中型网站都是吃不消的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容

  • 我是日记星球338号星宝宝,我正在参加13期21天蜕变之旅。自己没有想到自己竟然坚持了连续21天完成日记打...
    猫猫79阅读 101评论 0 0
  • 十六字令《秋》 文:浮萍寻根 秋。鸿雁南归岁月流。金罂裂,难裹万千愁。 {金罂:石榴别称}【词林正韵第十二部】
    浮萍寻根阅读 209评论 0 0
  • 《相信远方》 冰天次升 把这一生的每一次困惑 都打造成一扇窗 推开了 世界,豁然开朗 ...
    王小东阅读 306评论 0 1
  • 出差这一个月,感觉孩子懂得东西原来越多了,心里酸酸的感觉,感觉她的这段成长缺少了我得参与,我走,也能随时跟我说拜拜...
    8601阅读 108评论 0 0