2012-09-23 39 views
11

Tôi đang cạo một trang Facebook với mô-đun nút PhantomJS (https://github.com/sgentle/phantomjs-node), nhưng khi tôi thử đánh giá trang, nó không đánh giá hàm tôi chuyển cho nó. Thực thi nó trong một kịch bản độc lập và chạy nó với trình thông dịch Node hoạt động .. Mã tương tự trong ứng dụng Express.js không hoạt động.Phantomjs không thực thi chức năng trong page.evaluate chức năng

Đây là mã của tôi

facebookScraper.prototype.scrapeFeed = function (url, cb) { 
    f = ':scrapeFeed:'; 

    var evaluator = function (s) { 
     var posts = []; 

     for (var i = 0; i < FEED_ITEMS; i++) { 
      log.info(__filename+f+' iterating step ' + i); 
      log.info(__filename+f+util.inspect(document, false, null)); 
     } 

     return { 
      news: posts 
     }; 
    } 

    phantom.create(function (ph) { 
     ph.createPage(function (page) { 
      log.fine(__filename+f+' opening url ' + url); 
      page.open(url, function (status) { 
       log.fine(__filename+f+' opened site? ' + status); 
       setTimeout(function() { 
        page.evaluate(evaluator, function (result) { 
         log.info(__filename+f+'Scraped feed: ' + util.inspect(result, false, null)); 
         cb(result, ph); 
        }); 
       }, 5000); 
      }); 
     }); 
    }); 
}; 

Kết quả tôi nhận được:

{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opening url <URL> ","timestamp":"2012-09-23T18:35:10.151Z"} 
{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opened site? success","timestamp":"2012-09-23T18:35:12.682Z"} 
{"level":"info","message":"PATH/fb_regular.js:scrapeFeed: Scraped feed: null","timestamp":"2012-09-23T18:35:12.687Z"} 

Vì vậy, như bạn thấy, nó gọi hàm phantom callback (tham số thứ hai trong đánh giá chức năng) với một null đối số, nhưng nó không thực hiện tham số đầu tiên (hàm đánh giá của tôi, mà in bước lặp X).

Bất kỳ ai cũng biết vấn đề là gì?

Trả lời

23

Tôi không chắc chắn về phiên bản PhantomJS bạn đang sử dụng, nhưng đối với tài liệu về phiên bản 1.6+ ghi nhật ký bên trong tập lệnh được đánh giá sẽ ghi lại kết quả trong trang đã chứa. Nó sẽ không đăng nhập vào giao diện điều khiển của bạn. Để có được điều đó bạn sẽ phải ràng buộc đăng nhập vào trang onConsoleMessage sự kiện:

page.onConsoleMessage = function (msg) { console.log(msg); }; 

Đối với kết quả không phải là có sẵn: Chức năng page.evaluate mất lập luận như vậy - một trong những đầu tiên là một chức năng được thực thi và phần còn lại được truyền làm đầu vào cho hàm đó. Kết quả sẽ được trả về trực tiếp:

var title = page.evaluate(function (s) { 
    return document.querySelector(s).innerText; 
}, 'title'); 
console.log(title); 
9

evaluate đang chạy trong chế độ sandbox, có nghĩa là không ai trong số các biến được định nghĩa trong môi trường chứa có sẵn, bao gồm cb hoặc thậm chí các đối tượng phantom hay bất kỳ chức năng mà bạn có thể đã được xác định .

Bạn có thể khai thác thông tin một cách rõ ràng vào hộp cát làm đối số bổ sung cho evaluate.

page.evaluate(function(cb){...}, cb); 
4

PhantomJS' là cánh cửa với bối cảnh DOM (bối cảnh trang). Chỉ có thể truy cập DOM thông qua chức năng này. Vì hàm này được sandbox, bạn không thể sử dụng các biến được định nghĩa bên ngoài nó và chúng phải được chuyển một cách rõ ràng. Có những hạn chế những gì có thể được thông qua trong và ngoài mặc dù (docs):

Lưu ý: Những lập luận và giá trị trả về cho evaluate chức năng phải là một đối tượng nguyên thủy đơn giản. Quy tắc của ngón tay cái: nếu nó có thể được tuần tự hóa thông qua JSON, thì nó là tốt.

Đóng, chức năng, nút DOM, v.v. sẽ không hoạt động!

phantomjs-node là cầu nối giữa PhantomJS và nút.js và như vậy có một API hơi khác so với bản thân PhantomJS. Các hàm đồng bộ trong PhantomJS không trả về bất cứ thứ gì trong phantomjs-node, nhưng hãy gọi lại nơi kết quả được truyền vào. Hàm gọi lại thực hiện trong ngữ cảnh bên ngoài và không được sandboxed.

Những lập luận có thể được thông qua bằng cách này:

page.evaluate(function(arg1, arg2){ 
    // use arg1 and arg2 in the page 
    // return `result` 
}, function(result){ 
    // use `result` in the node context 
}, "some arg1", "another arg"); 
+1

Phiên bản mới nhất của các cầu phantomjs-nút cần trả về một Promise thay dựa vào chức năng gọi lại. –

+0

Điều này thực sự giúp tôi, cảm ơn bạn –

+0

Vâng, tôi mất khoảng 6 giờ thử một số thứ bên trong hàm 'evaluation' ... Nếu có một hàm bên trong nó, hoặc bất kỳ kiểu nguyên thủy nào, nó thậm chí sẽ không bắt đầu thực thi hàm ... Một điều quan trọng. ** Đừng quên đọc tài liệu ** –

2

Sau đây làm việc cho tôi để đánh giá một trang:

page.evaluate(function(s) { 
    return document.querySelector(s) 
}, 'body').then(res => { 
    console.log(res) 
}) 
Các vấn đề liên quan