2012-10-03 22 views
21

Tôi đang tích hợp trình duyệt không đầu PhantomJS vào một dự án của tôi (hiện đang sử dụng phiên bản 1.6). Đối với hầu hết các phần, nó đang làm một công việc tuyệt vời tại hoàn thành mà tôi cần phải thực hiện. Tuy nhiên, tính chất không đồng bộ của cách gọi WebPage.open() hoạt động và cần gọi phantom.exit() tại một số điểm, làm cho nó khó xử lý các chuyển hướng phía máy khách khi bạn không thể dự đoán được chúng sẽ đi đâu đi.Cách kết thúc tập lệnh PhantomJS chỉ sau khi chuyển hướng phía máy khách đã diễn ra

Những gì tôi theo sau là cách gọi phantom.exit() chỉ sau khi làm mới meta (dẫn đến một trang khác) và chuyển hướng JavaScript gắn liền với những thứ như sự kiện onload đã được thực thi. Tôi có thể thấy lý do tại sao đây là vấn đề, bởi vì theo lý thuyết, chuyển hướng phía khách hàng có thể diễn ra bất kỳ số giây nào sau khi tải trang và tôi không thể yêu cầu khả năng thoát chỉ khi không có thêm chuyển hướng đang thực hiện diễn ra. Ngay bây giờ, giải pháp tốt nhất tôi có thể nghĩ đến là a) tự phát hiện sự hiện diện của các phần tử làm mới meta trên trang và xử lý với chính chúng, và b) sử dụng setInterval() để cho phép một lượng thời gian lành mạnh (ví dụ, 1- 1,5 giây) để trôi qua trước khi gọi phantom.exit(). Về cơ bản nó sẽ trông giống như sau:

var page = require('webpage').create(); 
var visitComplete = false; 
var url = "http://some.url"; 
var pageOpenedTime; 
setInterval(function() { 
    if (visitcomplete && typeof pageOpenedTime != 'undefined' && 
     new Date() - pageOpenedTime >= 1500) 
    { 
     phantom.exit(); 
    } 
), 1000); 
page.open(url, function() { 
    pageOpenedTime = new Date(); 
    if (!hasMetaRefresh(page)) { 
     visitComplete = true; 
    } 
}); 

function hasMetaRefresh(page) { 
    // Query the DOM here to detect meta refresh elements 
} 

Có ý tưởng nào tốt hơn không?

Chỉnh sửa: Tôi nên đề cập rằng suy nghĩ đầu tiên của tôi là có thể xảy ra sự kiện PhantomJS khi JavaScript được liên kết với tải trang ban đầu đã được thực hiện, nhưng cuộc gọi lại onLoadFinished xuất hiện trước khi thực hiện bất kỳ JavaScript trang, bao gồm cả sự kiện tải. Tôi cũng đã thực hiện một số thử nghiệm về khoảng thời gian mà tôi có thể đợi, và trong khi 1000 ms đủ dài để chuyển hướng JavaScript (thông qua sự kiện tải trọng cơ thể) được thực thi trong một trang thử nghiệm nhỏ, 100 ms không đủ dài.

+0

Tôi đã sử dụng cùng một cách tiếp cận trong dự án của mình, tức làthêm một chút tạm dừng giữa các cuộc gọi. Tôi e rằng đó là lựa chọn duy nhất (hiện tại). –

Trả lời

0

Tôi có ý tưởng sử dụng bộ tính giờ được giả lập cho mục đích này. Giả sử chúng tôi bao gồm "a mocked timer" trong trang. Bằng cách đó, bạn có thể tua nhanh thời gian để tránh thời gian nhàn rỗi js. Xem các ví dụ trên trang GitHub.

Đây chỉ là một cách tiếp cận để làm cho mọi thứ diễn ra nhanh hơn, nhưng như bạn mong đợi, không thể chắc chắn nếu sự kiện chuyển hướng sẽ được kích hoạt trong tương lai.

8

Tôi đã gặp vấn đề tương tự khi tải trang đang sử dụng Optimizely và biến thể là chuyển hướng location.href.

Tôi hiện đang sử dụng gọi lại onNavigationRequest bên trong hàm "renderPage". Những chuyển hướng tối ưu đó không còn chặn nữa và tôi không cần thời gian chờ tùy ý.

var webpage = require('webpage'); 
var page = null; 

var renderPage = function (myurl) { 
    page = webpage.create(); 

    page.onNavigationRequested = function(url, type, willNavigate, main) { 
     if (main && url!=myurl && url.replace(/\/$/,"")!=myurl&& (type=="Other" || type=="Undefined")) { 
     // main = navigation in main frame; type = not by click/submit etc 

      log("\tfollowing "+myurl+" redirect to "+url) 
      myurl = url; 
      page.close(); 
      renderPage(url); // rerun this function wit the new URL 
     } 
    }; // on Nav req 

    page.open(myurl, function(status) { 
     if (status==="success") { 
      page.render("screenshot.jpg"); 
     } else { 
      page.close(); 
     } 
    }); // page open 
} // render page 


renderPage("http://some.domain.com"); 

xem tài liệu: http://phantomjs.org/api/webpage/handler/on-navigation-requested.html

+0

Điều này sẽ làm việc cho chuyển hướng đầu trang, chuyển hướng js và hành động của người dùng phải không? – CMCDragonkai

+0

@CMCDragonkai: mỗi lần sử dụng của tôi hoạt động trên BẤT CỨ thay đổi trong URL - vì vậy chúng tôi nhận được 302 -> trình duyệt đưa ra yêu cầu mới -> thay đổi điều hướng Điều tương tự nếu bạn thực hiện một vị trí.href qua JavaScript; Các giao dịch người dùng (ví dụ, mouseclicks mô phỏng và formubmits vv được xử lý khác nhau: giá trị "type" với thay đổi (type: Các giá trị có thể bao gồm: 'Undefined', 'LinkClicked', 'FormSubmitted', 'BackOrForward', 'Reload', 'FormResubmitted' , 'Khác') – ProfessionalHack

0

Tôi đã kiểm tra loại hình ví dụ cho phantomjs chuyển hướng xử lý: may mắn lớn.

Hiện tại, không có bản sửa lỗi chung cho nó. Nếu bạn vá một số tập lệnh as suggested here, nó sẽ thất bại trong trường hợp khác, ví dụ: bên cạnh việc sử dụng location.href, sử dụng javascript để chuyển hướng. Tôi chưa thử nghiệm cơ thể. Sau một vài tiền vá ở đây và ở đó, tôi bỏ cuộc.

Tôi chỉ sử dụng firefox kích hoạt "nặng" Selenium để giải quyết vấn đề của mình. Nếu bạn cần tải nhiều trang, thay vì khởi động lại firefox, chỉ cần sử dụng webdriver.delete_all_cookies() để làm sạch một số bắt. Nó cung cấp cho tôi kết quả đáng tin cậy (mà tôi cần phải thực hiện chụp màn hình, tải xuống html, nhận url cuối cùng và nhiều thứ khác) so sánh với các phantomj.

Các vấn đề liên quan