PhantomJS在爬虫中应用

编写爬虫时,如果单纯是静态网站,Nodejs的cheerio,requests以及Python的urlib、urlib2与request(BeautifulSoup)就能解决需求。如果碰上网站通过AJAX获取数据或者JS延迟获取数据时。上面的技术栈就比较难获取到我们想要的数据,PhantomJS这个无界面浏览器,又有人称"虚拟浏览器"就派上用场了。
Phantomjs的功能,就是提供一个命令行下使用,它是基于Webkit内核,我们可以使用像正常的浏览器访问所需的网站。在某些时候,很多的人搭配着selenium+phantomjs搭建可以访问动态获取数据的网站,现在先说phantomjs在爬虫中的用法。

  • 1.安装phantomjs
    • phantomjs是个二进制程序,可以到phantomjs官网下载。如果你安装了nodejs的npm包管理器,也可以直接运行下面命令安装:
npm install phantomjs -g
  • 2.如果是直接下载phantomjs二进制文件,还需要把程序文件的路径添加到环境变量的path里。这样方便我们直接在全局调用phantomjs。
  • 3.在windows的DOS命令行窗口,直接输入phantomjs直接开启程序,phantomjs为我们提供RPEL环境,可以直接解释javascript。
1-1
  • 4.在phantomjs提供的REPL环境下输入以下命令,可以实例输出
# >>>表示是输出行
phantomjs --version
>>>2.1.1
phantomjs>window.navigator
{
   "appCodeName": "Mozilla",
   "appName": "Netscape",
   "appVersion": "5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gec
ko) PhantomJS/2.1.1 Safari/538.1",
   "cookieEnabled": true,
   "language": "zh-CN",
   "mimeTypes": {
      "length": 0
   },
   "onLine": true,
   "platform": "Win32",
   "plugins": {
      "length": 0
   },
   "product": "Gecko",
   "productSub": "20030107",
   "userAgent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, l
ike Gecko) PhantomJS/2.1.1 Safari/538.1",
   "vendor": "Apple Computer, Inc.",
   "vendorSub": ""
}
  • 5.打开sublimetext编写一个js文件,代码如下;并且运用phantomjs运行代码文件。在阮一峰老师phantomjs文档强调,不管怎么样的程序里面,phantom.exit()这行不能少。phantom.exit()表示退出REPL环境:
#代码实例代码
function plus(a,b){
  return a*b;
}
console.log(plus(1,2));
phantom.exit()
#以下为命令行窗口运行的情况
>phantomjs spider.js
2
  • 6.webpage模块:open()
    • webpage模块是phantomjs核心的模块:可以把webpage看做一个类,通过实例化webpage类对象,然后调用对象的方法进行获取网页,最后使用类方法进行操作。
    • open(url,callback):open方法默认第一个参数为url地址,callback是回调函数,参数只有Status。无论后台服务器返回的是500或者400状态码,status的状态值都是success的值。
    • open()方法默认是以get方法获取数据;open()方法也可以使用其他的方式;例如以post方式,open(url,'post',postData,callback);open方法的第二个参数用来指定HTTP方法,第三个参数用来指定所要传递的参数。
    • 下面给出简单的完整的获取百度首页的代码:
# 这是默认get的获取方法
var webPage=require('webpage');
#设置网页的编码格式,如果不设置,会出现乱码情况
phantom.outputEncoding="gbk";
#创建一个webpage实例对象
var page=webPage.create();
var tbUrl="https://www.baidu.com";
#设置浏览器伪headers
page.settings.userAgent="Mozilla/5.0(Windows NT 6.1;Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36";
# 调用open方法打开具体网页,默认以get请求获取
page.open(tbUrl,function (status) {
   setTimeout(function(){
       var result=pageTab.evaluate(function(){
           return document.body
           
       });
       console.log(result.toString());
       pageTab.render("1.png");
       phantom.exit();
   },4000);
})
#post方法传参数获取网页数据
var webPage=require('webpage');
var page=webPage.create();
var postData="username&password"
page.open('http://www.kiwis.com/','post',postData,function(status){
 console.log(status);
 phantom.exit();
});
# open()方法提供配置对象,对HTTP请求进行详细的配置
var webPage=require('webpage');
var page=webPage.create();
var setting={
 operation:"POST",
 encoding:"urf8",
 headers:{
   "Content-Type":"application/json"
 },
 data:JSON.stringify({
   some:'something',
   others:['data1']
 })
};
page.open("http://www.kiwis.com",setting,function(status){
 console.log("Status:"+status);
 phantom.exit();
});
  • 7.webpage模块:evaluate()方法
    • evaluate(callback):evaluate方法可以在数据网页返回之后,可以直接evaluate执行javascript语句进行数据的提取和解析,这也是使用phantomjs作为爬虫提取数据的关键所在。
