2016-04-27 3 views
0

Im Moment verwende ich ein Intervall, um nach Änderungen zu suchen. Wenn es irgendwelche Änderungen gibt, wird mein Skript mich warnen und falls nicht, wird es eine Sekunde warten und dann erneut prüfen. Gibt es einen besseren Weg, dies zu tun? Die Informationen, nach denen mein Skript sucht, sind zeitkritisch. Wenn das Skript mich zu langsam alarmiert, kann ich nichts mit den Informationen anfangen. Also, was frage ich, gibt es einen besseren Ansatz, so dass ich sofort auf Veränderungen aufmerksam werden kann?Bessere Möglichkeit, zeitkritische Informationen zu scrappen?

Code:

page.open(url) 
timer = Date.now(); 
do{ 
if(Date.now()-timer>=1000){ 
//Look for change 
} 
timer =Date.now() 
}while (no chnages) 

Antwort

0

PhantomJS funktioniert nicht gut, wenn eine synchrone Schleife, wie in Ihrem Fall verwenden. Da JavaScript single-threaded ist, wird dies die Ausführung blockieren.

Mit Verzögerung

Sie können sicher setTimeout oder setInterval für diesen Fall verwenden:

var interval = 1000; // change according to needs 
page.open(url, function(){ 
    setTimeout(function retry(){ 
     var condition = page.evaluate(...); 
     if (!condition) { 
      setTimeout(retry, interval); 
     } else { 
      // TODO: what to do on success 
     } 
    }, interval); 
}); 

Das setInterval Beispiel ähnlich aussehen würde. Genau das tut waitFor() im Beispielordner von PhantomJS. Das Problem bei diesen Ansätzen ist natürlich eine mögliche Verzögerung zwischen der Änderung und einer Benachrichtigung über diese Änderung. Sie können das Wiederholungsintervall natürlich verringern, bis Sie keinen Unterschied mehr sehen.

Ohne Verzögerung

Es gibt mindestens zwei Möglichkeiten, um eine Änderung unverzüglich zu erkennen.

  • Register zum page.onResourceReceived event und versuchen zu bestimmen, ob die Änderung, die Sie interessiert sind hat mit den begrenzten Informationen passieren vorgesehen (es ist nicht möglich, in den Körper des Antrags zu sehen).

  • In PhantomJS 2.x (in 1.x möglicherweise mit einem Präfix), können Sie ein MutationObserver schaffen für Veränderungen in dem DOM im Seitenkontext zu betrachten (in page.evaluate()) und Sie dann eine sofortige Benachrichtigung von dem schicken Seitenkontext (vom MutationObserver-Ereignishandler) zum äußeren Kontext unter Verwendung der window.callPhantom and page.onCallback pair.

1

Wenn die Ressource Sie richtig die letzte Änderung Header Einstellung sind holen, ist es effizienter sein könnte eine HTTP HEAD-Anforderung zuerst zu machen und nur die Seite in PhantomJS öffnen, wenn es geändert wurde. Dies wäre definitiv komplexer, so dass es sich lohnt, zuerst andere Optionen zu prüfen.

Ein Beispielcode, der die letzte Modifikationszeit unter http://stackoverflow.com überprüft, ist wie folgt.

var url = 'http://stackoverflow.com'; 
var page = require('webpage').create(); 
var interval = 1000; // change according to needs 
var previousLastModified; 
(function modifiedCheck() { 
    var xhr = new XMLHttpRequest(); 
    xhr.onreadystatechange = function() { 
     if (xhr.readyState == 4 && xhr.status == 200) { 
      var lastModified = xhr.getResponseHeader("Last-Modified"); 
      if (lastModified !== previousLastModified) { 
       page.open(url, function(status) { 
        if (status === 'success') { 
         previousLastModified = lastModified; 
         // TODO: do something with fetched page 
         console.log('fetched page.'); 
        } 
        setTimeout(modifiedCheck, interval); 
       }); 
      } else { 
       setTimeout(modifiedCheck, interval); 
      } 
     } 
    }; 
    console.log('making HEAD request.'); 
    xhr.open('HEAD', url); 
    xhr.send(); 
})(); 

Sie können von der Konsolenprotokollierung sehen, dass die Seite für 1 Minute zwischengespeichert wird.

Die selbstausführende modifiedCheck-Funktion im Beispiel verwendet anonyme Funktionen zur asynchronen Verarbeitung des Ergebnisses des AJAX-Aufrufs und der PhantomJS-Seitenladung, wodurch die Blockierung begrenzt wird.

Hinweis: Sie müssen PhantomJS mit der Option --web-security=false ausführen, damit der AJAX-Aufruf ohne Fehler ausgeführt werden kann.