2014-07-10 36 views
2

我正在嘗試使用PhantomJS進行頁面自動化。我的目標是能夠訪問網站,點擊圖片,並在頁面從點擊加載後繼續使用其他代碼。爲了測試這一點,我正在嘗試編寫一個腳本,該腳本將轉到PhantomJS網站上的快速入門指南的網址,然後單擊PhantomJS徽標,將該頁面帶到PhantomJS主頁。還要在點擊前後呈現網站圖片,以確保點擊正常工作。這是我現在的代碼:PhantomJS點擊圖片,然後等待加載

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

page.open('http://phantomjs.org/quick-start.html', function(status) { 
console.log(status); 
page.render('websiteBeforeClick.png'); 
console.log(page.frameUrl); //check url before click 

var element = page.evaluate(function() { 
    return document.querySelector('img[alt="PhantomJS"]'); 
}); 

page.sendEvent('click', element.offsetLeft, element.offsetTop, 'left'); 

window.setTimeout(function() { 
console.log(page.frameUrl); //check url after click 
}, 3000); 

console.log('element is ' + element); //check that querySelector() is returning an element 
page.render('websiteAfterClick.png'); 
phantom.exit(); 
}); 

問題是我的前後圖片是一樣的。這是我運行時的輸出。

success 
element is [object Object] 

進出口使用他們的SendEvent方法從這裏開始「http://phantomjs.org/api/webpage/method/send-event.html」但我不知道,如果它的工作。

此外爲什麼在我的window.setTimeout()執行console.log(page.frameUrl)?

我正在PhantomJS網站上查看他們的頁面自動化示例。特別是這一個「https://github.com/ariya/phantomjs/blob/master/examples/imagebin.js」。 我注意到他們的例子中使用

document.querySelector('input[name=disclaimer_agree]').click() 

但是,當我跟我的代碼試了一下我得到了一個錯誤。

document.querySelector('img[alt="PhantomJS"]').click(); 
TypeError: 'undefined' is not a function 

編輯#1:

我改變了我的代碼的結束部分是:

page.sendEvent('click', element.offsetLeft, element.offsetTop, 'left'); 


window.setTimeout(function() { 
    console.log(page.frameUrl); 
    page.render('websiteAfterClick.png'); 
    phantom.exit(); 
}, 3000); 

console.log('element is ' + element); 
}); 

現在我的後圖像是正確的。但現在我的問題是,如果我想繼續使用我的代碼,即點擊站點上的其他元素,我的新代碼是否必須全部嵌套在超時函數內部?

+0

'爲什麼在我的window.setTimeout()中沒有執行console.log(page.frameUrl)?因爲你有''phantom.exit()'纔有機會執行。 –

+0

@MattBurland我應該在哪裏放置我的phantom.exit()或我的window.setTimeout()來實現我想要的結果。 – user3803788

+0

看起來你已經知道了。至於額外的超時:一種方法是嵌套它們,但顯然這可能變得笨拙。另一種方法是在同一時間啓動它們,但最後暫停時間足以讓所有其他人完成,但如果其中一個速度很慢,這會有點冒險。更好的選擇是使用[jQuery的延遲](http://api.jquery.com/category/deferred-object/),這樣你就可以將它們全部綁在一起並等待它們。 –

回答

0

是的,您的新代碼將從setTimeout回調中調用。您可以直接嵌套代碼或編寫一個爲您封裝代碼的函數,並在setTimeout內調用該函數。

function anotherClick(){ 
    // something 
} 

page.sendEvent('click', element.offsetLeft, element.offsetTop, 'left'); 

window.setTimeout(function() { 
    console.log(page.frameUrl); 
    page.render('websiteAfterClick.png'); 
    anotherClick(); 
    phantom.exit(); 
}, 3000); 

還有另一種方法。您也可以使用多個setTimeout完全編寫它,但之後您無法對以前調用中的突發情況做出反應。

page.sendEvent('click', element.offsetLeft, element.offsetTop, 'left'); 

window.setTimeout(function() { 
    console.log(page.frameUrl); 
    page.render('websiteAfterClick.png'); 
}, 3000); 

window.setTimeout(function() { 
    // some more actions 
}, 6000); // you cannot know if this delay is sufficient 

window.setTimeout(function() { 
    phantom.exit(); 
}, 9000); // you cannot know if this delay is sufficient 

我會建議使用CasperJS,如果你想要做許多動作/導航步驟。

5

有一個例子功能phantom.waitFor(callback),我在following post解釋,這是不言而喻如下:

phantom.waitFor = function(callback) { 
    do { 
    // Clear the event queue while waiting. 
    // This can be accomplished using page.sendEvent() 
    this.page.sendEvent('mousemove'); 
    } while (!callback()); 
} 

這可以幫助簡化您的代碼,避免嵌套調用window.setTimeout(),這是不是很無論如何,因爲您正在等待預先設定的時間,而不是等待元素變得可見。一個例子是如下:

// Step 1: Open and wait to finish loading 
page.open('http://localhost/'); 
phantom.waitFor(function() {return !page.loading;}); 

// Step 2: Click on first panel and wait for it to show 
page.evaluate(function() { $("#activate-panel1").click(); }); 
phantom.waitFor(function() { 
    return page.evaluate(function() {return $("#panel1").is(":visible");}) 
}); 

// Step 3: Click on second panel and wait for it to show 
page.evaluate(function() { $("#activate-panel2").click(); }); 
phantom.waitFor(function() { 
    return page.evaluate(function() {return $("#panel2").is(":visible");}) 
}); 
console.log('READY!'); 
phantom.exit(); 

這將依次加載每個面板(即同步地),同時保持代碼簡單並避免嵌套回調。

希望它是有道理的。你也可以使用CasperJS作爲替代方案,其目的是使這個東西更簡單。