爬虫3-爬虫防范
——参考博客 https://www.zhuyingda.com/blog/article.html?id=17
机器人协议 爬虫领域有一个“白道手段”——robots协议,这是一个君子协议,即用allow和disallow声明各个页面的爬取授权,但除了商业搜索引擎的爬虫程序,野生爬虫根本不会管你这个(明白了scrapy框架中的ROBOTSTXT_OBEY 默认为True)
1. 服务器端的检测
服务器端针对user-agent、referer、cookie等字段进行检查,但这种检查方式存在明显的缺点,这些字段都是可以轻易伪造的,甚至还能不断变换这些字段和ip代理,伪装成多个用户在访问,所以这种检查方式还是不太靠谱。
另一种检查方式是,服务器端可以检查浏览器http头指纹,根据声明的浏览器厂商和版本,来鉴别http header中的各字段是否符合该浏览器的特征。典型的就是PhantomJS 1.X版本采用的Qt框架,在http头里面有明显的Qt框架网络请求特征,可以被服务器直接识别拦截
还有一种变态的检测机制,服务器对所有的页面请求,在http response中种下一个cookie token,然后在这个页面内异步执行一些的ajax接口里面去校验来访请求是否含有cookie token,并将token传回表明这是一个合法的浏览器,否则说明刚刚下发token的用户只访问了页面的html,并没有执行js代码调用ajax请求,很可能就是个爬虫程序。
~思考:这些方法基本上都可以被selenium+chromedriver+ip代理绕过
2. 客户端的检测
结合参考博客,查询了js和html的知识看懂了博主的想法,在页面加入js代码进行检测确实是一种可靠的方法。
2.1 plugin对象的检查
navigator对象相关介绍:http://www.w3school.com.cn/jsref/dom_obj_navigator.asp
首先介绍navigator对象,Navigator 对象包含有关浏览器的信息,plugin : 插件。所以通过js代码,我们可以直接检查无头浏览器的重要信息。
if(navigator.plugins.length == 0) {
console.log("It may be Chrome headless");
}
navigator.plugins会返回一个数组,里面的元素代表浏览器已安装的插件,无头浏览器通常是没有插件的。
2.2 language的检查
通过navigator.language可以获取浏览器界面的语言设置,navigator.languages可以获取一个数组,里面存储的是浏览器用户所有的次选语言。而无头浏览器的navigator.languages返回的是空字符串。
if(navigator.languages == "") {
console.log("Chrome headless detected");
}
2.3 webGL的检查
普通的网页组成:HTML、JavaScript
WebGL网页组成:HTML5、JavaScript和GLESL ES(着色器语言 OpenGL ES)
WebGL通过H5中的<cavas>元素(画布)定于绘图区域,然后通过JavaScript内嵌GLSL ES在cavas中绘制三维图形
var canvas = document.createElement('canvas'); //获取cavas属性
var gl = canvas.getContext('webgl'); //获取webgl上下文
// WEBGL_debug_renderer_info扩展是WebGL API的一部分
// 借助此扩展,能够检索有关用户图形驱动程序的调试信息,这里主要获取vendor和renderer两个值
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
if(vendor == "Brian Paul" && renderer == "Mesa OffScreen") {
console.log("Chrome headless detected");
}
有人对比了linux上的普通谷歌浏览器和无头模式下vendor和renderer两个值的区别
(http://www.webhek.com/post/detecting-chrome-headless.html)
普通谷歌浏览器:vendor:'Google SwiftShader' renderer:'Google Inc.'
无头模式: vendor:'Brian Paul' renderer:'Mesa OffScreen'
“Mesa OffScreen”——它是没有使用任何 window 系统的渲染技术的名称
“Brian Paul” ——开源 Mesa 图形库的最初的程序。
当然不是所有的无头浏览器都是这个两个值,不过这里确实提供了一种参考思路。
2.4 浏览器hairline特性的检查
if(!Modernizr["hairline"]) {
console.log("It may be Chrome headless");
}
Modernizr 是一个 JavaScript 库,可以检测用户浏览器的 HTML5、CSS3 特性的支持状况。
无头模式下没有hairline特征,这个特征是用来检测是否支持hidpi/retina hairlines的
2.5 图片加载失败
var body = document.getElementsByTagName("body")[0];
var image = document.createElement("img");
image.src = "http://iloveponeydotcom32188.jg";
image.setAttribute("id", "fakeimage");
body.appendChild(image);
image.onerror = function(){
if(image.width == 0 && image.height == 0) {
console.log("Chrome headless detected");
}
}
在正常的chrome浏览器中,加载失败的图片的大小跟浏览器的zoom有关,但肯定不为0。而在无头浏览器里,这种图片的宽和高都为0
~思考:selenium+chromedriver正常模式,除了没有插件外其他4种方法应该都可以绕过?
2.6 反爬虫的银弹?
验证码虽然是一种有效的机器人检查方法,但是爬虫可以将验证码下载到本地,调用阿里云提供的验证码识别服务逃过检查,或者直接人工识别。而拖动滑块的验证码似乎也可以让代码重复执行拖动操作?但是按顺序点击应该无法绕过。
另一种谷歌成熟的验证技术也是非常有效方法——Google reCAPTCHA,基于用户鼠标、触屏等行为的验证技术