爬虫的基本流程
- 选取一部分精心挑选的种子URL,将种子URL加入待抓取任务队列。
- 从待抓取URL队列中取出待抓取的URL,DNS解析得到主机的ip,并将URL对应的网页下载存储进已下载网页库中,将该URL放进已抓取URL队列。
- 分析提取已下载的网页中的URL,将未抓取过的URL放入待抓取URL队列,从而进入下一个循环。
- 解析已下载的网页,将需要的数据内容解析出来。
- 数据持久化,以数据库或其它形式存储。
一个URL的请求与响应
爬虫最主要的任务就是发起请求(Request),然后获取服务器的响应(Response),遵循HTTP协议。
HTTP之请求消息Request
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
- 请求行(request line)
- 请求头部(header)
- 空行
- 请求数据
GET请求样例:
|
|
HTTP之响应消息Response
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息。
HTTP响应也由四个部分组成,分别是:
- 状态行
- 消息报头
- 空行
- 响应正文
Response响应样例:
|
|
解析网页数据
Python HTML解析器
DOM(文档对象模型)树
重点介绍Beautiful Soup
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。Beautiful Soup会帮你节省数小时甚至数天的工作时间。
Beautiful Soup 解析html样例:电视猫
|
|
存储数据
爬虫的抓取策略
在爬虫系统中,待抓取URL队列是很重要的一部分。待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那个页面,后抓取哪个页面。而决定这些URL排列顺序的方法,叫做抓取策略。下面重点介绍几种常见的抓取策略:
深度优先策略(DFS)
深度优先策略是指爬虫从某个URL开始,一个链接一个链接的爬取下去,直到处理完了某个链接所在的所有线路,才切换到其它的线路。 此时抓取顺序为:A -> B -> C -> D -> E -> F -> G -> H -> I -> J
广度优先策略(BFS)
宽度优先遍历策略的基本思路是,将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。 此时抓取顺序为:A -> B -> E -> G -> H -> I -> C -> F -> J -> D
高效抓取数据(多线程/多进程/分布式爬虫)
分布式爬取,针对大型爬虫系统的,实现一个分布式的爬虫,主要为以下几个步骤:
- 1、基本的http抓取工具,如scrapy;
- 2、避免重复抓取网页,如Bloom Filter;
- 3、维护一个所有集群机器能够有效分享的分布式队列;
- 4、将分布式队列和Scrapy的结合;
- 5、后续处理,网页析取(如python-goose),存储(如Mongodb)。
反爬虫机制与应对策略
爬虫:使用任何技术手段,批量获取网站信息的一种方式。 反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。
**常见的反爬虫机制:**一般网站从三个方面反爬虫,即请求网站访问时的请求头Headers,用户行为,目标网站的目录和数据加载方式。前两个方面可以说是反爬虫策略中最为常见的,而第三个则是应用ajax(异步加载)的方式加载页面目录或者内容,增大爬虫在对目标网站形成访问之后获取数据的难度。
0x01 通过Headers反爬虫
-
通过Headers中的User-Agent识别爬虫 从用户请求的Headers反爬虫是最常见的反爬虫策略。由于正常用户访问网站时是通过浏览器访问的,所以目标网站通常会在收到请求时校验Headers中的User-Agent字段,如果不是携带正常的User-Agent信息的请求便无法通过请求。
-
通过Headers中的Refer防止盗链 盗链是指服务提供商自己不提供服务的内容,利用别人网站的链接去获取别人网站里面的图片或者视频等资源,一部分网站为了防盗链,还会校验请求Headers中的Referer字段。
0x01 应对策略
- 构造Headers 针对这类反爬虫机制,可以直接在自己写的爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中,或使用User-Agent池。也就是每次发送的时候随机从池中选择不一样的浏览器头信息,防止暴露爬虫身份;另外通过对请求的抓包分析,将Referer值修改为目标网站域名,就能很好的绕过。
0x02 基于用户行为反爬虫
-
设置IP访问频率,如果超过一定频率,弹出验证码 如果输入正确的验证码,则放行,如果没有输入,则拉入禁止一段时间,如果超过禁爬时间,再次出发验证码,则拉入黑名单。当然根据具体的业务,为不同场景设置不同阈值,比如登陆用户和非登陆用户,请求是否含有refer。
-
通过并发识别爬虫 有些爬虫的并发是很高的,统计并发最高的IP,加入黑名单(或者直接封掉爬虫IP所在C段)
-
请求的时间窗口过滤统计 爬虫爬取网页的频率都是比较固定的,不像人去访问网页,中间的间隔时间比较无规则,所以我们可以给每个IP地址建立一个时间窗口,记录IP地址最近12次访问时间,每记录一次就滑动一次窗口,比较最近访问时间和当前时间,如果间隔时间很长判断不是爬虫,清除时间窗口,如果间隔不长,就回溯计算指定时间段的访问频率,如果访问频率超过阀值,就转向验证码页面让用户填写验证码。
-
限制单个ip/api token的访问量 比如15分钟限制访问页面180次,具体标准可参考一些大型网站的公开api,如twitter api,对于抓取用户公开信息的爬虫要格外敏感
0x02 应对策略
-
降低请求频率 例如每隔一个时间段请求一次或者请求若干次之后sleep一段时间,也可以每次请求后随机间隔几秒再进行下一次请求。由于网站获取到的ip是一个区域网的ip,该ip被区域内的所有人共享,因此这个间隔时间并不需要特别长。
-
使用代理IP池 使用代理IP池需要大量的IP资源。可以专门写一个在网上抓取可用代理ip的脚本,然后将抓取到的代理ip维护到代理池中供爬虫使用,当然,实际上抓取的ip不论是免费的还是付费的,通常的使用效果都极为一般,如果需要抓取高价值数据的话也可以考虑购买宽带adsl拨号的VPS,如果ip被目标网站被封掉,重新拨号即可。
0x03 动态页面的反爬虫
-
数据通过ajax请求得到或JavaScript生成 上述的几种情况大多都是出现在静态页面,但是对于动态网页,我们需要爬取的数据是通过ajax请求得到,或者通过JavaScript生成的。
-
ajax请求的所有参数全部加密 网站把ajax请求的所有参数全部加密了。我们根本没办法构造自己所需要的数据的请求。还有一些严防死守的网站,除了加密ajax参数,它还把一些基本的功能都封装了,全部都是在调用自己的接口,而接口参数都是加密的。
0x03 应对策略
-
模拟ajax请求获取数据 首先用Firebug或者HttpFox对网络请求进行分析。如果能够找到ajax请求,也能分析出具体的参数和响应的具体含义,我们就能采用上面的方法,直接利用requests或者urllib2模拟ajax请求,对响应的json进行分析得到需要的数据。
-
调用浏览器内核模拟正常人的交互 通过selenium+phantomJS框架,调用浏览器内核,并利用phantomJS执行js来模拟人为操作以及触发页面中的js脚本。从填写表单到点击按钮再到滚动页面,全部都可以模拟,不考虑具体的请求和响应过程,只是完完整整的把人浏览页面获取数据的过程模拟一遍。用这套框架几乎能绕过大多数的反爬虫,因为它不是在伪装成浏览器来获取数据(上述的通过添加Headers一定程度上就是为了伪装成浏览器),它本身就是浏览器,phantomJS就是一个没有界面的浏览器,只是操控这个浏览器的不是人。
0x04 其它反爬虫机制-Cookie限制
- Cookie限制 和Headers校验的反爬虫机制类似,当用户向目标网站发送请求时,会再请求数据中携带Cookie,网站通过校验请求信息是否存在Cookie,以及校验Cookie的值来判定发起访问请求的到底是真实的用户还是爬虫,第一次打开网页会生成一个随机cookie,如果再次打开网页这个Cookie不存在,那么再次设置,第三次打开仍然不存在,这就非常有可能是爬虫在工作了。
- Cookie校验和Headers的区别 用户发送的Headers的内容形式是固定的可以被轻易伪造的,Cookie则不然。原因是由于浏览器请求网站访问的过程中所分析得到的Cookie往往都是经过相关的js等过程已经改变了domain的Cookie,假如直接手动修改爬虫携带的Cookie去访问对应的网页,由于携带的Cookie已经是访问之后的domain而不是访问之前的domain,所以是无法成功模拟整个流程的,这种情况必然导致爬虫访问页面失败。
0x04 应对策略
- 分析Cookie 分析Cookie,可能会携带大量的随机哈希字符串,或者不同时间戳组合的字符串,并且会根据每次访问更新domain的值。分析过程:首先要在对目标网站抓包分析时,必须先清空浏览器的Cookie,然后在初次访问时,观察浏览器在完成访问的过程中的请求细节(通常会在这一过程中发生若干次301/302转跳,每次转跳网站返回不同的Cookie给浏览器然后在最后一次转跳中请求成功)。在抓包完成对请求细节的分析之后,再在爬虫上模拟这一转跳过程,然后截取Cookie作为爬虫自身携带的Cookie,这样就能够绕过Cookie的限制完成对目标网站的访问了。
0x05 其它反爬虫机制-验证码限制
-
验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。人类有着一种天赋,可以很轻松的从一段图片中识别出文字和数字,而机器却不能。
-
数字字母验证码 这类验证码优点是生成简单,大部分语言都自带图形库,在加入一点扭曲和噪点,基本可以解决掉初级爬虫工程师和暴力破解的脚本小子。缺点当然也显而易见,对于cnn代码只用写10行的今天,这些验证码只要有足够的标注数据,破解起来简直是轻而易举。
-
中文验证码 比如知乎采用过的验证码选择倒立的中文以及网易邮箱类的验证码(标记文字位置)。这类验证码一般来很少有公用的代码,因此编写起来麻烦。不过也正因为每一家采用的都不一样,在加上中文庞大的汉字库,确实给机器识别带来的比较大的挑战,如果配合好字体和扭曲,确实可以有不错的效果。
-
极验验证 极验的v2版验证体系破解难度甚至比不过数字字母验证码来的复杂,唯一的优势就是现在大部分打码平台不支持。图片识别上直接对比像素就可以识别位置,唯一难点的移动轨迹,但用轨迹做分类人类和机器间的特征并不那么明显,加上网页中采集轨迹的准确性较差,因此做一些简单的模拟就可以轻松躲过轨迹识别。
-
其它验证类型 比如12306这类图片验证,这种反爬虫要求较高,需要强大的图片库。其它还有算术验证、成语验证等等,发爬虫通过难度不是很高。
0x05 应对策略
-
打码平台 最常用,最简单的识别,一般字母文字1分一次,中文识别略贵,计算题可能5分,不支持极验这类。
-
OCR库 传统的ocr采用先切割再识别的方案,对于新型的验证码已经很难做了。
-
机器学习 端到端数字字母识别神器,根据识别难度和长度不同,对标注数据的需求量不一样,当然图片预处理也稍微有些区别。一般简单常见的识别可以直接从网上找代码。