var webpage=require('webpage');
page=webPage.create();
page.open("https://www.baidu.com",function(status){
  var title=page.evaluate(function(){
    console.log(document.title);
    return document.title;
  });
  phantom.exit();
});
  • 8.webpage模块:onConsoleMessage():在网页内的console语句和evaluate方法内部的console语句,默认不会显示在标准输出面板,所以phantomjs模块提供了onConsoleMessage方法进行监听console的触发事件,进行输出。
var webPage=require('webpage');
var page=webPage.create();
page.onConsoleMessage(function(data){
  console.log("the pass data is"+data);
});
page.open(url,function(status){
  if(status){
    console.log("hello world!");
  }
  phantom.exit();
});
  • 9.webpage模块:includeJs()方法。
    • includeJs(resourceURL,callback)方法提供了加载外部脚本的功能,使用phantomjs的includeJs对前端jser简直是福音的存在;在提取数据时可以直接加载jQuery库操作;以前在使用后端服务的Nodejs的Request和cheerio(服务端的jquery)脚本爬虫时会觉得提取XML或HTML中的数据时还担心前端jquery语法和cheerio不兼容;现在麻麻再也不用担心啦。
    • includeJs方法在加载完成外部资源或者脚本之后就自动调用回调函数。
var webPage=require('webpage');
var page=webPage.create();
page.open("https://www.baidu.com",function(status){
  page.includeJs("https://code.jquery.com/jquery-3.2.1.min.js",function(){
    page.evaluate(function(){
      $('.su').click();
    });
  });
});
  • 10.webpage模块:render():
    • render方法用于将网页保存成图片,参数就是要保存的图片路径。方法可以根据路径的后缀名,将网页保存成png、Gif、jpeg和pdf。方法可以接受一个配置对象,format字段用于图片格式,quality字段用于图片质量,最差是0,最好是100;renderBase64方法就是把截图png格式编码成Base64格式的字符串输出。
var webPage=require("webpage");
var page=webPage.create();
page.viewportSize={widtth:960,height:580};
page.open("http://www.baidu.com",function(status){
  page.render("1.png",{format:"png",quality:"100"});
  phantom.exit()
});
  • 11.webpage模块:viewportSize,zoomFactor
    • viewportSize属性是指定打开的浏览器窗口大小(如上节所示),即网页的初始化浏览器窗口大小。viewportSize的height字段是必须参数,不可省略。
    • zoomFactor属性指定渲染页面的放大系数(1即100%)
var webPage=require('webpage');
var page=webPage.create();
page.viewportISize={
  width:920,
  height:480
};
page.zoomFactor=1;
page.render("1.png");
  • 12.webpage模块:onResouceRequested
    • onResourceRequested属性用来指定一个回调函数,当页面请求一个资源时,会触发这个回调函数。第一个参数是HTTP请求的数据对象,第二个参数是发出的网络请求对象。
    • http请求数据:
      • id:请求资源编号
      • method:使用http方法
      • url:所请求的资源url
      • headers:http头信息数组
    • 网络请求对象包含以下方法:
      • abort():终止当前网络请求,网络请求终止会触发onResourceError回调函数
      • changeUrl(newUrl):改变当前网络请求的URL
      • setHeader(key,value):设置http头信息
