美文网首页我爱编程
PhantomJS在爬虫中应用

PhantomJS在爬虫中应用

作者: Evtion | 来源:发表于2017-09-20 15:35 被阅读0次

编写爬虫时,如果单纯是静态网站,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使用

相关文章

网友评论

    本文标题:PhantomJS在爬虫中应用

    本文链接:https://www.haomeiwen.com/subject/abzajxtx.html