Welcome to EliteQing's Blog

数据抓取的艺术(三)

原文地址:http://blog.chinaunix.net/uid-22414998-id-3696649.html

 

  本来是想把这部分内容放到前一篇《数据抓取的艺术(二):数据抓取程序优化》之中。但是随着任务的完成,我越来越感觉到其中深深的趣味,现总结如下:

   (1)时间
     时间是一个与抓取规模相形而生的因素,数据规模越大,时间消耗往往越长。所以程序优化变得相当重要,要知道抓取时间越长,出错的可能性就越大,这还不说程序需要人工干预的情境。一旦运行中需要人工干预,时间越长,干预次数越多,出错的几率就更大了。在数据太多,工期太短的情况下,使用多线程抓取,也是一个好办法,但这会增加程序复杂度,对最终数据准确性产生一定影响。
     所以,千万不能看不起小小的调优,那怕只是0.02秒一次的改进,对于上万乃至千万级别的数据量而言,都可以节省数小时甚至数天的时间,同时也能在某种程度上降低出错的概率。于是,我得出一个原则:“程序优化要力求极致”。
     这是“软”的因素。

   (2)效率
      呵呵,效率可以被视为是时间的另一种说辞,虽然这种说法并不全面。在这里我所谓的效率,指的是I/O效率。一旦算法优化已经完善,那么还有什么可以提高效率以缩短程序完成的时间呢?这回抓取,我使用的是SSD硬盘,与实验室的机械硬盘相比(可惜用的是笔记本),速度得到了明显的提升。
     我感觉以后处理大规模数据(或“大数据”),需要使用内存数据库。首先,使用数据库而非Excel就已经能够提高效率,如果再采用内存数据库的话,效率将得到更大幅度的攀升。当然,如果你机器内存足够大的话,可以试试Redis。
     SSD硬盘与内存数据库是特别重要的两个方面。但我们也不能忽略CPU,一个好的CPU就是一颗“强劲的心”,但是笔记本的CPU一般都做过“调优”(想想吧:有限的电力,为了延时,只好吃一口“蓝色小丸药”),我觉得I3处理器性能有些低下,如果不是I5+还不如直接用奔腾双核结构。当然最好是运行在台式机、工作站、服务器甚至云系统中。嘿嘿,下次我要试试Sae。
     这是“硬”的因素。

   (3)了解你的对手
     常言道,知己知彼百战不殆。做数据抓取,最重要的就是了解你的对手。这一轮,我很倒霉,我碰到了Google姐,由于我的数据只能从Google上析出,所以没的选择,不过虽说她也把我折腾地够呛,但最终我还是享受到了“神秘的”幸福。
     这是“人”(目标对手)的因素。
     八卦一下我和Google姐一夜大战的六个回合吧。
     第一回合,简单地使用urllib2或其它库是不行的,我的血泪史说明,搜索超不过8个Google就强行和你失去连接了。重新搜这几个还可以,但接着第8个往后走,她就又不干了,还是不能连接。姐姐一脸坏笑地看着我,就这点小把戏,还想过来扒我裤子?我十分汗颜,责怪自己没能正确估计出她那雄壮的腰围。
     第二回合,我开始设计欺骗Google。由于人类访问网站,不会有极短而均匀的点击行为,所以我设计了一个小函数,每次搜索完毕,随机暂停1~3秒,这是在模仿人的访问模式。不幸再次降临到我身上,姐姐的坏笑依旧,我也没能触动到她的一根毫毛。
     第三回合,我生气了。我准备上代理,我的战术很简单,弄一大堆代理站成一队,排得一眼望不到边,失去连接我就换一个代理,再失去就再换,吓死她!结果这条路仍没走通,这种硬碰硬的方式不是好方式,姐姐其实是过来人,从小吓大的,这招没用:一方面是我找到的可用代理IP实在有限,根本不够换的;另一方面,代理的引入大大增加了程序出错的可能性,因为代理本来就不都靠谱。好几次,不是Google断掉的而是代理跑着跑着给断的。
     第四回合,我没气可生了。我开始深入研究,静下心来耐心学习这个领域的知识,仔细欣赏、研究Google这个熟女。功夫不负有心人,我找到了终极解决方案:浏览器。不必再模拟手工行为(Mechanize),咱就直接用浏览器访问,看她还有什么话说。其实这样的方法很多,核心就是使用测试工具。所以你也可以使用selenium或Windmill,也可以使用QT+Webkit等等就不一一列举了。当然,我用的是Selenium+Phantomjs+BeautifulSoup,后来想想也不用BS,直接正则算了,但毕竟BS比较简单哈。
     第五回合,我编写好程序,进行优化,特意选择深夜悄然开始执行。我用的校园网,晚上网速极快,所以嗖嗖地抽取出结果,但有个问题,就是Google对单IP短时持续访问请求是有限制的,这个限制不论是蜘蛛还是人都绕不开,她会证给你一个填写验码的证明页面,上书“不能未婚先孕”,到街道办开了证明才能让你继续。唉,对此,一开始,我太年轻,真没什么办法,只能在程序中识别这个页面,然后保存结果退出。再重新启动继续这个断点接着执行。不过由于每隔70、80个就会因验证码页面停掉一次,我的抓取速度一直不高,因为需要手工干预。
     [虚拟第六回合,我用一个新线程执行抓取,当这个线程遇到验证码时,保存、退出并回馈断点参数,然后带入参数重启一个新的线程。时间原因,还没如此实现。]
     第六回合,较长的抓取时间,我在傻傻等待,时不时断点续抓一次。我受不了了,我开始做点其他的事情,比如浏览新闻、听听音乐、看看电影什么的。终于,我发现,竟然碰不到验证码页面了。这点十分惊喜,仔细研究了这个过程,我得出结论,抓取时其他程序对抓取程序网速的影响,正好让Google认为这似乎就是人在搜索,所以从95个左右开始,到最后的152个的共词搜索,还是那个程序,但由于我的其他休闲活动导致后半程一次都没有遇到验证码。Oh Yeah~神马重启一个新线程,NND都是浮云,一边爬取数据一边轻松生活才是王道。(只是别因下片把网速全占满了,使你的抓取程序一直处于一个等待状态,就像《潜伏》最后一幕一样,翠平抱着孩子一直在等待一个永远不能归来的人)。所以要向普天下的男人们大声说:不要那么直接,一上来就只知道抓,一起多看看电影、多听听歌,效果会更好!难道不是么?

posted @ 2016-05-15 00:31  EliteQing  阅读(175)  评论(0编辑  收藏  举报