PhantomJS在爬蟲中應(yīng)用

編寫爬蟲時,如果單純是靜態(tài)網(wǎng)站驼仪,Nodejs的cheerio,requests以及Python的urlib懂牧、urlib2與request(BeautifulSoup)就能解決需求。如果碰上網(wǎng)站通過AJAX獲取數(shù)據(jù)或者JS延遲獲取數(shù)據(jù)時有序。上面的技術(shù)棧就比較難獲取到我們想要的數(shù)據(jù)握巢,PhantomJS這個無界面瀏覽器晕鹊,又有人稱"虛擬瀏覽器"就派上用場了。
Phantomjs的功能,就是提供一個命令行下使用捏题,它是基于Webkit內(nèi)核玻褪,我們可以使用像正常的瀏覽器訪問所需的網(wǎng)站。在某些時候公荧,很多的人搭配著selenium+phantomjs搭建可以訪問動態(tài)獲取數(shù)據(jù)的網(wǎng)站带射,現(xiàn)在先說phantomjs在爬蟲中的用法。

  • 1.安裝phantomjs
    • phantomjs是個二進制程序循狰,可以到phantomjs官網(wǎng)下載窟社。如果你安裝了nodejs的npm包管理器,也可以直接運行下面命令安裝:
npm install phantomjs -g
  • 2.如果是直接下載phantomjs二進制文件绪钥,還需要把程序文件的路徑添加到環(huán)境變量的path里灿里。這樣方便我們直接在全局調(diào)用phantomjs。
  • 3.在windows的DOS命令行窗口程腹,直接輸入phantomjs直接開啟程序匣吊,phantomjs為我們提供RPEL環(huán)境,可以直接解釋javascript寸潦。
1-1
  • 4.在phantomjs提供的REPL環(huán)境下輸入以下命令色鸳,可以實例輸出
# >>>表示是輸出行
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文檔強調(diào),不管怎么樣的程序里面斩箫,phantom.exit()這行不能少吏砂。phantom.exit()表示退出REPL環(huán)境:
#代碼實例代碼
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類對象乘客,然后調(diào)用對象的方法進行獲取網(wǎng)頁狐血,最后使用類方法進行操作。
    • open(url,callback):open方法默認第一個參數(shù)為url地址易核,callback是回調(diào)函數(shù)氛雪,參數(shù)只有Status。無論后臺服務(wù)器返回的是500或者400狀態(tài)碼耸成,status的狀態(tài)值都是success的值。
    • open()方法默認是以get方法獲取數(shù)據(jù)浴鸿;open()方法也可以使用其他的方式井氢;例如以post方式,open(url,'post',postData,callback)岳链;open方法的第二個參數(shù)用來指定HTTP方法花竞,第三個參數(shù)用來指定所要傳遞的參數(shù)。
    • 下面給出簡單的完整的獲取百度首頁的代碼:
