PhantomJS用法示例


收錄待用,修改轉載已取得騰訊雲授權


前言

大家有沒有發現之前我們寫的爬蟲都有一個共性,就是只能爬取單純的html代碼,如果頁面是JS渲染的該怎么辦呢?如果我們單純去分析一個個后台的請求,手動去摸索JS渲染的到的一些結果,那簡直沒天理了。所以,我們需要有一些好用的工具來幫助我們像瀏覽器一樣渲染JS處理的頁面。

其中有一個比較常用的工具,那就是

PhantomJS

Full web stack No browser required
PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast andnative support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.
PhantomJS是一個無界面的,可腳本編程的WebKit瀏覽器引擎。它原生支持多種web 標准:DOM 操作,CSS選擇器,JSON,Canvas 以及SVG。

好,接下來我們就一起來了解一下這個神奇好用的庫的用法吧。

ps:服務器是騰訊雲

安裝

PhantomJS安裝方法有兩種,一種是下載源碼之后自己來編譯,另一種是直接下載編譯好的二進制文件。然而自己編譯需要的時間太長,而且需要挺多的磁盤空間。官方推薦直接下載二進制文件然后安裝。

大家可以依照自己的開發平台選擇不同的包進行下載

下載地址

當然如果你不嫌麻煩,可以選擇

下載源碼

然后自己編譯。

目前(2016/3/21)最新發行版本是 v2.1,

安裝完成之后命令行輸入

phantomjs -v

如果正常顯示版本號,那么證明安裝成功了。如果提示錯誤,那么請重新安裝。

本文介紹大部分內容來自於官方文檔,博主對其進行了整理,學習更多請參考

官方文檔

快速開始

第一個程序

第一個程序當然是Hello World,新建一個 js 文件。命名為 helloworld.js

console.log('Hello, world!');
phantom.exit();

命令行輸入

phantomjs helloworld.js

程序輸出了 Hello,world!程序第二句話終止了 phantom 的執行。

注意:phantom.exit();這句話非常重要,否則程序將永遠不會終止。

頁面加載

可以利用 phantom 來實現頁面的加載,下面的例子實現了頁面的加載並將頁面保存為一張圖片。

var page = require('webpage').create();
page.open('http://cuiqingcai.com', function (status) {
    console.log("Status: " + status);
    if (status === "success") {
        page.render('example.png');
    }
    phantom.exit();
});

首先創建了一個webpage對象,然后加載本站點主頁,判斷響應狀態,如果成功,那么保存截圖為example.png

以上代碼命名為 pageload.js,命令行

phantomjs pageload.js

發現執行成功,然后目錄下多了一張圖片,example.png

因為這個 render 方法,phantom 經常會用到網頁截圖的功能。

測試頁面加載速度

下面這個例子計算了一個頁面的加載速度,同時還用到了命令行傳參的特性。新建文件保存為loadspeed.js

var page = require('webpage').create(),
  system = require('system'),
  t, address;

if (system.args.length === 1) {
  console.log('Usage: loadspeed.js <some URL>');
  phantom.exit();
}

t = Date.now();
address = system.args[1];
page.open(address, function(status) {
  if (status !== 'success') {
    console.log('FAIL to load the address');
  } else {
    t = Date.now() - t;
    console.log('Loading ' + system.args[1]);
    console.log('Loading time ' + t + ' msec');
  }
  phantom.exit();
});

程序判斷了參數的多少,如果參數不夠,那么終止運行。然后記錄了打開頁面的時間,請求頁面之后,再紀錄當前時間,二者之差就是頁面加載速度。

phantomjs loadspeed.js http://cuiqingcai.com

運行結果

Loading http://cuiqingcai.com
Loading time 11678 msec

這個時間包括JS渲染的時間,當然和網速也有關。

代碼評估

To evaluate JavaScript code in the context of the web page, use evaluate() function. The execution is “sandboxed”, there is no way for the code to access any JavaScript objects and variables outside its own page context. An object can be returned from evaluate(), however it is limited to simple objects and can’t contain functions or closures.

利用 evaluate 方法我們可以獲取網頁的源代碼。這個執行是“沙盒式”的,它不會去執行網頁外的 JavaScript 代碼。evalute 方法可以返回一個對象,然而返回值僅限於對象,不能包含函數(或閉包)

var url = 'http://www.baidu.com';
var page = require('webpage').create();
page.open(url, function(status) {
  var title = page.evaluate(function() {
    return document.title;
  });
  console.log('Page title is ' + title);
  phantom.exit();
});

以上代碼獲取了百度的網站標題。

Page title is 百度一下,你就知道

任何來自於網頁並且包括來自evaluate()內部代碼的控制台信息,默認不會顯示。

需要重寫這個行為,使用 onConsoleMessage 回調函數,示例可以改寫成

