phamtomjs能否得到js運行後的代碼並輸出到文檔?

如題

比如AJAX網站下,只有js運行過才顯示的信息能否在phamtomjs里顯示並 輸出?

用了Open方法,但是得到的中文在CMD中是亂碼。另一個問題是如何讓console里的內容保存下來呢?


知乎上居然有人問PhantomJS的問題,必須怒答。

可以的。不過要得到所有Ajax完成後的頁面,需要做一些特別的判定。

PhantomJS的渲染引擎就是QtWebkit,JS引擎是JavascriptCore(不是V8),所以大致上可以當作一個沒有GUI的Safari。

所以PhantomJs載入一個網頁,基本跟Safari一樣了,自然所有Javascript都會被解析執行的(不管 這些代碼是否會修改DOM)

要想測試的話,可以用PhantomJS截圖的API,找一個Ajax請求很多的頁面,每隔200毫秒截一張圖,就能看到具體頁面loading的過程了。

一般在無Ajax網頁,可以直接調用PhantomJS載入頁面的callback來獲取結果。但是在有Ajax的情況下,這個Callback被調用的時候,後台Ajax命令可能還在執行中(或者還沒發出去),所以需要手動添加一些代碼(比如setTimeout(2000)一類的),來等待所有Ajax命令執行結束。

具體的做法是:

1. 最簡單的

假設你使用open(url, callback)這個函數打開頁面。這個函數callback的是在頁面DOM Loaded後不久就觸發了。但是這個時候Ajax的請求不一定執行完畢。所以要在open(url, callback)這裡的callback裡面再加上一個setTimeout來等待Ajax執行完畢。

但是這個做法缺陷是,我並不知道具體要setTimeout多久才能保證ajax執行完畢。

2. 稍微複雜點,解決方案。

PhantomJS有個兩個callback API是

page.onResourceRequested //在頁面每個request發出的時候被觸發
page.onResourceReceived //在頁面每個response收到的時候被觸發

在這兩個callback裡面記錄下每個request的id,和每個response的id,並在open(url, callback)的callback被調用的時候,檢查是否每個request都有對應的response。如果不是的話,說明有ajax request被發了出去,但是並沒有收到,因此繼續調用setTimeout來等待。直到所有request都有對應的response。

2. 最麻煩的

直接改掉PhantomJS的源碼,讓他在N秒內沒有新的request發出後,再觸發open(url, callback)裡面的callback。可以參考我的改動https://github.com/ye11ow/phantomjs,不過我是改得Ghostdriver, 而不是PhantomJS本身 :-)


用 setTimeout 也有問題,鬼知道要等多久的,不過有一種方法,也就是獲取 document.readyState ,判斷是否 complete,知道到達預期。

function onComplete() {
setTimeout(function () {
var readyState = page.evaluate(function () {
return document.readyState;
});

if (readyState === "complete") {
parse();
}
else {
onComplete();
}
}, 1000);
}


亂碼的話,在執行腳本的頭部加上phantom.outputEncoding = 『gb2312』;試試


如何判斷Ajax執行完畢?

Ajax執行完畢後,頁面會有一些特徵(Flag),程序中加個sleep,循環檢測(直到自認為的超時),一旦發現Flag就認為Ajax執行完畢,可以讀取頁面源碼進而獲取Ajax的執行結果了。


推薦閱讀:

怎樣防止重複發送 Ajax 請求?

TAG:前端開發 | JavaScript | Ajax | PhantomJs |