# 這是默認get的獲取方法
var webPage=require('webpage');
#設(shè)置網(wǎng)頁的編碼格式,如果不設(shè)置约急,會出現(xiàn)亂碼情況
phantom.outputEncoding="gbk";
#創(chuàng)建一個webpage實例對象
var page=webPage.create();
var tbUrl="https://www.baidu.com";
#設(shè)置瀏覽器偽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";
# 調(diào)用open方法打開具體網(wǎng)頁零远,默認以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方法傳參數(shù)獲取網(wǎng)頁數(shù)據(jù)
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方法可以在數(shù)據(jù)網(wǎng)頁返回之后厌蔽,可以直接evaluate執(zhí)行javascript語句進行數(shù)據(jù)的提取和解析牵辣,這也是使用phantomjs作為爬蟲提取數(shù)據(jù)的關(guān)鍵所在。
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():在網(wǎng)頁內(nèi)的console語句和evaluate方法內(nèi)部的console語句奴饮,默認不會顯示在標(biāo)準輸出面板纬向,所以phantomjs模塊提供了onConsoleMessage方法進行監(jiān)聽console的觸發(fā)事件,進行輸出戴卜。
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簡直是福音的存在投剥;在提取數(shù)據(jù)時可以直接加載jQuery庫操作师脂;以前在使用后端服務(wù)的Nodejs的Request和cheerio(服務(wù)端的jquery)腳本爬蟲時會覺得提取XML或HTML中的數(shù)據(jù)時還擔(dān)心前端jquery語法和cheerio不兼容;現(xiàn)在麻麻再也不用擔(dān)心啦江锨。
    • includeJs方法在加載完成外部資源或者腳本之后就自動調(diào)用回調(diào)函數(shù)吃警。
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方法用于將網(wǎng)頁保存成圖片,參數(shù)就是要保存的圖片路徑泳桦。方法可以根據(jù)路徑的后綴名汤徽,將網(wǎng)頁保存成png、Gif灸撰、jpeg和pdf谒府。方法可以接受一個配置對象,format字段用于圖片格式浮毯,quality字段用于圖片質(zhì)量完疫,最差是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屬性是指定打開的瀏覽器窗口大小(如上節(jié)所示),即網(wǎng)頁的初始化瀏覽器窗口大小。viewportSize的height字段是必須參數(shù)饰迹,不可省略芳誓。
    • zoomFactor屬性指定渲染頁面的放大系數(shù)(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屬性用來指定一個回調(diào)函數(shù),當(dāng)頁面請求一個資源時啊鸭,會觸發(fā)這個回調(diào)函數(shù)锹淌。第一個參數(shù)是HTTP請求的數(shù)據(jù)對象,第二個參數(shù)是發(fā)出的網(wǎng)絡(luò)請求對象赠制。
    • http請求數(shù)據(jù):
      • id:請求資源編號
      • method:使用http方法
      • url:所請求的資源url
      • headers:http頭信息數(shù)組
    • 網(wǎng)絡(luò)請求對象包含以下方法:
      • abort():終止當(dāng)前網(wǎng)絡(luò)請求赂摆,網(wǎng)絡(luò)請求終止會觸發(fā)onResourceError回調(diào)函數(shù)
      • changeUrl(newUrl):改變當(dāng)前網(wǎng)絡(luò)請求的URL
      • setHeader(key,value):設(shè)置http頭信息
var webPage=require('webpage');
var page=webPage.create();
page.onResourceRequested=function(requestData,RequestObj){
  console.log('request'+requestData.id+'----'+JSON.stringify(requestData));
}
//過濾資源應(yīng)用
page.onResourceRequested=function(requestData,RequestObj){
  if((/http:\/\/.+?\.css$/gi).test(requestData['url'])){
    console.log("abort this resource");
    request.abort();
  }
}
  • 13.webpage模塊:onResourceReceived
    • onResourceReceived屬性用于指定一個回調(diào)函數(shù),當(dāng)網(wǎng)頁收到所請求的資源時,就會執(zhí)行該回調(diào)函數(shù)烟号。它的參數(shù)就是服務(wù)器發(fā)來的HTTP回應(yīng)的元數(shù)據(jù)對象绊谭。如果http回應(yīng)非常大,分成多個數(shù)據(jù)塊發(fā)送汪拥,onResourceReceived會在多次收到數(shù)據(jù)塊時觸發(fā)回調(diào)函數(shù)达传。
    • 元數(shù)據(jù)對象包含以下字段:
      • id:所請求的資源編號
      • url:所請求資源的url
      • time:包含http回應(yīng)時間的Date對象
      • headers:http頭信息數(shù)組
      • bodySize:解壓縮的收到的內(nèi)容大小
      • content-Type:接到的內(nèi)容種類
      • redirectURL:重定向URL(如果有的話)
      • stage:對多數(shù)據(jù)塊的http響應(yīng)
      • status:HTTP狀態(tài)碼,如404,200
      • statusText:http狀態(tài)信息喷楣,比如OK
var webPage=require('webpage');
var page=webPage.create();
page.onResourceReceived=function(response){
  console.log("response"+response.status+response.statusText);
}
  • 14.System模塊:system模塊可以加載操作系統(tǒng)變量趟大,System.args就是參數(shù)數(shù)組。
var webpage=require('webpage')
var system=require('system');
var t,address;
//如果命令行沒有給出網(wǎng)址
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');
//設(shè)置網(wǎng)頁編碼格式
phantom.outputEncoding="gbk";
var pageTab=webPage.create();
var tbUrl="http://www.360kan.com/";
//設(shè)置請求頭信息
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網(wǎng)址的數(shù)據(jù)是動態(tài)加載的铣焊,這里等待2秒在執(zhí)行其他操作逊朽。
    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);
};
抓取的數(shù)據(jù)
  • 16.Phantomjs官方翻譯文檔示例:
    • setting.userAgent指定http請求的userAgent頭信息
    • setting.viewportSize:z指定瀏覽器窗口的大小
    • clipRect:指定截圖的大小,第一參數(shù)top(距離瀏覽器上面多少距離)曲伊;第二參數(shù)是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的常用使用方法坟募,下一篇關(guān)于selenium2和phantomjs結(jié)合使用爬蟲js延遲或者AJAX獲取數(shù)據(jù)的提取方式實例岛蚤。

