2013 from—https://my.oschina.net/u/1024140/blog/188154

近期找工作略不顺。技术无用。晚上写下了这点东西。

首先说下最近在找工作的x的大概相关技术加点路线。py 3年+,linux日常熟练,限于不擅web、手机app开发,一直无太好的可展示的东西。前段时间从一家小公司离职。年前投下,没啥的话,年后再看下。先投的py爬虫的,没合适的再看运维和py相关其他。

正文开始前略吐槽下,我之前工作的小公司,在我去之前,还是多线程urllib爬正则解析,网页编码解析从GBK,UTF8依次猜。他有点强让我走了。

我开始大量使用scrapy时,scrapy已是0.16版。这个版本相对比较成熟,该版本持续了近一年时间,13年夏发布0.18版。在网上搜scrapy资料,中文的相对较少,为数不多的几篇也多写于scrapy较早的版本(提醒看资料注意发布时间)。从旧资料看,早期的scrapy,还没有dns解析缓存,url去重等功能。到0.16时,scrapy已基本成型,差的几个功能(如HTTP长连接,仿浏览器缓存机制(RFCXXXX)的CACHE)陆续在0.18,0.20里面上实现了。Scrapinghub(写scrapy的人搞得公司)上的产品也更丰富了。

scrapy的优点在于成熟完善,定制开发快。

scrapy对比其他我所知的定制爬虫解决方案。主要对比python内的几个方案。

JAVA:nutch,hetrix…etc。这几个更适合做通用爬虫或少量的定制爬虫,相对scrapy优点是资料比较多,成熟。不过用java系的写大量定制爬虫应该比较痛苦。

Ruby:不了解,仅听说ruby有个爬虫库。

Node.js:遇到有个初创团队用node.js写的,负责人有scrapy(<0.16),gevent经验。不了解。

python:gevent及其他py的爬虫框架。稍后会详细描述这部分。

对于gevent上写爬虫的各位,我只能说你们有实力,你们为何要造轮子,你们肯定有自己的理由的,推荐参考下scrapy造轮子。gevent写爬虫大概的方案是gevent+requests+一个队列库(redis,beanstalk.etc.)。需要注意的点和坑有如下一些。

0,gevent使用协程,monkey_patch后一些调试方法不可用。

1,requests的编码检测是不符标准的,他有两个编码,一个是http head里面的编码,另一个是依据网页body的编码。标准是网页内容声明的编码优先于http头的编码,requests没有做这个考虑,总是使用head里面的编码。在head和body编码声明不一致时可能出现编码错误。

2,gevent的同步机制略少,某些情况下协程同步效率低。这个是我在写http代理调度器(类似Crawlera)的东西时遇到的。http代理调度器我下面会提及。

3,其他各种细节。太多。如requests开gzip,requests连接池等等。太多太多。

gevent相对于scrapy的优点有:

1,如果涉及到底层定制 ,gevent比scrapy所用的twisted简单。我曾想给scrapy嵌一个http代理调度功能,发现略难,需要很了解twisted。

2,如果你只需要很少的几个简单爬虫,你可能觉得gevent用着更顺手(但scrapy也很容易)。对于纯下载网页,用gevent实现比scrapy快,毕竟scrapy还有其他功能,但这有个前提,你有很高很高的带宽,要先达到scrapy的下载页面速率上限。

python还有其他几个爬虫框架,我都大致看过源码。有个框架有个让你人工输验证码的demo(名字忘了)。其他没什么特别的了。

scrapy经验,资料

资料:官方文档,http权威指南,一些博文。

看文档时仔细点,很多功能都有。