var url = 'http://www.baidu.com';
var page = require('webpage').create();
page.onConsoleMessage = function (msg) {
    console.log(msg);
};
page.open(url, function (status) {
    page.evaluate(function () {
        console.log(document.title);
    });
    phantom.exit();
});

這樣的話,如果你用瀏覽器打開百度首頁,打開調試工具的console,可以看到控制台輸出信息。

重寫了 onConsoleMessage 方法之后,可以發現控制台輸出的結果和我們需要輸出的標題都打印出來了。

一張網頁,要經歷怎樣的過程,才能抵達用戶面前?
一位新人,要經歷怎樣的成長,才能站在技術之巔?
探尋這里的秘密;
體驗這里的挑戰;
成為這里的主人;
加入百度,加入網頁搜索,你,可以影響世界。

請將簡歷發送至 %c ps_recruiter@baidu.com( 郵件標題請以“姓名-應聘XX職位-來自console”命名) color:red
職位介紹:http://dwz.cn/hr2013
百度一下,你就知道

啊,我沒有在為百度打廣告!

屏幕捕獲

Since PhantomJS is using WebKit, a real layout and rendering engine, it can capture a web page as a screenshot. Because PhantomJS can render anything on the web page, it can be used to convert contents not only in HTML and CSS, but also SVG and Canvas.

因為 PhantomJS 使用了 WebKit內核,是一個真正的布局和渲染引擎,它可以像屏幕截圖一樣捕獲一個web界面。因為它可以渲染網頁中的人和元素,所以它不僅用到HTML,CSS的內容轉化,還用在SVG,Canvas。可見其功能是相當強大的。

下面的例子就捕獲了github網頁的截圖。上文有類似內容,不再演示。

var page = require('webpage').create();
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

除了 png 格式的轉換,PhantomJS還支持 jpg,gif,pdf等格式。

測試樣例

其中最重要的方法便是 viewportSize 和 clipRect 屬性。

viewportSize 是視區的大小,你可以理解為你打開了一個瀏覽器,然后把瀏覽器窗口拖到了多大。

clipRect 是裁切矩形的大小,需要四個參數,前兩個是基准點,后兩個參數是寬高。

通過下面的小例子感受一下。

var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
//the clipRect is the portion of the page you are taking a screenshot of
page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };
//the rest of the code is the same as the previous example
page.open('http://cuiqingcai.com/', function() {
  page.render('germy.png');
  phantom.exit();
});

運行結果

就相當於把瀏覽器窗口拖到了 1024×768 大小,然后從左上角裁切出了 1024×768 的頁面。

網絡監聽

Because PhantomJS permits the inspection of network traffic, it is suitable to build various analysis on the network behavior and performance.

因為 PhantomJS 有網絡通信的檢查功能,它也很適合用來做網絡行為的分析。

When a page requests a resource from a remote server, both the request and the response can be tracked via onResourceRequested and onResourceReceived callback.

當接受到請求時,可以通過改寫onResourceRequested和onResourceReceived回調函數來實現接收到資源請求和資源接受完畢的監聽。例如

var url = 'http://www.cuiqingcai.com';
var page = require('webpage').create();
page.onResourceRequested = function(request) {
  console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
  console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
page.open(url);

運行結果會打印出所有資源的請求和接收狀態,以JSON格式輸出。

頁面自動化處理

Because PhantomJS can load and manipulate a web page, it is perfect to carry out various page automations.

因為 PhantomJS 可以加載和操作一個web頁面,所以用來自動化處理也是非常適合的。

DOM操作

Since the script is executed as if it is running on a web browser, standard DOM scripting and CSS selectors work just fine.

腳本都是像在瀏覽器中運行的,所以標准的 JavaScript 的 DOM 操作和 CSS 選擇器也是生效的。

例如下面的例子就修改了 User-Agent,然后還返回了頁面中某元素的內容。

var page = require('webpage').create();
console.log('The default user agent is ' + page.settings.userAgent);
page.settings.userAgent = 'SpecialAgent';
page.open('http://www.httpuseragent.org', function(status) {
  if (status !== 'success') {
    console.log('Unable to access network');
  } else {
    var ua = page.evaluate(function() {
      return document.getElementById('myagent').textContent;
    });
    console.log(ua);
  }
  phantom.exit();
});

運行結果

The default user agent is Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.0 Safari/538.1

Your Http User Agent string is: SpecialAgent

首先打印出了默認的 User-Agent,然后通過修改它,請求驗證 User-Agent 的一個站點,通過選擇器得到了修改后的 User-Agent。

使用附加庫

在1.6版本之后允許添加外部的JS庫,比如下面的例子添加了jQuery,然后執行了jQuery代碼。

var page = require('webpage').create();
page.open('http://www.sample.com', function() {
  page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
    page.evaluate(function() {
      $("button").click();
    });
    phantom.exit()
  });
});