資料參考來自:
1.阮一峰老師 phantomJS
2.騰云閣社區(qū)關(guān)于phantomjs使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市懈糯,隨后出現(xiàn)的幾起案子涤妒,更是在濱河造成了極大的恐慌,老刑警劉巖赚哗,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件她紫,死亡現(xiàn)場離奇詭異,居然都是意外死亡屿储,警方通過查閱死者的電腦和手機贿讹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來够掠,“玉大人民褂,你說我怎么就攤上這事》杼叮” “怎么了赊堪?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竖哩。 經(jīng)常有香客問我雹食,道長,這世上最難降的妖魔是什么期丰? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上钝荡,老公的妹妹穿的比我還像新娘街立。我一直安慰自己,他們只是感情好埠通,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布赎离。 她就那樣靜靜地躺著,像睡著了一般端辱。 火紅的嫁衣襯著肌膚如雪梁剔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天舞蔽,我揣著相機與錄音荣病,去河邊找鬼。 笑死渗柿,一個胖子當(dāng)著我的面吹牛个盆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朵栖,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼颊亮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陨溅?” 一聲冷哼從身側(cè)響起终惑,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎门扇,沒想到半個月后雹有,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡悯嗓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年件舵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脯厨。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡铅祸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出合武,到底是詐尸還是另有隱情临梗,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布稼跳,位于F島的核電站盟庞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汤善。R本人自食惡果不足惜什猖,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一票彪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧不狮,春花似錦降铸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驻仅,卻和暖如春谅畅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背噪服。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工毡泻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芯咧。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓牙捉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敬飒。 傳聞我的和親對象是個殘疾皇子邪铲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容

  • phantomjs實現(xiàn)了一個無界面的webkit瀏覽器。雖然沒有界面无拗,但dom渲染带到、js運行、網(wǎng)絡(luò)訪問英染、canva...
    卍卍_卐卐閱讀 38,523評論 1 13
  • 前言 大家有沒有發(fā)現(xiàn)之前我們寫的爬蟲都有一個共性揽惹,就是只能爬取單純的html代碼,如果頁面是JS渲染的該怎么辦呢四康?...
    追不到的那縷風(fēng)閱讀 2,998評論 1 5
  • 公益廣告: 原圖: 商業(yè)廣告: 原圖: 風(fēng)景: 原圖: 使用APP:Prisma搪搏、PicsArt、美圖秀秀 使用
    刀鎵鑫閱讀 189評論 0 0
  • 寶貝今天進行了打泡泡的工作闪金。不妨將觀察的重心放在收拾整理上疯溺。因為操作過程中,寶貝將盆子里的水全灑在托盤里哎垦,于是老師...
    CASA三班閱讀 336評論 0 1