2011-09-07 106 views
8

我需要做一些網絡抓取。在使用不同的Web測試框架之後,其中大多數地方的速度太慢(Selenium)或者我的需求太多(env.js),我認爲zombie.js看起來最有希望,因爲它使用一組可靠的庫進行HTML解析和DOM操作。然而,在我看來,像它竟然不支持基本的基於事件的Javascript代碼如以下網頁:網站抓取使用zombie.js的問題

<html> 
    <head> 
    <title>test</title> 
    <script type="text/javascript"> 

     console.log("test script executing..."); 
     console.log("registering callback for event DOMContentLoaded on " + document); 

     document.addEventListener('DOMContentLoaded', function(){ 
     console.log("DOMContentLoaded triggered"); 
     }, false); 

     function loaded() { 
     console.log("onload triggered"); 
     } 

    </script> 
    </head> 

    <body onload="loaded();"> 
    <h1>Test</h1> 
    </body> 
</html> 

我於是決定手動觸發這些事件是這樣的:

zombie = require("zombie"); 

zombie.visit("http://localhost:4567/", { debug: true }, function (err, browser, status) { 

    doc = browser.document; 
    console.log("firing DOMContentLoaded on " + doc); 
    browser.fire("DOMContentLoaded", doc, function (err, browser, status) { 

    body = browser.querySelector("body"); 
    console.log("firing load on " + body); 
    browser.fire("load", body, function (err, browser, status) { 

     console.log(browser.html()); 

    }); 
    }); 

}); 

這適用於這個特定的測試頁面。不過,我的問題是更普遍的問題:我希望能夠在Facebook上抓取更復雜的基於AJAX的網站(如http://www.facebook.com/profile.php?id=100000028174850&sk=friends&v=friends)。使用殭屍登錄到網站並不是問題,但是像這些列表這樣的內容似乎完全使用AJAX加載,我不知道如何觸發啓動加載的事件處理程序。

有幾個問題我有一個關於這個問題:

  • 已有人已經實施了類似的複雜刮不使用瀏覽器進行遠程控制一樣硒的解決方案?
  • 是否有一些有關基於JavaScript的複雜頁面加載過程的參考?
  • 有人可以提供關於如何調試真正的瀏覽器,看看我可能需要執行觸發Facebook事件處理程序的建議嗎?
  • 有關此主題的任何其他想法?

再次,請不要指出我涉及控制像Selenium這樣的真正瀏覽器的解決方案,因爲我知道這些。不過,歡迎提供一些真正的內存中渲染器的建議,如WebKit可以從Ruby腳本語言訪問,但最好能夠設置cookie,並且最好還可以加載原始HTML,而不是觸發真正的HTTP請求。

+0

你正在尋找一個JavaScript測試框架或Web數據提取工具嗎?如果你只是在尋找一個scree-scraping工具,那麼可以在不執行Javascript的情況下刮掉大多數網站,甚至是AJAX重量級的網站。 – chesles

+1

問題是關於網絡抓取。你是對的,通常確實有可能在不執行Js的情況下做到這一點,例如通過手動發佈REST請求。在Facebook的情況下,只需使用HTTP和HTML解析就可以抓取該網站的移動版本。但我對通用解決方案感興趣,它理解Javascript並且不需要真正的瀏覽器實例。這似乎是可能的,因爲env.Js和zombie.Js顯示,但它似乎是一個技巧問題。 –

回答

12

爲了進行數據提取,運行「無頭瀏覽器」並手動觸發javascript事件不會是最簡單的事情。雖然不是不可能,但有更簡單的方法來做到這一點。

大多數網站,即使是AJAX重量級的網站,都可以在不執行其單個Javascript代碼的情況下被抓取。實際上,通常比試圖找出一個網站的Javascript代碼要容易得多,該代碼經常被混淆,縮小並難以調試。如果你對HTTP有深刻的理解,你就會明白爲什麼:(幾乎)與服務器的所有交互都被編碼爲HTTP請求,因此無論它們是由Javascript發起的,還是用戶點擊鏈接或bot程序中的自定義代碼,這對服務器沒有任何影響。 (我之所以這樣說,幾乎是因爲當Flash或applets涉入時,不知道數據在哪裏飛行;它們可以是特定於應用程序的,但Javascript中的任何操作都將通過HTTP進行。)

也就是說,在任何使用定製軟件的網站上模仿用戶。首先,您必須能夠看到發送到服務器的原始HTTP請求。您可以使用代理服務器來記錄真實瀏覽器向目標網站發出的請求。有許多工具可以用於此目的:CharlesFiddler非常方便,最專注screen-scraper tools有一個基本的代理內置,Firefox和Chrome的Firebug擴展具有類似的工具來查看AJAX請求...你會得到這個想法。

一旦您可以看到由於網站上的特定操作而產生的HTTP請求,很容易編寫程序來模仿這些請求;只需將相同的請求發送到服務器,它就會像處理特定操作的瀏覽器一樣對待您的程序。

不同的語言庫提供不同的功能。對於紅寶石來說,我看到很多人使用mechanize for ruby

如果數據提取是您唯一的目標,那麼您幾乎總能通過這種方式模仿HTTP請求來獲得所需的內容。不需要Javascript。因爲Facebook提供了檢測自動訪問的措施(它們使用的不僅僅是驗證碼),因爲Facebook提供的Facebook特別困難(儘管不是不可能)非常困難(儘管不是不可能)。如果他們發現可疑活動,他們將會禁用該帳戶。畢竟,這是對他們的terms of service(第3.2節)。

+1

謝謝你爲這個問題提出複雜的答案。我已經使用Firebug和Fiddler2來監控HTTP和Web服務器之間的流量,但是如果使用難以反向的通信主題,這是非常有用的,正如很多社交網站所做的那樣。但即使可以使用底層接口與Web服務器交互並提取信息,這也需要不斷調整scraper,這可能非常耗時。 Env.js(我最喜歡的工作,因爲我想)表明,它實際上可以通過編程模擬一個真正的瀏覽器。 –

+0

確實如此,Facebook和其他網站試圖儘可能讓你刮掉他們的網站;他們更喜歡你使用他們的API,這樣他們可以更好地控制你的程序訪問什麼,並因此更好地保護他們的用戶的隱私。 – chesles

+0

儘管如此,使用像Selenium這樣的工具來模擬衝浪用戶似乎沒有任何問題(除了緩慢),除了大量使用動態內容之外,我沒有遇到任何障礙。即使OAuth沒有針對自動訪問進行保護,認證可以沒有任何問題地編寫腳本,甚至不需要使用Javascript。 –