引用了 jQuery 之后,我們便可以在下面寫一些 jQuery 代碼了。

Webpage對象

在前面我們介紹了 webpage 對象的幾個方法和屬性,其實它本身還有其它很多的屬性。具體的內容可以參考

Webpage

Webpage用例

里面介紹了 webpage的所有屬性,方法,回調。

命令行

Command-line Options

PhantomJS提供的命令行選項有:

  • –help or -h lists all possible command-line options. Halts immediately, will not run a script passed as argument. [幫助列表]

  • –version or -v prints out the version of PhantomJS. Halts immediately, will not run a script passed as argument. [查看版本]

  • –cookies-file=/path/to/cookies.txt specifies the file name to store the persistent Cookies. [指定存放cookies的路徑]

  • –disk-cache=[true|false] enables disk cache (at desktop services cache storage location, default is false). Also accepted: [yes|no]. [硬盤緩存開關,默認為關]

  • –ignore-ssl-errors=[true|false] ignores SSL errors, such as expired or self-signed certificate errors (default is false). Also accepted: [yes|no]. [忽略ssl錯誤,默認不忽略]

  • –load-images=[true|false] load all inlined images (default is true). Also accepted: [yes|no]. [加載圖片,默認為加載]

  • –local-storage-path=/some/path path to save LocalStorage content and WebSQL content. [本地存儲路徑,如本地文件和SQL文件等]

  • –local-storage-quota=number maximum size to allow for data. [本地文件最大大小]

  • –local-to-remote-url-access=[true|false] allows local content to access remote URL (default is false). Also accepted: [yes|no]. [是否允許遠程加載文件,默認不允許]

  • –max-disk-cache-size=size limits the size of disk cache (in KB). [最大緩存空間]

  • –output-encoding=encoding sets the encoding used for terminal output (default is utf8). [默認輸出編碼,默認utf8]

  • –remote-debugger-port starts the script in a debug harness and listens on the specified port [遠程調試端口]

  • –remote-debugger-autorun runs the script in the debugger immediately: ‘yes’ or ‘no’ (default) [在調試環境下是否立即執行腳本,默認否]

  • –proxy=address:port specifies the proxy server to use (e.g. –proxy=192.168.1.42:8080). [代理]

  • –proxy-type=[http|socks5|none] specifies the type of the proxy server (default is http). [代理類型,默認http]

  • –proxy-auth specifies the authentication information for the proxy, e.g. –proxy-auth=username:password). [代理認證]

  • –script-encoding=encoding sets the encoding used for the starting script (default is utf8). [腳本編碼,默認utf8]

  • –ssl-protocol=[sslv3|sslv2|tlsv1|any’] sets the SSL protocol for secure connections (default is SSLv3). [SSL協議,默認SSLv3]

  • –ssl-certificates-path= Sets the location for custom CA certificates (if none set, uses system default). [SSL證書路徑,默認系統默認路徑]

  • –web-security=[true|false] enables web security and forbids cross-domain XHR (default is true). Also accepted: [yes|no]. [是否開啟安全保護和禁止異站Ajax,默認開啟保護]

  • –webdriver starts in ‘Remote WebDriver mode’ (embedded GhostDriver): ‘[[:]]’ (default ‘127.0.0.1:8910’) [以遠程WebDriver模式啟動]

  • –webdriver-selenium-grid-hub URL to the Selenium Grid HUB: ‘URLTOHUB’ (default ‘none’) (NOTE: works only together with ‘–webdriver’) [Selenium接口]

  • –config=/path/to/config.json can utilize a JavaScript Object Notation (JSON) configuration file instead of passing in multiple command-line optionss [所有的命令行配置從config.json中讀取]

注:JSON文件配置格式

{
  /* Same as: --ignore-ssl-errors=true */
  "ignoreSslErrors": true,

  /* Same as: --max-disk-cache-size=1000 */
  "maxDiskCacheSize": 1000,

  /* Same as: --output-encoding=utf8 */
  "outputEncoding": "utf8"

  /* etc. */
}

There are some keys that do not translate directly:

 * --disk-cache => diskCacheEnabled
 * --load-images => autoLoadImages
 * --local-storage-path => offlineStoragePath
 * --local-storage-quota => offlineStorageDefaultQuota
 * --local-to-remote-url-access => localToRemoteUrlAccessEnabled
 * --web-security => webSecurityEnabled

以上是命令行的基本配置

實例

在此提供官方文檔實例,多對照實例練習,使用起來會更得心應手。

官方實例

結語

以上是博主對 PhantomJS 官方文檔的基本總結和翻譯,如有差錯,希望大家可以指正。另外可能有的小伙伴覺得這個工具和 Python 有什么關系?不要急,后面會有 Python 和 PhantomJS 的綜合使用的。


原文鏈接:https://www.qcloud.com/community/article/928598001491399938


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM