本文章參考了使用phantomjs操作DOM並對頁面進行截圖需要注意的幾個問題 及phantomjs使用說明 這兩篇文章,初次接觸phantomjs的童鞋可以去看下這兩篇原文
在學習中可以看下 phantomjs官方相關示例
phantomjs是一個無界面瀏覽器,可用於網頁截圖和前端自動化測試,基於webkit內核(也就是chrome使用的內核),並使用js編寫業務腳本來請求、瀏覽和操作頁面。
1、安裝phantomjs
下載phantomjs(官網下載),選擇自己需要的版本下載即可,我這里是在windows下使用的,下載后直接解壓,為了方便我將包含phantomjs.exe的目標路徑添加到了環境變量里面,后續使用比較方便。
安裝完成后在cmd里面輸入phantomjs --version即可查看phantomjs版本信息。
2、phantomjs使用
phantomjs有標准的入門文檔可以參考,網上也有很多的資料可以查閱,在使用過程中根據自己的需要實際操作。
我們這里主要是對文章開頭提到到第一篇文章的仿照實現,所以理論和相關的注意事項可以參考文章引用的第一篇文章。
操作界面中的DOM樹主要使用使用
evaluate(function, arg1, arg2, ...) {object}
在截圖中如何將整個界面截圖,有如下幾種方法:
一個是使瀏覽器足夠大,這樣底部就顯示了,可以設置viewPortSize很大:page.viewportSize = {width: 4800,height: 8000};
另一個是通過BOM方法操作滾動條,可以把滾動條滾動到一個很大的值,如:window.scrollTo(0,10000);也可以滾動到適應的高度:window.document.body.scrollTop = document.body.scrollHeight;
如何延遲截圖,頁面請求的資源,如圖片、異步cgi、js等,返回的時間以及執行的長短都是不確定的,如果截圖過早,可能很多空白區域,因此需要定時截圖,在打開頁面后,使用setTimeout來延遲截圖
window.setTimeout(function () { page.render("test.png"); phantom.exit(); }, 1000);
完整的代碼,請求搜狗搜索微信的公眾賬號信息,並對連接標記紅框、延遲截圖
var page = require('webpage').create(); system = require('system'); //var url = 'http://yule.club.sohu.com/gifttrade/thread/2m2efbrpfui'; var address; if(system.args.length == 1){ phantom.exit(); }else{ adress = system.args[1]; page.open(adress, function (status){ if (status != "success"){ console.log('FAIL to load the address'); phantom.exit(); } page.evaluate(function(){ //此函數在目標頁面執行的,上下文環境非本phantomjs,所以不能用到這個js中其他變量 window.scrollTo(0,10000);//滾動到底部 //window.document.body.scrollTop = document.body.scrollHeight; window.setTimeout(function(){ var plist = document.querySelectorAll("a"); var len = plist.length; while(len) { len--; var el = plist[len]; el.style.border = "1px solid red"; } },5000); }); window.setTimeout(function (){ //在本地生成截圖 page.render("json2form.png"); console.log(page.content); phantom.exit(); }, 5000+500); }); }
這里附上java操作phantomjs的代碼:

package com.newsTest.weixin; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * 類名: DownLoad * 包名: com.newsTest.weixin * 作者: zhouyh * 時間: 2014-9-10 下午04:19:46 * 描述: TODO(這里用一句話描述這個類的作用) */ public class DynamicDownLoad { /** * * 方法名:getSrcContent * 作者:zhouyh * 創建時間:2014-9-10 下午06:57:32 * 描述:根據傳入的url,調用phantomjs進行下載,並返回源碼信息 * @param url * @return */ public static String getSrcContent(String url){ //windows下phantomjs位置 String path = "D:/phantomjs-1.9.7-windows/"; Runtime rt = Runtime.getRuntime(); Process process = null; try { process = rt.exec(path + "phantomjs.exe D:/phantomjs-1.9.7-windows/test.js " + url.trim()); } catch (IOException e) { // TODO 這里寫異常處理的代碼 e.printStackTrace(); } InputStream is = process.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); StringBuffer sbf = new StringBuffer(); String tmp = ""; try { while((tmp = br.readLine())!=null){ sbf.append(tmp); } } catch (IOException e) { // TODO 這里寫異常處理的代碼 e.printStackTrace(); } return sbf.toString(); } /** * 方法名:main * 作者:zhouyh * 創建時間:2014-9-10 下午04:19:46 * 描述:TODO(這里用一句話描述這個方法的作用) * @param args * @throws IOException */ public static void main(String[] args){ // TODO Auto-generated method stub String src = DynamicDownLoad.getSrcContent("http://weixin.sogou.com/gzh?openid=oIWsFt9MmzCvfJgaVxEUevPcuUCg"); System.out.println(src); } }
補充:對於延遲截圖,還是有個問題,就是無法監聽ajax或者資源是否完整加載導致頁面不全;解決方案,viewport設置一個比截圖高度的矮,通過比較生產圖片的高度來判斷截取圖片的結果
參考以下文章
http://blog.csdn.net/hwwzyh/article/details/39184905