简单聊聊工作中总结的爬虫经验
作者:不吃夹生饭 爬虫工程师 Python爱好者社区专栏作者
知乎ID : https://www.zhihu.com/people/bu-chi-jia-sheng-fan
原本计划是开了这个专栏一周更新一篇,但是这段时间太忙了。
今天主要是说说工作中遇到的:
1.各类反爬虫
2.一些小技巧
3.我自己常用的爬虫框架
4.分享搭建一个简单的代理池
好了,进入正题。
首先是各类反爬虫和小技巧,我穿插着讲,好的,容我想想列一个表。
1.刚开始写脚本的时候经常忘记带 request headers,特别是host和user-agent这俩个字段(通常带这两个就足够了),这个就是体现在对http协议理解不够。具体是哪个网站我忘了,我因为没有带上ua,一直拿不到html,耽搁我不少的时间。
因为网站会检查你的 request headers 中的host,如果不对,好的你拿不到数据,然后是检测你的ua,嗯?什么是ua,就是User-Agent,不同的浏览器有不同的ua,也是爬虫伪装浏览器的第一步。
2.关于cookies,这个我就遇到过一次,也是我上一份工作中遇到的,我要拿数据的那个网站,分析了url,确定了参数,post过去,嗯?怎么是空网页,数据喃。
这里我们在用浏览器的开发者工具时,在network里要关注所出现的各种url。后来我注意到在每次post后还有一个url紧跟着请求,原来这个post请求数据是个障眼法。
所以呢,这个就是网站通过post请求把参数放到cookies里,然后到了真正出数据的url里,在请求时带上刚刚的cookies,服务器在读取完cookies接着就能看到数据了。
3.接下来就是ip的访问频率了。
我在入职现在这份工作时,老大让我在xx网抓一份全国的旅行社数据,结果我的ip被ban,整个公司那一周都不能上那网站。所以,当我给老大汇报这个事情的时候,老大淡淡说了句,你当人家网站的运维chishi的么。
同时,在这里作为一名爬虫工程师,基本的职业素养就包括,好比隔壁组坐着一个漂亮的菇凉,咱们看看就好了,不要去影响人家。所以说,在每两次请求间一定要有时延。这里我不是说,咱们通过测试来摸索出该网站的rps(request per second),然后就着rps来跑,这样的确算是提高效率的方法,但是我偷懒,统一设置为10秒的时延。
但是,处理办法有好几种。
一,每一次请求时变更ua,就可以理解为学校机房里,大家同时访问一个url,难不成就把这个机房的ip给ban了?
二,在request headers里带上 referer,既然是模拟人的操作,那就在每一次请求的headers的referer里带上上一次的请求url。什么?referer是做什么的,这个就是告诉服务器我是从哪一个url来到哪一个url去。
三, 设置时延,这个不解释,我们抓数据的同时不能给服务器造成太大压力,也不能影响别人的浏览体验。
四,使用代理, 通过改变代理ip的方式,让服务器没办法来阻止你拿数据。
4. 放在js中的反爬虫,这里我很愿意来举一个实际的栗子。客官们可以跟着我一起来看看人家怎么反爬虫的。
就说携程酒店的评论数据好了。
http://link.zhihu.com/?target=http%3A//hotels.ctrip.com/
然后随便点一个酒店进去,“shift+ctrl+i” 打开开发者工具
然后拖动页面去找评论,点击 更多评论, 这时候注意开发者工具里的network里的变化。
然后能看到这两个
可以看到,我画圈的就是关键,而下面那个AjaxHotelComment。是请求评论的页面,因为在请求这个ajax时里面有个参数eleven,看似是个token,实际不符合token的定义,总之就是在这个ajax请求前通过oceanball?这个请求得到一个eleven参数,然后交给请求ajax得到数据。
现在我们点进去那个画圈的url,复制开一个新窗口打开。
整理后的代码长这个样子
eval(function(arr, f) {
if (typeof Array.prototype.map === "function") {
return arr.map(f)
}
var res = [],
j = 0;
for (var i = 0,
l = arr.length; i < l; i++) {
res[j++] = f(arr[i], i, arr)
}
return res
} ([.....],
function(item) {
return String.fromCharCode(item - 38644)
eval这个臭名昭著效率低的东西恰巧就是反爬虫利器,我们可以看到这段代码实际起作用的内容就是
arr.map(f)
好的,我们来模拟。
我们打开开发者工具的console,
在里面输入
var a = [那一大段的列表].map(function(item) {
return String.fromCharCode(item - 38644)
}).join('')
a //输出结果
结果就可以看到这样的
也就是说,解码后,给了这么一段,(事实上这个跟网站底层的js有关联,不然在底层的js里找到 getElevenCode()这个function死活模拟不出来结果)。
好的,在站长工具里对解析出来的这段js代码进行格式化,看到的结果呢,只想骂马萌萌!!各个参数都是机器生成的。其中绕来绕去,被绕晕。
然后看到一段注释,心想,嘿,后门吧。转码过来看,结果如下
好的呀!结果我被嘲讽了!再一次马萌萌!!携程的人太骄傲了。
从这里我们数数人家的加密就有(1.请求得eleven 2.转码获取新的js 3.再解码)3层加密。
转过来一想,都被嘲讽了,说明我离真相就近了。
那我们换一个思路,从底层js去找。
这时候我们去看人家从哪个js来
然后点进去,“ctrl+f”搜 ‘eleven’,结果我们找到这个
可是我没看明白逻辑!!!!!!
于是我就卡在这了。
所以,携程的这个栗子的反爬虫就是通过恶心的js来完成。
为啥要这样做,因为这类网站的数据不需要通过登陆就能看到
5. 然后就是验证码咯
老大通过机器学习训练出可以识别xx网的验证码,已经上线了,所以验证码形同虚设(暂时的)
不过验证码依旧是我认为反爬虫强有力的手段,因为涉及的技术很多,学习成本很高,很容易就放弃了。
6. 至于像淘宝啊 京东啊微博啊的种种反爬虫,我还没抓过,所以我也不清楚。
等等,被老大叫出去抽根烟 -.-!
好了,我回来了,刚刚跟老大聊了聊后面的工作安排。原本今天还打算写一下框架和一个简单的代理池,放后面好了, 不好意思哈 各位。
接下来我的工作就是弄爬虫框架,还有分布式,所以我学到了什么再来分享。
Python的爱好者社区历史文章大合集:
关注后在公众号内回复“ 课程 ”即可获取:
小编的转行入职数据科学(数据分析挖掘/机器学习方向)【最新免费】
小编的Python的入门免费视频课程!
小编的Python的快速上手matplotlib可视化库!
崔老师爬虫实战案例免费学习视频。
陈老师数据分析报告扩展制作免费学习视频。
玩转大数据分析!Spark2.X + Python精华实战课程免费学习视频。