2012-09-23 10 views
11

Skrobię stronę na Facebooku za pomocą modułu węzła PhantomJS (https://github.com/sgentle/phantomjs-node), ale kiedy próbuję ocenić stronę, nie oceni ona funkcji, którą do niej podchodzę. Wykonywanie go w autonomicznym skrypcie i uruchamianie go za pomocą interpretera węzłów działa. Ten sam kod w aplikacji Express.js nie działa.Phantomjs nie wykonuje funkcji w funkcji page.evaluate

To jest mój kod

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); 
      }); 
     }); 
    }); 
}; 

Wyjście uzyskać:

{"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"} 

Więc, jak widać, to wywołuje funkcję Phantom oddzwonienia (drugi parametr w funkcji oceny) o wartości null argument, ale nie wykonuje pierwszego parametru (funkcja ewaluatora, która drukuje iterujący krok X).

Ktoś wie, na czym polega problem?

Odpowiedz

23

Nie jestem pewien, jakiej wersji PhantomJS używasz, ale jeśli chodzi o dokumentację wersji 1.6+ logowanie w ocenianym skrypcie spowoduje zarejestrowanie wyniku na zawartej stronie. Nie zaloguje się do konsoli. Aby dostać się, że trzeba by związać zalogowaniu na stronach onConsoleMessage imprezy:

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

Co do wyniku nie jest dostępny: Funkcja page.evaluate bierze argumenty jak tak - pierwszy z nich to funkcja do wykonania i reszta jest przekazywana jako wejście do tej funkcji. Wynik jest zwracany bezpośrednio:

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

evaluate jest uruchamiana w trybie piaskownicy, co oznacza, że ​​żadna ze zmiennych zdefiniowanych w środowisku zawierającym są dostępne, w tym cb lub nawet przedmiot phantom lub jakiekolwiek funkcje, które mogą być zdefiniowane .

Możesz jawnie tunelować informacje w piaskownicy jako dodatkowe argumenty pod adresem evaluate.

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

PhantomJS”to drzwi do kontekstu DOM (kontekst strona). Dostęp do DOM jest możliwy tylko za pośrednictwem tej funkcji. Ponieważ funkcja jest piaskowana, nie można używać zmiennych zdefiniowanych poza nią i muszą one być jawnie przekazywane. Istnieją ograniczenia co można minęły i obecnie (choć docs):

Uwaga: Argumenty i wartość zwracana z funkcją evaluate musi być prosty prymitywny przedmiot. Zasada: jeśli może być serializowana przez JSON, to jest w porządku.

Zamknięcia, funkcje, węzły DOM itd. Będą nie działają!

phantomjs-node stanowi pomost pomiędzy PhantomJS i węzła.js i jako taki ma nieco inny interfejs API niż sam PhantomJS. Funkcje synchroniczne w PhantomJS nie zwracają niczego w phantomjs-node, ale pobierają wywołanie zwrotne, w którym wynik jest przekazywany. Oddzwanianie wykonywane jest w kontekście zewnętrznym i nie jest piaskowane.

argumenty mogą być przekazywane w ten sposób:

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

Najnowsza wersja mostu phantomjs węzłów powinny powrócić obietnicą zamiast polegania na funkcji zwrotnej. –

+0

To naprawdę mi pomogło, dziękuję –

+0

Cóż, tracę około 6 godzin próbując pewnych rzeczy wewnątrz funkcji 'assess' ... Jeśli jest w niej jakaś inna funkcja lub jakikolwiek inny typ, to nawet nie rozpocznie wykonywania funkcji ... Jedna ważna rzecz. ** Nie zapomnij przeczytać dokumentacji ** –

2

Następujące pracował dla mnie oceniać strony:

page.evaluate(function(s) { 
    return document.querySelector(s) 
}, 'body').then(res => { 
    console.log(res) 
}) 
Powiązane problemy