2014-07-01 46 views
1

我正在學習PhantomJS。如果你能幫助我理解爲什麼下面的代碼給我一個錯誤(如下所示)並幫助我修復錯誤,我將不勝感激。我正在嘗試使用phantomjs在頁面上執行一些JavaScript。當我在Chrome控制檯中輸入時,評估函數中的代碼行可以很好地工作,即它們會給出預期的結果(document.title)。爲什麼這個phantomjs代碼返回null和文檔標題?

謝謝。

PhantomJS代碼

var page = require('webpage').create(); 

var url = 'http://www.google.com'; 

page.open(url, function(status) { 


    var title = page.evaluate(function(query) { 
     document.querySelector('input[name=q]').setAttribute('value', query); 

     document.querySelector('input[name="btnK"]').click(); 

     return document.title; 
    }, 'phantomJS'); 

    console.log(title); 

    phantom.exit() 
}) 

錯誤

TypeError: 'null' is not an object (evaluating 'document.querySelector('input[name="btnK"]').click') 

    phantomjs://webpage.evaluate():4 
    phantomjs://webpage.evaluate():7 
    phantomjs://webpage.evaluate():7 
null 

編輯1:針對安德魯的回答

安德魯,很奇怪,但我的電腦上,在按鈕是一個輸入元素。以下屏幕截圖顯示了我的電腦上的結果。

編輯2:單擊事件不可靠

有時候,以下click事件的作品,有時沒有。

​​

不清楚發生了什麼事。

關於答案

對於未來的讀者,除了答案,Artjom B.要點是有助於理解發生了什麼。然而,對於更強大的解決方案,我認爲必須使用類似waitfor.js示例的東西(正如答案中所建議的那樣)。我希望可以在這裏複製和粘貼Artjom B.的要點。雖然下面的要點工作(與表格提交);我仍然不清楚爲什麼如果我嘗試模擬輸入上的單擊按鈕時它不起作用。如果有人能夠澄清這一點,那將會很棒。

// Gist by Artjom B. 
var page = require('webpage').create(); 
var url = 'http://www.google.com'; 
page.open(url, function(status) { 
    var query = 'phantomJS'; 
    page.evaluate(function(query) { 
     document.querySelector('input[name=q]').value = query; 
     document.querySelector('form[action="/search"]').submit(); 
    }, query); 
    setTimeout(function(){ 
     var title = page.evaluate(function() { 
      return document.title; 
     }); 
     console.log(title); 
     phantom.exit(); 
    }, 2000); 
}); 
+1

谷歌可能會向不同的客戶端提供不同的頁面,所以它可能是您的瀏覽器的「輸入」,但幻燈片的「按鈕」。嘗試記錄document.body,並檢查真正在那裏。 – Andrew

+0

謝謝安德魯。它是輸入但名稱=「btnG」。這一次它沒有給出錯誤。這部分工作。但是,它也沒有點擊按鈕。在搜索字詞提交之前,它返回的頁面標題是「Google」。 – Curious2learn

+0

這是有道理的。點擊將導致導航,並且需要時間。要獲得新的標題,請等待一段時間,例如3s,或者像這樣監聽頁面加載事件:page.onLoadFinished = function(){..evaluate ..}。另外檢查casperjs,它建立在Phantomjs上,但更易於使用。 – Andrew

回答

3

谷歌使用的表單提交的查詢。谷歌改變搜索按鈕的原型方法的可能性很大,因此它不是測試網頁抓取的最佳網站。

最簡單的方法是實際執行表單提交,稍微調整您的示例。

var page = require('webpage').create(); 
var url = 'http://www.google.com'; 
page.open(url, function(status) { 
    var query = 'phantomJS'; 
    var title = page.evaluate(function(query) { 
     document.querySelector('input[name=q]').value = query; 
     document.querySelector('form[action="/search"]').submit(); 
     return document.title 
    }, query); 
console.log(title); 
phantom.exit(); 
}); 

注意,你可能需要考慮響應是異步從這個電話,所以直接獲得冠軍將有可能導致一個未定義的錯誤(你需要考慮它需要對頁面的時間在查看數據之前加載;您可以在他們的waitfor.js例子中查看)。

+0

你是對的,你沒法用phantomjs(或casperjs)點擊那個按鈕。在返回標題之前,您可能需要等一會兒。看到這[gist](https://gist.github.com/anonymous/cb33e8173c0c56e85597)。 –

+0

你的主旨很棒。謝謝。但是,相同的setTimeOut不適用於按鈕點擊。爲什麼需要提交表單?點擊按鈕不提交表單? – Curious2learn

+0

@ Curious2learn通常點擊會提交表單,但我認爲谷歌使用一些技術來檢測客戶端並投擲石塊。使用phantomjs/casperjs瀏覽谷歌網站確實很困難。幾乎所有其他網站的行爲都正確。假設phantomjs/casperjs如何工作還存在問題,否則就不會有太多的問題。 –

3

您可以打開google.com並在控制檯中嘗試document.querySelector( '輸入[名稱= 「btnK」]'),它爲空。 google input

Actully嘗試用替換鍵輸入:

document.querySelector('button[name="btnK"]') 

google search button

+0

請看我上面的回答編輯1. – Curious2learn