欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

浅谈动态爬虫与去重

来源:本站整理 作者:佚名 时间:2017-01-10 TAG: 我要投稿

0x01 简介
随着Web 2.0的发展,页面中的AJAX也越来越多。由于传统爬虫依靠静态分析,不能准确的抓取到页面中的AJAX请求以及动态更新的内容,已经越来越不能满足需求。基于动态解析的Web 2.0爬虫应运而生,通过浏览器内核解析页面源码,模拟用户操作,能有效解决上述问题。本文将详细分析利用PhantomJS + Python 编写爬虫并进行去重的思路。
0x02 PhantomJS
PhantomJS 是无界面的 Webkit 解析器,提供了 JavaScript API 。由于去除了可视化界面,速度比一般 Webkit 浏览器要快很多。同时提供了很多监控和事件接口,可以方便的操作 DOM 节点,模拟用户操作等。
接下来我们通过一个简单的例子,来展示下动态爬虫和传统爬虫的区别。目标:加载一个页面(那么,一起玩吧),并且获取其中所有的标签。
// example.js
var page = require('webpage').create();
page.onAlert = function (message) {
    console.log(message);
    return true;
};
page.onCallback = function() {
    page.evaluate(function(){
        atags = document.getElementsByTagName("a");
        for(var i=0;i
            if (atags[i].getAttribute("href")){
                alert(atags[i].getAttribute("href"));
            }
        }
    })
    phantom.exit()
};
page.open("http://named.cn/.mine", "get", "", function (status) {
    page.evaluateAsync(function(){
        if (typeof window.callPhantom === 'function') {
            window.callPhantom();
        }
    }, 10000)
});
抓取结果如下:
/.mine
/cmd2/controls/signin
/cmd2/controls/getcode
/download.html
/.blog
/.mine
/.at
/~发现推荐.findbbs
/help.html
/江南水乡.bbs/7313348
/摄情男女.bbs/7313242
/欢乐一家亲.bbs/7313356
/深夜食堂.bbs/7313168
/家有熊孩子.bbs/7313321
/乐淘亲子营.bbs/7313320
.../*省略*/...
/婚礼记.bbs/7277165
/不知道的事情.bbs/7277164
/不知道的事情.bbs/7277162
/婚礼记.bbs/7277160
/不知道的事情.bbs/7277016
http://www.miitbeian.gov.cn/
/cmd2/controls/mailpost/内容举报
download.html
静态抓取的代码如下:
import requests
import pyquery
res = requests.get("http://named.cn/.mine")
count = 0
pq = pyquery.PyQuery(res.content)
for i in pq("a"):
    print "[%d]: %s" % (count, pq(i).attr("href"))
抓取结果为空。
从上述的例子中,我们可以明显看出动态分析比静态分析抓取到了更多的结果。产生差别的原因,是页面中的数据加载来自于AJAX请求,所有的  标签都是动态更新到页面中的。静态分析对这种情况无能为力,而基于浏览器内核的动态分析,可以轻松的处理这些情况。
但也可以明显看出动态分析的缺点:系统资源占用较多,且占用时间较长,还会有一些莫名其妙的坑,编写起来也更复杂更花时间(需要对前端编程有一定的了解)。
当然除了 PhantomJS 还有一些其他的动态解析器,比如同样基于 Webkit 内核的 PyQt(PhantomJS的最新版本也是基于pyqt来实现)、基于 PhantomJS 封装的 CasperJS、基于的 Firefox Gecko 内核的SlimerJS等。由于并没有一个统一的标准,各个动态解析器的API实现程度也参差不齐,也会有各种各样的坑,并没有一个 “最佳” 的解决方案。
0x03 触发事件及页面监听
上面的例子,介绍了爬虫中常见的一个场景:在页面加载完成后,通过AJAX加载数据。但现实中的场景,往往会更复杂,需要与用户进行交互后才会触发,比如在点击了某个按钮后跳转到某个页面、滚动到页面尾部后加载下一页的数据等。我们需要新的解决方案,去模拟正常用户的操作。那么,应该如何将用户交互抽象为代码?
用户操作的本质,实际上是触发了绑定在DOM节点的事件。所以模拟用户操作的问题,可以简化为触发节点事件。事件执行的结果也是多种多样的,但对于爬虫来说,我们需要关注的结果只有两种:1. 是否添加了新的节点(、等等) 2. 是否发起了新的请求(包括AJAX请求、跳转等)。简化后,我们需要解决的问题有:
1. 如何获取绑定事件?
2. 如何触发事件?
3. 如何获取事件触发的结果?
最后我们的解决方案如下:
1. 如何获取绑定事件?JavaScript中绑定事件,都会调用addEventListener函数。在页面里的代码执行前(onInitialized | PhantomJS),hook addEventListener函数,就可以捕获到哪些DOM节点绑定了事件。
_addEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function(a,b,c) {
    EVENT_LIST.push({"event": event, "element": this})
    _addEventListener.apply(this, arguments);
};
2. 如何触发事件?JavaScript中提供了dispatchEvent函数,可以触发指定DOM节点的指定事件,也就是上一个问题中,我们收集的EVENT_LIST。
for(var i in EVENT_LIST){
    var evt = document.createEvent('CustomEvent');

[1] [2] [3] [4]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载