导语:
简要介绍通用爬虫技术的原理,聚焦于聚焦网络爬虫进行分析,网络爬行时为提高效率优化爬行策略、贴合网页更新频率、分析算法三个方面进行简单阐述方法。
以python为例,向网页发起HTTP请求,简述python的网络爬虫原理并进行构建。
在抓取对方网站、APP 应用的相关数据时,经常会遇到一系列的方法阻止爬虫。一方面是为了保证服务的质量,另一方面是保护数据不被获取。本文会介绍常见的一些反爬虫和反反爬虫的手段。
正文:
一、通用网络爬虫
通用网络爬虫的实现原理可以简要概括如下:(见图一)
1、获取初始URL,即网页地址。可以由用户直接指定,或者也可以由用户指定的爬取网页决定。
2、根据初始的URL页面并获得新的URL。获得初始的URL地址之后,首先需要爬取对应URL地址中的网页,爬取了对应的URL地址中的网页后,将网页存储到原始数据库中,并且在爬取网页的同时,发现新的URL地址,同时将已爬取的URL地址存放到一个URL列表中,用于去重及判断爬取的进程。
3、将新的URL放到URL队列中。在第2步中,获取了下一个新的URL地址之后,会将新的URL地址放到URL队列中。
4、从URL队列中读取新的URL,并依据新的URL爬取网页,同时从新网页中获取新URL,并重复上述的爬取过程。
5、满足爬虫系统设置的停止条件时,停止爬取。在编写爬虫的时候,一般会设置相应的停止条件。如果没有设置停止条件,爬虫则会一直爬取下去,一直到无法获取新的URL地址为止,若设置了停止条件,爬虫则会在停止条件满足时停止爬取
二、聚焦网络爬虫
聚焦网络爬虫,由于其需要有目的地进行爬取,所以对于通用网络爬虫来说,必须要增加目标的定义和过滤机制,具体来说,此时,其执行原理和过程需要比通用网络爬虫多出三步,即目标的定义、无关链接的过滤、下一步要爬取的URL地址的选取。(见图二)
1、对爬取目标的定义和描述。在聚焦网络爬虫中,我们首先要依据爬取需求定义好该聚焦网络爬虫爬取的目标,以及进行相关的描述。
2、获取初始的URL。
3、根据初始的URL爬取页面,并获得新的URL。
4、从新的URL中过滤掉与爬取目标无关的链接。因为聚焦网络爬虫对网页的爬取是有目的性的,所以与目标无关的网页将会被过滤掉。同时,也需要将已爬取的URL地址存放到一个URL列表中,用于去重和判断爬取的进程。
5、将过滤后的链接放到URL队列中。
6、从URL队列中,根据搜索算法,确定URL的优先级,并确定下一步要爬取的URL地址。在通用网络爬虫中,下一步爬取哪些URL地址,是不太重要的,但是在聚焦网络爬虫中,由于其具有目的性,故而下一步爬取哪些URL地址相对来说是比较重要的。对于聚焦网络爬虫来说,不同的爬取顺序,可能导致爬虫的执行效率不同,所以,我们需要依据搜索策略来确定下一步需要爬取哪些URL地址。
7、从下一步要爬取的URL地址中,读取新的URL,然后依据新的URL地址爬取网页,并重复上述爬取过程。
8、满足系统中设置的停止条件时,或无法获取新的URL地址时,停止爬行。
三、爬行策略
在网络爬虫的过程中,一个目标网址往往会牵扯关联到多个URL地址,那么对于这些URL地址,爬虫应该先爬取哪个?后爬取哪个?
在通用网络爬虫中,虽然爬取的顺序并不是那么重要,但是在其他很多爬虫中,比如聚焦网络爬虫中,爬取的顺序非常重要,而爬取的顺序,一般由爬行策略决定。我们将为大家介绍一些常见的爬行策略。
爬行策略主要有深度优先爬行策略、广度优先爬行策略、大站优先策略、反链策略、其他爬行策略等。这里我们进行简要介绍。
深度优先爬行策略
爬取一个网页,然后将这个网页的下层链接依次深入爬取完再返回上一层进行爬取。(见图三)
即爬行顺序为:A → D → E → B → C → F → G。
广度优先爬行策略
爬取同一层次的网页,将同一层次的网页全部爬取完后,在选择下一个层次的网页去爬行,比如,上述的网站中,如果按照广度优先的爬行策略去爬取的话,爬行顺序可以是:A→B→C→D→E→F→G。
大站爬行策略
按对应网页所属的站点进行归类,如果某个网站的网页数量多,那么我们则将其称为大站,按照这种策略,网页数量越多的网站越大,然后,优先爬取大站中的网页URL地址。
反链策略
一个网页的反向链接数,指的是该网页被其他网页指向的次数,这个次数在一定程度上代表着该网页被其他网页的推荐次数。所以,如果按反链策略去爬行的话,那么哪个网页的反链数量越多,则哪个网页将被优先爬取。
除了以上这些爬行策略,在实际中还有很多其他的爬行策略,比如OPIC策略、Partial PageRank策略。
四、网页更新策略
一个网站的网页会经常更新,作为爬虫方,在网页更新后,我们需要对其进行重新爬取。如果网页更新过慢,而爬虫重新爬取的频率过快,势必会造成爬虫和服务器的压力。如果网页更新较快,而爬虫重新爬取的频率过慢,则会导致信息滞后,达不到爬虫原有的目的。
当网页更新频率和爬虫重新爬取频率趋于一致时,爬虫的效果越好。下面将简单介绍三种网页更新策略:用户体验策略、历史数据策略、聚类分析策略。
用户体验策略
在搜索引擎查询某个关键词的时候,会出现一个排名结果,在排名结果中,通常会有大量的网页,但是,大部分用户都只会关注排名靠前的网页,所以,在爬虫服务器资源有限的情况下,爬虫会优先更新排名结果靠前的网页。
爬取中会保留对应网页的多个历史版本,并进行对应分析,依据这多个历史版本的内容更新、搜索质量影响、用户体验等信息,来确定对这些网页的爬取周期。
历史数据策略
依据某一个网页的历史更新数据,通过泊松过程进行建模等手段,预测该网页下一次更新的时间,从而确定下一次对该网页爬取的时间,即确定更新周期。
聚类分析策略
一个网页为新网页,则不会有对应的历史数据,并且,如果要依据历史数据进行分析,则需要爬虫服务器保存对应网页的历史版本信息。
经过大量的研究发现,网页可能具有不同的内容,但是一般来说,具有类似属性的网页,其更新频率类似。这是聚类分析算法运用在爬虫网页的更新上的一个前提指导思想。
我们可以首先对海量的网页进行聚类分析,在聚类之后,会形成多个类,每个类中的网页具有类似的属性,即一般具有类似的更新频率。
聚类完成后,我们可以对同一个聚类中的网页进行抽样,然后求该抽样结果的平均更新值,从而确定对每个聚类的爬行频率。
五、网页分析算法
在搜索引擎中,爬虫爬取了对应的网页之后,会将网页存储到服务器的原始数据库中,之后,搜索引擎会对这些网页进行分析并确定各网页的重要性,即会影响用户检索的排名结果。
搜索引擎的网页分析算法主要分为3类:基于用户行为的网页分析算法、基于网络拓扑的网页分析算法、基于网页内容的网页分析算法。
基于用户行为的网页分析算法
依据用户对这些网页的访问行为,对这些网页进行评价,比如,依据用户对该网页的访问频率、用户对网页的访问时长、用户的单击率等信息对网页进行综合评价。
基于网络拓扑的网页分析算法
基于网络拓扑的网页分析算法是依靠网页的链接关系、结构关系、已知网页或数据等对网页进行分析的一种算法,所谓拓扑,简单来说即结构关系的意思。
基于网络拓扑的网页分析算法,同样主要可以细分为3种类型:基于网页粒度的分析算法、基于网页块粒度的分析算法、基于网站粒度的分析算法。
PageRank算法是一种比较典型的基于网页粒度的分析算法。相信很多朋友都听过Page-Rank算法,它是谷歌搜索引擎的核心算法,简单来说,它会根据网页之间的链接关系对网页的权重进行计算,并可以依靠这些计算出来的权重,对网页进行排名。
当然,具体的算法细节有很多,在此不展开讲解。除了PageRank算法之外,HITS算法也是一种常见的基于网页粒度的分析算法。
基于网页块粒度的分析算法,也是依靠网页间链接关系进行计算的,但计算规则有所不同。
我们知道,在一个网页中通常会包含多个超链接,但一般其指向的外部链接中并不是所有的链接都与网站主题相关,或者说,这些外部链接对该网页的重要程度是不一样的,所以若要基于网页块粒度进行分析,则需要对一个网页中的这些外部链接划分层次,不同层次的外部链接对于该网页来说,其重要程度不同。
这种算法的分析效率和准确率,会比传统的算法好一些。
基于网站粒度的分析算法,也与PageRank算法类似,但是,如果采用基于网站粒度进行分析,相应的,会使用SiteRank算法。即此时我们会划分站点的层次和等级,而不再具体地计算站点下的各个网页的等级。
所以其相对于基于网页粒度的算法来说,则更加简单高效,但是会带来一些缺点,比如精确度不如基于网页粒度的分析算法精确。
基于网页内容的网页分析算法
在基于网页内容的网页分析算法中,会依据网页的数据、文本等网页内容特征,对网页进行相应的评价。
六、Python的网络爬虫原理
学python很多人告诉你说,用python写个爬虫只需要一行代码。(见图四)
爬虫的基本流程其实就是一个 HTTP 请求的过程,以浏览器访问一个网址为例,从用户输入 URL 开始,客户端通过 DNS 解析查询到目标服务器的 IP 地址,然后与之建立 TCP 连接,连接成功后,浏览器构造一个 HTTP 请求发送给服务器,服务器收到请求之后,从数据库查到相应的数据并封装成一个 HTTP 响应,然后将响应结果返回给浏览器,浏览器对响应内容进行数据解析、提取、渲染并最终展示在你面前。
HTTP 协议的请求和响应都必须遵循固定的格式,只有遵循统一的 HTTP 请求格式,服务器才能正确解析不同客户端发的请求,同样地,服务器遵循统一的响应格式,客户端才得以正确解析不同网站发过来的响应。
HTTP 请求格式
HTTP 请求由请求行、请求头、空行、请求体组成。
请求行由三部分组成:
第一部分是请求方法,常见的请求方法有 GET、POST、PUT、DELETE、HEAD
第二部分是客户端要获取的资源路径
第三部分是客户端使用的 HTTP 协议版本号
请求头是客户端向服务器发送请求的补充说明,比如 User-Agent 向服务器说明客户端的身份。
请求体是客户端向服务器提交的数据,比如用户登录时需要提高的账号密码信息。请求头与请求体之间用空行隔开。请求体并不是所有的请求都有的,比如一般的GET都不会带有请求体。
例如:(见图五)
HTTP 响应格式与请求的格式很相似,也是由响应行、响应头、空行、响应体组成。
响应行也包含三部分,分别是服务端的 HTTP 版本号、响应状态码、状态说明,响应状态码常见有 200、400、404、500、502、304 等等,一般以 2 开头的表示服务器正常响应了客户端请求,4 开头表示客户端的请求有问题,5 开头表示服务器出错了,没法正确处理客户端请求。状态码说明就是对该状态码的一个简短描述。
第二部分就是响应头,响应头与请求头对应,是服务器对该响应的一些附加说明,比如响应内容的格式是什么,响应内容的长度有多少、什么时间返回给客户端的、甚至还有一些 Cookie 信息也会放在响应头里面。
第三部分是响应体,它才是真正的响应数据,这些数据其实就是网页的 HTML 源代码。
七、反爬虫:爬虫与反爬虫的斗争
在抓取对方网站、APP 应用的相关数据时,经常会遇到一系列的方法阻止爬虫。一方面是为了保证服务的质量,另一方面是保护数据不被获取。常见的一些反爬虫和反反爬虫的手段如下。
IP 限制
服务端在一定时间内统计 IP 地址的访问次数,当次数、频率达到一定阈值时返回错误码或者拒绝服务。这种方式比较直接简单,但在 IPv4 资源越来越不足的情况下,很多用户共享一个 IP 出口,典型的如“长城宽带”等共享型的 ISP。另外手机网络中的 IP 地址也是会经常变化的,如果对这些IP地址进行阻断,则会将大量的正常用户阻止在外。
对于大多数不需要登录就可以进行访问的网站,通常也只能使用 IP 地址进行限制。比如“Freelancer 网站”,大量的公开数据可以被访问,但同一个 IP 地址的访问是有一定的限制的。针对IP地址限制非常有效的方式是,使用大量的“高匿名”代理资源。这些代理资源可以对源 P地址进行隐藏,从而让对方服务器看起来是多个 IP地址进行访问。另一种限制方式是,根据业务需要,对国内、国外的 IP 地址进行单独处理,进而对国外的高匿名代理进行阻断,例如使用海外的 IP 地址访问“天眼查网站”则无法访问。
验证码
验证码是一种非常常见的反爬虫方式。服务提供方在 IP 地址访问次数达到一定数量后,可以返回验证码让用户进行验证。这种限制在不需要登录的网页界面比较常见,它需要结合用户的 cookie 或者生成一个特殊标识对用户进行唯一性判断,以防止同一个 IP 地址访问频率过高。验证码的存在形式非常多,有简单的数字验证码、字母数字验证码、字符图形验证码,网站也可以用极验验证码等基于用户行为的验证码。针对简单验证码,可以使用打码平台进行破解。这种平台通过脚本上传验证的图片,由打码公司雇用的人工进行识别。针对极验验证等更复杂的验证码,可以尝试模拟用户的行为绕过去,但通常比较烦琐,难度较大。谷歌所用的验证码更为复杂,通常是用户端结合云端进行手工打码,但会带来整体成本较高的问题。要想绕过这些验证码的限制,一种思路是在出现验证码之前放弃访问,更换 IP 地址。ADSL 拨号代理提供了这种可能性。ADSL 通过拨号的方式上网,需要输入 ADSL 账号和密码,每次拨号就更换一个IP地址。不同地域的 P地址分布在多个地址段,如果IP地址都能使用,则意味着IP地址量级可达千万。如果我们将 ADSL 主机作为代理,每隔一段时间主机拨号一次(换一个 IP),这样可以有效防止IP地址被封禁。这种情况下,IP 地址的有效时限通常很短,通常1分钟以下。结合大量的ADSL拨号代理可以达到并行获取大量数据的可能。如果网站使用了一些特殊的唯一性的标识,则很容易被对方网站识别到,从而改进反爬虫策略,面对这种情况,单独切换 IP 地址也会无效。遇到这种情况,必须要搞清楚标识的生成方式,进而模拟真实用户的访问。
登录限制
登录限制是一种更加有效的保护数据的方式。网站或者 APP 可以展示一些基础的数据,当需要访问比较重要或者更多的数据时则要求用户必须登录。例如,在网站中,如果想要查看更多的信息,则必须用账号登录;“知乎”则是必须在登录后才能看到更多的信息。登录后,结合用户的唯一标识,可以进行计数,当访问频度、数量达到一定阈值后即可判断为爬虫行为,从而进行拦截。针对“登录限制 的方法,可以使用大量的账号进行登录,但成本通常比较高。
针对微信小程序,可以使用wx.login()方法,这种方式不需要用户的介入,因而不伤害用户的体验。小程序调用后会获取用户的唯一标识,后端可以根据这个唯一标识进行反爬虫的判断。
数据伪装
在网页上,我们可以监听流量,然后模拟用户的正常请求。mitmproxy 等工具可以监听特定网址的访问(通常是 API 的地址),然后将需要的数据存储下来。基于 Chrome Headless 的工具也可以监听到流量并进行解析。在这种情况下,某些网站会对数据进行一些伪装来增加复杂度。例如,在某网站上展示的价格为945元,在DOM树中是CSS进行了一些伪装。要想得到正确的数值,必须对 CSS 的规则进行一些计算才行。例如(见图六)
该网站使用特殊的字体对数据进行了伪装。例如,3400,对应显示的是 1400, 如如果能够找到所有的字体对应的关系,则可以逆向出正确的价格。
对于这种伪装,可以人工分析目标网站的前端代码,对CSS、Javascript和字符进行分析,推导出计算公式。在这种情况下,使用爬虫必须要非常小心,因为很可能目标网站进行改版后,规则已经发生了变化,抓取到的数据便会无效。在爬虫程序的维护上可以增加一些数据有效性的检查,通过自动化或者人工的方式进行检查。例如,针对机票数据可以检查价格是否在一个合理的区间范围内,如果超出,则认为规则已经变化。更为复杂的方案是可以借助 OCR 技术,对所需要的区域进行识别,然后对比抓取到的结果。
参数签名
设计良好的 API 通常都要对参数使用签名(sign)来驱避非法请求,常见于手机 APP。APP 通过加密算法对请求的参数进行运算,从而得到一个签名。这个签名通常和时间戳相关,并且在请求中附加上时间戳。在请求的参数固定的情况下,能够在一小段时间内生效。当请求发送到服务端后,服务端对参数、时间戳进行验证,比较签名是否一致。如果不一致,则判断为非法请求。这样做的好处是,可以保护请求,即便是被抓包,在很短时间内这个请求就会失效。获取 APP端的加密算法一般较为困难,通常需要进行反编译才能获得加密算法。然而现阶段绝大多数APP已经被加壳(典型的如360加固、爱加密等),要进行反编译都很困难。另一种保护措施是,将加密算法放到原生代码中进行编译,通常这些代码是 C 或 C++代码。由于原生代码相对于 Java 代码更难进行逆向工程,所以这给反编译又带来了更多的麻烦。
针对这种参数签名的方法,没有太好的途径能够来解决,在逆向反编译无果的 情况下,可以试着找寻有没有其他的入口,例如,HTML5、微信小程序等。如果它们请求了相同的 API,则很有可能在源代码中包含了加密算法。幸运的是,基于 Javascript 开发的应用非常容易逆向分析,能够很快地获取加密算法,从而绕过 APP 的保护机制。如果这些方法都不奏效,则可以考虑模拟用户操作应用,通过抓包的方式采集到流量中的信息。但这种方式效率较低,如果要发出多个并发的请求,往往需要多个设备同时进行。
隐藏验证
更复杂的反爬虫的方式之一是,隐藏验证。例如,在网站的防护上,通过 Javascript请求一些特殊的网址,可以得到一些特定的令牌(token),这样每次请求时即可生成不同的令牌。甚至有些网站会在不可见的图片加上一些特殊的请求参数,从而识别是否是真正的浏览器用户。这种情况下,想直接获取 API 进行请求通常行不通或者非常困难,只能通过Chrome Headless等工具模拟用户的行为,从而规避这种情况。
阻止调试
在分析某网站时发现,一旦打开浏览器的控制台界面,就会无限触发浏览器debugge指令。深入研究代码发现,该网站在一个名为 leonid-tq-jq-v3-min.js 中 给所有的构造函数都加上了 debugger 这个关键字,导致任何对象的生成都会触发调试器。这样做的目的是阻止意外的脚本或程序进行跟踪调试,从而保护代码。这种情况下,可以构建一个修改过的js文件,去掉 debugger关键字,使用 mitmproxy 转发流量并拦截 leonid-tq-jq-v3-min.js,将改后的js文件返回给浏览器,从而绕过这个限制。(见图七)
http://www.dxsbao.com/shijian/549485.html 点此复制本页地址