PhantomJS快速入門

PhantomJS快速入門javascript

  本文簡要介紹了PhantomJS的相關基礎知識點,主要包括PhantomJS的介紹、下載與安裝、HelloWorld程序、核心模塊介紹等。因爲鄙人才疏學淺,不免有疏漏之處,歡迎指正交流。html

  一、PhantomJS是什麼?前端


  PhantomJS是一個基於webkit的JavaScript API。它使用QtWebKit做爲它核心瀏覽器的功能,使用webkit來編譯解釋執行JavaScript代碼。任何你能夠在基於webkit瀏覽器作的事情,它都能作到。它不只是個隱形的瀏覽器,提供了諸如CSS選擇器、支持Web標準、DOM操做、JSON、HTML五、Canvas、SVG等,同時也提供了處理文件I/O的操做,從而使你能夠向操做系統讀寫文件等。PhantomJS的用處可謂很是普遍,諸如網絡監測、網頁截屏、無需瀏覽器的 Web 測試、頁面訪問自動化等。java

  PhantomJS官方地址:http://phantomjs.org/。jquery

  PhantomJS官方API:http://phantomjs.org/api/。git

  PhantomJS官方示例:http://phantomjs.org/examples/。github

  PhantomJS GitHub:https://github.com/ariya/phantomjs/。web

  二、PhantomJS下載與安裝小程序


  官方下載地址:http://phantomjs.org/download.html。目前官方支持三種操做系統,包括windows\Mac OS\Linux這三大主流的環境。你能夠根據你的運行環境選擇要下載的包,個人運行環境是Windows7。windows

  下載完成後解壓文件,建議爲方便使用,單獨放在一個文件夾裏,如我放在D:\workspace\phantomjs裏。

  到這裏,你已經成功下載安裝好PhantomJS了。那麼,打開D:\workspace\phantomjs\bin文件夾,雙擊運行phantomjs.exe,出現以下界面,那麼你就能夠運行JS代碼了。

  因爲咱們都比較懶,不喜歡爲了運行一個程序老是跑到D:\workspace\phantomjs\bin文件夾打開phantomjs.exe。那麼,你能夠將phantomjs.exe添加到環境變量裏。具體以下:打開個人電腦->右鍵屬性->高級系統設置->高級標籤->環境變量,在系統變量裏找到Path,將你的phantomjs添加到環境變量裏。比方說個人路徑添加的爲「;D:\workspace\phantomjs\bin」,切記不要少了前面那個分號。

  三、第一個PhantomJS小程序HelloWorld


 

  好了,到目前爲止,能夠開始咱們的第一個PhantomJS程序了。打開你的工做目錄,新建文件hello.js,敲入如下代碼,Ctrl+S保存:

 1 // a phantomjs example
 2 var page = require('webpage').create();
 3 phantom.outputEncoding="gbk";
 4 page.open("http://www.cnblogs.com/front-Thinking", function(status) {
 5    if ( status === "success" ) {
 6       console.log(page.title); 
 7    } else {
 8       console.log("Page failed to load."); 
 9    }
10    phantom.exit(0);
11 });

  而後,打開CMD命令行工具,切換到你的當前目錄,敲入phantomjs hello.js,結果以下:

  若是你的結果跟個人同樣,那麼恭喜你,你已經成功跑起來屬於你的第一個PhantomJS程序了。那麼咱們簡要介紹下上面的代碼:第2行,webpage是phantomjs的核心模塊之一,它給用戶提供了訪問、操做、選擇web文檔的接口。第3行,設置下編碼格式,不然輸出的多是亂碼。第4行,運行page.open函數,其中第一個參數是你要訪問的url,第二個參數是一個回調函數。在回調函數裏咱們檢查了下返回的狀態,若是是success那麼咱們就將瀏覽的url制定文檔的title打印出來,如你所見,若是不是那麼打印文檔加載出錯。最後一行退出phantomjs執行環境。

  四、PhantomJS核心API


  webpage:如你所見,上面的例子咱們已經見識了它的威力了。它的做用主要是提供了一套能夠訪問和操做web文檔的核心方法,包括操做DOM、事件捕獲、用戶事件模擬等等。

  system:該模塊提供了一些與操做系統相關的接口,例如訪問操做系統信息、訪問系統環境變量、接受命令行參數等等與程序執行相關的系統信息。

  fs:即FileSystem。熟悉NodeJS的朋友都知道,NodeJS也內建了相關的核心模塊。fs提供了執行文件I/O操做的標準接口,如讀寫文件、刪除文件等。它使得你持久化一些文件(如logfile等)變得很是容易。

  webserver:如其名字同樣,你能夠基於它來實現本身的webserver,用來處理請求而且執行PhantomJS代碼等。

  其它一些配置信息,執行PhantomJS的命令格式以下:

