最近一直忙于团建的工作,能够完全静下心来的时间也比较短,但团队的分享约定不能忘,同时也为了欢迎即将入队的一位新成员,在这里跟大家分享下Web2.0爬虫的一些技术点,希望对大家有些帮助,大家可以结合【这篇文章】一起来看,收获应该会更大,对其实Web2.0爬虫这个概念出来很久了,早在2008年就有人提及到并实现,主流的思路还是基于浏览器框架来进行构建,我在12年写的WatScan扫描器也是用基于Webkit浏览器的原理来实现的,运行了一年多,但其爬行的效果却并不是理想,中间也作了不少改进,由于 Web2.0下各种标签的事件众多,脚本的形式也比较多样,让Web2.0扫描器很难达到通用的标准,经常需要为这些异常情况去完善和改进,只能说具备Web2.0的这些功能,在真实环境中的爬取却并不那么理想,主要问题还是在于爬行效率和页面状态的触发深度,不过随着Ajax应用的丰富,为扫描器增加Web2.0爬取功能也是个不错的选择。
什么是Web2.0爬虫,在Web1.0时代,网站主要都是基于静态页面构建,但伴随着Ajax技术的发展,到了Web2.0时代,Web站点的架构发生了变化,融入了更多的动态交互和事件触发,这也就给传统Web爬虫提出挑战,因为在传统Web爬虫的视角,每一个URL即代表了站点的一个不同页面,而URL也是可以很容易的通过正则进行匹配获取;但在Ajax应用中,这种情况发生了改变,一个页面中有着不同的状态,需要通过JavaScript来进行触发才能获取,传统爬虫是无法进行感知和爬取;为了弥补传统爬虫的不足和解决Ajax技术所带来的难题,Web2.0爬虫的概念也就被提出来了;那么什么是Web2.0爬虫,它的特点是什么呢?在知道技术产生的背景后,这里我们首先需要清楚Ajax的工作方式和特点,AJAX不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web 应用程序的技术,使用Javascript向服务器提出请求并处理响应而不阻塞用户,核心对象XMLHTTPRequest。通过这个对象,您的 JavaScript 可在不重载页面的情况与Web服务器交换数据,说通俗点,AJAX其实就是一种异步通讯请求,允许页面内容可以动态加载,从而导致最终展现在浏览器终端的不是整个页面,只是页面的某个状态。因而要想实现Web2.0的有效爬取,就需要模拟Ajax引擎,解决下面五个主要问题:
- 执行JavaScript代码。由于Ajax应用的功能实现依赖于JavaScript代码在Web客户端的执行,因此Ajax爬虫必须能够执行JavaScript代码,所以需要添加一个JavaScript脚本解释器
- 页面DOM树操作,对页面内容进行DOM树解析,可以对标签进行动态的操作
- 页面事件触发,由于一些标签会包含事件属性,需要对这些事件触发,才能获取到更完整的页面。
- 页面状态保持,传统的Web站点中每一个URL标志一个静态页面;而在Ajax应用中,一个页面可能有很多状态变化,每当触发一个事件,都会导致页面的变化,因而Ajax爬虫需要记录这些页面状态,以便对变化的页面进行链接爬取
- 重复事件识别,Ajax应用中某些事件可能都是由同一个JavaScript函数来处理,触发这些事件可能导致相同状态,而这些重复的状态会造成服务器的过度负载;而且当同一页面在进行状态变化时,我们也需要记录和识别这些重复事件,避免重复触发和爬取。
说了那么多理论,我们来看下具体的实践,省去了爬虫的实现框架细节,这里主要介绍下Ajax爬虫的实现,为了降低技术难度,这里主要使用浏览器作为Ajax引擎,这样就可以很解决上述的三个难点,页面状态的深度设置为2(注:这里解释下什么是页面状态深度,就是说对当前页面进行事件触发的时候,新产生的内容仍然存在需要事件触发的事件才能完整的获取页面内容,每一次事件触发所产生的页面变化称之为一个深度),因为再深会影响爬行效率,简单的实现算法如下:
CrawlAjax(url): Browser.init() Urls_out=[] While True: Dom,State=Browser.open(url) Browser.setState(State) Content = Dom.getHtml() Events =Dom.getEvents() Urls = Dom.getUrls() For depth1 in Events: newDom,State = Browser.doEvent(depth1) Browser. setState(State) Browser.loadState() newurls = newDom.getNewUrls() urls_out.extend(newurls) NewEvents = newDom.getNewEvents() For depth2 in NewEvents: newDom, State =Browser.doEvent(depth2) Browser. setState(State) newurls=newDom.getNewUrls() Urls_out.extend(newurls)
下面是我早前用python实现的Ajax爬虫,实现中难免存在一些不足,大家可以感受下浏览器爬虫的爬行特点。【WatCrawler.zip】解压密码:wat。
转自:http://www.imiyoo.com/webscan/2014/09/23/271.html
SuperSpider——打造功能强大的爬虫利器
博文作者:加菲
发布日期:2013-12-11
阅读次数:49366
博文内容:
1.爬虫的介绍
图1-1 爬虫(spider)
网络爬虫(web spider)是一个自动的通过网络抓取互联网上的网页的程序,在当今互联网中得到越来越广泛的使用。这种技术一般用来爬取网页中链接,资源等,当然,更为高级的技术是把网页中的相关数据保存下来,成为搜索引擎,例如著名的google和百度。常见的爬虫应用还有像一淘这样的比价网站,电影推荐网站等。
为了让大家进一步感受到爬虫的魅力,笔者编写了一个爬取淘宝和京东数据的比价网站(http://jiafei.org:8888/),如图1-2所示。由于淘宝和京东的搜索结果页面中有部分内容引(如价格)是通过ajax动态获得的,再用javascript把内容写入到相应的标签中的,当搜索Iphone 5s时,后台爬虫利用webkit生成去最终的dom树,爬取有用的数据,经过简单的处理后返回相应的结果。
图1-2 一个简单的比较网站
2.为何需要爬虫
爬虫对于扫描器来说至关重要,站在整个扫描器的最前线(如图2-1所示)。在一个专业扫描器中,一般首先会由爬虫爬取指定的页面,接着把爬到的url传递给调度server,最后由调度server分发需要扫描的url给扫描agent来完成整个扫描过程。
图2-1 扫描器的组成
2.爬虫的架构与分析
Web安全对于互联网公司来说至关重要,为了让公司的扫描器与业界的扫描器看齐,server安全组自研了一款功能强大的爬虫——SuperSpider,主要用来为漏洞扫描提供丰富的urls。SuperSpider的架构如图3-1所示,首先由下载器模块下载指定的页面,分析页面模块分析完成后一方面把需要的数据传递给存储模块,另一方面将爬取的urls传递给去重模块,去重后放到url队列中,最后由调度器安排次序传递url给下载器下载新的页面。接下来详细讲讲分析页面,调度器和去重这3个模块。
图3-1 爬虫的架构
3.1分析页面
简单的来说, 爬虫主要作用就是用来分析页面。
难点:因为现在是web2.0时代,绝大部分网页都会使用javascript处理页面,而且很多网页内容都是通过Ajax技术加载的。因此,只是简单地解析HTML文件会远远不够。
解决:如何做到这点?编写一个基于webkit的爬虫SuperSpider。下面将详细说明SuperSpider所具有的5个功能强大的爬取能力。
a. 静态页面链接分析
简单点来说,就是分析html文档,例如下图的一个<a>标签的超链接,SuperSpider会识别出href中的值为一个超链接,提取其值html_link.php?id=1。
b. javascript动态解析
下图为一段javascript代码,该代码的目的是在id为hi的a标签中提交属性href。
SuperSpider利用webkit内核执行以上javascript代码生成出以下html代码,再通过静态页面链接分析获取js_link.php?id=1&msg=abc这个url。
c. 自动分析表单
SuperSpider会自动识别出action中的值为所提交的地址,提取input标签中的name和value作为参数,最终生成出 post_link.php?id=1&msg=abc 这个url。
d. 自动交互
自动交换就是说要模仿出人的行为,例如点击鼠标,按下回车键等,下图就是一个需要点击鼠标的例子。
SuperSpider会自动识别出onclick是一个交换行为,从而执行里面的js代码生成出以下html,从而爬到了 click_link.php?id=1 这个url。
e. hook所有的网络请求
这是一个ajax请求,有别于以上4种基于dom树解析的分析技术,要捉到其请求的url只能通过hook请求,而webkit文档中并没有提到hook 网络请求的方法。于是通过修改webkit代码hook住每一个由webkit发送出去的请求,从而拿到了 ajax_link.php?id=1&t=1这个url。
3.2调度器
SuperSpider的调度器使用广度优先搜索策略,具体的逻辑如下图所示。首先,从入口页面1.html中爬到了2.html, 3.html和4.html,依次把它们放到url队列中。接着取出2.html,把爬到的5.html和6.html放到url队列中,随后便开始爬取3.html,依广度次序进行。
图3-2-1 爬虫调度的广度优先搜索策略
3.3去重
为了扫描的质量和效率,需要进行去重。例如大部分网站中日期作为其url的组成部分,尤其是门户网站。SuperSpider使用将数字替换成d+的算法对url进行去重。例如,
1.http://video.sina.com.cn/ent/s/h/2010-01-10/163961994.shtml?a=1&b=10
2.http://video.sina.com.cn/ent/s/h/2009-12-10/16334456.shtml?a=12&b=67
对数字进行模式处理为:
http://video.sina.com.cn/ent/s/h/d+-d+-d+/d+.shtml?a=d+&b=d+
如果链接1已经爬取过,链接2与链接1类似, 不重复爬取。
试验证明这种方法简捷高效,漏爬率极低,大大提升扫描器的效率。
4.爬虫的具体实现
a.webkit的易用性
常用的chrome, safari等浏览器都是基于webkit内核,不过提起这个内核,大家可能会觉得有点庞大艰深。但如果只是对于应用层面来说,webkit使用起来还是挺简易的。如图4-1所示,只需14行便可以写出一个浏览器。
图4-1 使用webkit编写的浏览器
b.难点解决
问题:Webkit需要视窗系统才能正常启动,而服务器一般都没有视窗系统的,那么如何在后台稳定地运行webkit?之前是去掉webkit中的图形渲染,css等与gui有关的代码,太麻烦,易出众多bug。
解决:使用xvfb虚拟出一个视窗系统,只需把alert, confirm, prompt的代码注释掉(因为会让浏览器卡住),简单快捷稳定。
c.爬虫的逻辑代码
图4-2为爬虫的逻辑代码,在parse函数里利用webkit生成出来的dom树来做具体的第三部分所提到的分析逻辑。
图4-2 爬虫的逻辑代码
5.效果
SuperSpider与wvs的爬虫对比,在著名的爬虫测试平台http://demo.aisec.cn/demo/进行测试,该平台要求爬虫要完全具备3.1所提到的5个功能才能爬取到所有的url,上图为扫描器的爬虫,下图为wvs的爬虫, 其中click_link.php (在3.1.d提到)是需要爬虫具有自动交换能力才能爬取到的。
结论:SuperSpider全部都能爬到, 在自动交互方面比wvs表现更好
图4-1 SuperSpider与wvs的结果对比
6.结尾
以上笔者的一些思考与总结,欢迎大牛们的意见和建议!
转载请注明:jinglingshu的博客 » Web扫描器科普系列:Web2.0爬虫