scrapy github账号的各类repo(https://github.com/scrapinghub)有很多好东西,如:

1,scrapyjs,splash:爬虫遇到的js问题的解决方法(JS解析会在下面提及)

2,webstruct…etc:机器学习,模糊匹配等用来解析网页内容的。

3,etc…

scrapy有个SEP类似PEP的,可以一看,也在github的仓库。

留意scrapy的博客http://blog.scrapinghub.com/

wiki:https://github.com/scrapy/scrapy/wiki

scrapy公司(http://scrapinghub.com/)的产品:

1,定制爬虫(让scrapy公司帮你写爬虫然后交付你)

2,scrapy cloud(提供跑爬虫的服务器(scrapyd))

3,autoscraping(点击需要内容即可实现爬取)

4,crawlera,解决爬网站的ip限制问题(我有一个类似功能的本地版http代理调度器及大量代理)。

一些常见问题,经验:

0,了解scrapy已经做过的功能,优化等。。。防止重复造轮子,如,去重,编码检测,dns缓存,http长连接,gzip等等。

1,JS相关。

这个是被问的最多的。看具体情况解决。可模拟相关js执行、绕过,或直接调浏览器去访问。自己用一个JS引擎+模拟一个浏览器环境难度太大了(参见V8的DEMO)。

调浏览器有很多方法。难以细说,关键字如下,selenium,phantomjs,casperjs,ghost,webkit,scrapyjs,splash。一些细节如关掉CSS渲染,图片加载等。只有scrapyjs是完全异步的,相对是速度最快的,scrapyjs将webkit的事件循环和twisted的事件循环合在一起了。其他的方案要么阻塞,要么用多进程。简单的js需求(对效率要求不高)随意选,最优方案是scrapyjs+定制webkit(去掉不需要的功能)。调浏览器开页面是比较耗资源的(主要是cpu)

2,内容解析。

XPATH就可以了,感兴趣可以看下pyquery,css选择器。

如果想获得网页对应的txt,可以调浏览器,有个类似plain_txt的接口可以获取网页保存成txt。

模糊匹配参考scrapy github里面几个库,机器学习不一定好用(效果问题,人工问题-需要训练)。还有写些正则去模糊匹配。

新闻类似的正文提取有readability,boilerplate。

3,分布式。

首先考虑按任务(目标)切分,然后让不同目标的爬虫在不同机器上跑

完全的对等分布式(多爬虫爬一个目标),把任务队列替换掉爬虫改改即可。github里面有几个现有的实现参考。

分布式需求可能是伪命题。想清楚为何要分布式。硬件够不够,像什么拿一个不支持持久化的url队列的爬虫说量大需要分布式的,我只能默念,你为何这么吊。

4,部署,调度

部署推荐scrapyd。这也是官方推荐的方法。

大量爬虫的调度,这个目前(13-10)没有现成的合适方法,期望是实现爬虫的某些配置放数据库,提供web后台 ,然后按配置周期、定时运行爬虫,终止,暂停爬虫等等。可以实现,但要自己写不少东西。

5,ip限制问题

买的起大量ip的可买(买大量同网段爬可能导致整网段被封)。

找大量免费的开放http代理,筛选可用的,免费开放代理不可靠,写个调度机制,自动根据成功次数,延迟等选择合适代理,这个功能难以在scrapy内实现,参考scrapinghub的crawlera,我完成了一个本地版。

6,url去重。

如果有千万级的URL需要去重,需要仔细看下scrapy的去重机制和bloom filter(布隆过滤器)。bloomfilter有个公式可以算需要多少内存。另bloomfilter  + scrapy在github有现有实现可以参考。

7,存储。

mongodb,mongodb不满足某些功能时考虑hbase,参考http://blog.scrapinghub.com/2013/05/13/mongo-bad-for-scraped-data/

8,硬件扛不住别玩爬虫。。。曾在I3 4G 1T上跑爬虫。卡在磁盘io(量大,磁盘io差,内存低),出现内存占用飙升。很难调试(调试爬虫看实际跑耗时较长),初步以为是爬虫有问题内存占用高导致数据库卡。调试结果确认为,配置低量太大,导致数据库慢,数据库慢之后爬虫任务队列占满内存并开始写磁盘,又循环导致数据库慢。

9,爬虫监控

scrapyd自带简单的监控,不够的话用scrapy的webservice自己写,暂无(13.10)现成的

9,=。=想到再补充。

最后说个故事。

面试的时候注意点到为止。几个雕坐在一个地方问了ban一下午的爬虫相关各种问题、方案、细节,还准备让我写个DEMO,加来回快一天了。