1 phantomjs [switches] [options] [script] [argument [argument [...]]]

  其中,各類參數都是可選的。例如咱們第一個程序的執行命令以下:

1 phantomjs hello.js

  打開debug模式(該模式用於開發,可提供必要提示信息):

1 phantomjs --debug=yes hello.js

  設置cookie路徑:

1 phantomjs --cookie-file=cookie.txt hello.js

  五、操做page content


  在helloworld中咱們已經學會了如何訪問一個url並取出它的title。下面咱們看看如何選擇並操做DOM元素:

  DOM選擇器,經常使用的getElementById、getElementByClassName、getElementByName、getElementByTagName、querySelector(CSS選擇器)。

  咱們看一個使用querySelector的例子:

1 var content = page.evaluate(function () {
2 var element = document.querySelector('#elem');
3     return element.textContent;
4 });
5 console.log(content);

  evaluate函數是個新東西,其實很簡單,就是在webpage環境下執行evaluate傳入的回調函數,在這裏面執行與phantom相關的操做能夠避免web頁面刺探phantom相關的設置信息。上面的代碼就比較簡單了,不囉嗦了。

  模仿用戶點擊事件:

  phantomJS提供了兩種模仿點擊事件的接口,一個是sendEvent,phantomJS事件觸發器;一個是DOM事件觸發器。

  咱們先看看第一個,語法以下:

1 sendEvent( eventType, Point X, Point Y, button='left' )
2 eventType: mouseup  mousedown mousemove click doubleclick
3 Point X : 觸發事件的X座標
4 Point Y: 觸發事件的Y座標

  第二個,咱們都應該比較熟悉了:

 1 var evt = document.createEvent("MouseEvents");
 2 evt.initMouseEvent(
 3     "click", // 事件類型
 4     true, 
 5     true, 
 6     window, 
 7     1, 
 8     1, 1, 1, 1, // 事件的座標
 9     false, // Ctrl鍵標識
10     false, // Alt鍵標識
11     false, // Shift鍵標識
12     false, // Meta鍵標識
13     0, // Mouse左鍵
14     element); // 目標元素
15 element.dispatchEvent(evt);

  六、事件處理


  在真正的瀏覽器裏,任何事件發生均可見,而在PhantomJS裏都是不可見的。在PhantomJS裏,咱們能夠捕獲這些事件並作出相應處理。因爲涉及到的事件有不少種,那麼咱們今天僅僅把一個比較有用的事件做爲例子,基於這個事件你能夠監控一個頁面並作出分析:

1 var startTime = null;
2 page.onLoadStarted = function() {
3     startTime = new Date().getTime();
4 }

  監聽也沒開始加載事件,獲取初始加載時間;

1 var resources = [];
2 page.onResourceRequested = function (request) {
3     resource = {
4         "startTime": request.time,
5         "url": request.url
6     };
7     resources[request.id] = resource;
8 };

監聽資源文件請求事件,獲取資源發起請求的時間;
1 page.onResourceReceived = function (response) {
2     if(response.stage == "start") {
3         resources[response.id].size = response.bodySize;
4     } else if(response.stage == "end") {
5         resources[response.id].endTime = response.time;
6     }
7 };