var webPage=require('webpage');
var page=webPage.create();
page.onResourceRequested=function(requestData,RequestObj){
  console.log('request'+requestData.id+'----'+JSON.stringify(requestData));
}
//过滤资源应用
page.onResourceRequested=function(requestData,RequestObj){
  if((/http:\/\/.+?\.css$/gi).test(requestData['url'])){
    console.log("abort this resource");
    request.abort();
  }
}
  • 13.webpage模块:onResourceReceived
    • onResourceReceived属性用于指定一个回调函数,当网页收到所请求的资源时,就会执行该回调函数。它的参数就是服务器发来的HTTP回应的元数据对象。如果http回应非常大,分成多个数据块发送,onResourceReceived会在多次收到数据块时触发回调函数。
    • 元数据对象包含以下字段:
      • id:所请求的资源编号
      • url:所请求资源的url
      • time:包含http回应时间的Date对象
      • headers:http头信息数组
      • bodySize:解压缩的收到的内容大小
      • content-Type:接到的内容种类
      • redirectURL:重定向URL(如果有的话)
      • stage:对多数据块的http响应
      • status:HTTP状态码,如404,200
      • statusText:http状态信息,比如OK
var webPage=require('webpage');
var page=webPage.create();
page.onResourceReceived=function(response){
  console.log("response"+response.status+response.statusText);
}
  • 14.System模块:system模块可以加载操作系统变量,System.args就是参数数组。
var webpage=require('webpage')
var system=require('system');
var t,address;
//如果命令行没有给出网址
if(system.args.length===1){
  console.log("the url address is need!");
  phantom.exit();
}
t=Date.now();
address=system.args[1];
page.open(address,function(status){
  if(status!=="success"){
    console.log("failed to get webpage");
  }else{
    t=Date.now()-t;
    console.log("Loading time"+t+"ms");
  }
phantom.exit();
});
var webPage=require('webpage');
//设置网页编码格式
phantom.outputEncoding="gbk";
var pageTab=webPage.create();
var tbUrl="http://www.360kan.com/";
//设置请求头信息
pageTab.settings.userAgent="Mozilla/5.0(Windows NT 6.1;Win64;x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36";
pageTab.open(tbUrl,function (status) {
//360kan网址的数据是动态加载的,这里等待2秒在执行其他操作。
    setTimeout(function(){
        pageTab.includeJs("http://code.jquery.com/jquery-3.2.1.min.js", function() {
            pageTab.evaluate(function() {
              var lists=$(".name");
              for(i=0;i<lists.length;i++){
                var list=lists[i];
                console.log(lists.text()+"\n");
              }
            });
            phantom.exit()
        });
    },2000);
})
pageTab.onConsoleMessage = function(msg) {
  console.log('Page title is ' + msg);
};
抓取的数据
  • 16.Phantomjs官方翻译文档示例:
    • setting.userAgent指定http请求的userAgent头信息
    • setting.viewportSize:z指定浏览器窗口的大小
    • clipRect:指定截图的大小,第一参数top(距离浏览器上面多少距离);第二参数是left(距离左边多少);width和height从字面可以知道是宽高大小。
var webpage=require('webpage');
var page=webpage.create();
page.setting.UserAgent="webkit/534.46 Mobile/9A405 safari/7534.48.3";
page.setting.viewportSize={width:400,height:600};
page.open("http://www.baidu.com",function(status){
  if(status!=="success"){
    console.log("load failed");
    phantom.exit();
  }else{
    var title=page.evaluate(function(){
      return document.title;
    });
    window.setTimeout(function(){
      page.clipRect={top:0,left:0,width:600,height:400};
      page.render(title+".png");
      page.clipRect={left:0,top:600,width:400,height:400};
      page.render(title+"1.png");
      phantom.exit();
    });
  }
});

上面是phantomjs的常用使用方法,下一篇关于selenium2和phantomjs结合使用爬虫js延迟或者AJAX获取数据的提取方式实例。

资料参考来自:
1.阮一峰老师 phantomJS
2.腾云阁社区关于phantomjs使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • phantomjs实现了一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canva...
    卍卍_卐卐阅读 38,221评论 1 13
  • 前言 大家有没有发现之前我们写的爬虫都有一个共性,就是只能爬取单纯的html代码,如果页面是JS渲染的该怎么办呢?...
    追不到的那缕风阅读 2,948评论 1 5
  • 公益广告: 原图: 商业广告: 原图: 风景: 原图: 使用APP:Prisma、PicsArt、美图秀秀 使用
    刀镓鑫阅读 174评论 0 0
  • 宝贝今天进行了打泡泡的工作。不妨将观察的重心放在收拾整理上。因为操作过程中,宝贝将盆子里的水全洒在托盘里,于是老师...
    CASA三班阅读 305评论 0 1