監聽資源文件加載完成事件,獲取加載完成時間;
 1 page.onLoadFinished = function () {
 2     endTime = new Date();
 3     timeInSeconds = (endTime - startTime) / 1000;
 4     console.log("Loading takes " + timeInSeconds + " seconds.");
 5     resources.forEach(function (resource) {
 6         st = new Date(resource.startTime).getTime();
 7         et = new Date(resource.endTime).getTime();
 8         timeSpent = (et - st) / 1000;
 9         console.log(timeSpent + " seconds : " + resource.url);
10     });
11     phantom.exit(0);
12 };
監聽文檔加載完成事件,記錄完成時間,並打印出全部資源文件的耗時。

  上面的on+事件,作了四件事,監聽資源文件請求和加載完成事件,監聽文檔加載開始完成事件,獲取對應的時間,這樣咱們就可使用這些事件去分析這個頁面的性能問題了。

  七、抓取頁面


  將要訪問的頁面抓取保存爲圖片或者PDF文件的格式,這在PhantomJS裏很是簡單。咱們下面就分別作一個保存圖片和PDF的例子:

  保存爲圖片:

 1 // a phantomjs example, saved as img
 2 var page = require('webpage').create();
 3 page.open("http://www.cnblogs.com/front-Thinking/", function(status) {
 4    if ( status === "success" ) {
 5       console.log(page.title); 
 6       page.render("front-Thinking.png");
 7    } else {
 8       console.log("Page failed to load."); 
 9    }
10    phantom.exit(0);
11 });

  注:render獲取一個參數,即保存文件的文件名。結果以下:

  保存爲pdf:

 1 // a phantomjs example,saved as pdf file
 2 var page = require('webpage').create();
 3 page.open("http://www.baidu.com", function(status) {
 4    if ( status === "success" ) {
 5       console.log(page.title); 
 6       page.paperSize = { format: 'A4', 
 7             orientation: 'portrait', 
 8             border: '1cm' };
 9       page.render("front-Thinking.pdf");
10    } else {
11       console.log("Page failed to load."); 
12    }
13    phantom.exit(0);
14 });

  注:其中,pagerSize設置pdf的格式。結果以下:

  利用這些提供的特性,你徹底能夠作一個爬蟲去爬去別人的網站。

  八、文件操做相關


  文件操做在編碼中很是有用,例如你能夠將一些配置信息放在文件中,在程序執行的過程當中去讀取;你也能夠將你程序執行過程當中一些有用的信息保存爲文件。所以文件I/O很是有用。咱們舉個簡單的例子,讀取文件信息:

 1 var filePath = '/workspace/file1.js';//文件路徑
 2 
 3 //判斷文件是否存在,是文件仍是文件夾
 4 if( fs.exists(filePath) && fs.isFile(filePath) ) {
 5        var ins = fs.open(filePath, 'r');//打開文件
 6         while(!ins.atEnd()) {//循環讀取文件內容
 7            var buffer = ins.readLine();//一行行的讀取
 8            console.log(buffer);
 9        }
10 }

  這裏,讀取文件內容並逐行打印。文件操做有如下幾種方式:

1 r      //讀取文件
2 w    //寫文件,回覆蓋
3 a     //寫文件,追加
4 rb    //讀取二進制流
5 rw    //寫入二進制流

  九、模塊化


  模塊化是沒個技術都涉及到的內容,這裏不作詳細介紹了。具體可參考阮一峯前輩的博客:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html

  十、與jQuery等第三方的結合


  有不少第三方很是優秀的庫函數,那麼這裏咱們就舉一個你們都很是喜歡的jQuery庫函數來說講phantomJS與庫函數的結合。代碼以下:

 1 var page = require('webpage').create();
 2 page.open("http://www.cnblogs.com/front-Thinking/", function(status) {
 3     if ( status === "success" ) {
 4         page.render("before.png");
 5         page.includeJs("http://code.jquery.com/jquery-1.10.1.min.js", 
 6             function() {
 7                 page.evaluate(function() {
 8                 $('#Header1_HeaderTitle').html('My PhantomJS');
 9             });
10             page.render("after.png");
11             phantom.exit();();
12         });
13     }
14 });

  以上代碼,訪問個人博客地址,並抓取截屏,加載jquery後修改我博客的標題,結果以下:

  

before.png

    

  after.png

  十一、其它


  PhantomJS能夠作的事情太多了以致於我可能都介紹了只有它N分之一,N趨於無窮大。說了僅僅是入門的帖子,因此就再也不深刻介紹下去了,固然我也只是個小白,暫時知道了解的也比較淺顯。其實,PhantomJS能夠結合Jasmine來一塊兒作測試,能夠省去很大的人力和時間成本。同時,開源社區有不少基於PhantomJS作的工具和應用,例如前端爬蟲等,有興趣的不妨去讀讀。

  結束語


  再次對你有如此大的耐性讀這麼一篇爛文到如今表示感謝(花了兩個多小時寫它,我也是夠有耐性的了,哇咔咔)!在閱讀或者敲代碼過程當中發現任何問題或者有任何疑問,歡迎留言指導交流!

相關文章
相關標籤/搜索