2008-12-27 5 views
6

Ich möchte die Benutzerseiten von SO kratzen, um den Besitzern meiner Symbolleiste die aktualisierten Informationen über ihre Fragen/Antworten/etc ...So führen Sie einen Hintergrund laden und Scraping einer Seite mit XUL/Firefox Extension

Das bedeutet, ich muss dies im Hintergrund tun, analysieren Sie die Seiten, extrahieren Sie den Inhalt, vergleichen Sie es mit dem letzten Lauf und präsentieren Sie dann die Ergebnisse entweder auf der Symbolleiste oder der Statusleiste oder alternativ in einem Popup-Fenster irgendeiner Art. Und all das muss getan werden, während der Benutzer seinen Geschäften nachgeht, ohne unterbrochen zu werden oder sogar auf SO zu sein.

Ich habe ziemlich gründlich sowohl auf Google als auch auf dem Mozilla Wiki nach einer Art Hinweis gesucht. Ich bin sogar soweit gegangen, ein paar andere Erweiterungen herunterzuladen, von denen ich denke, dass sie das Gleiche tun. Leider hatte ich nicht die Zeit, alle und die, die ich angeschaut habe, alle Daten APIs (Services, WebServices, XML) zu verwenden, nicht HTML-Verschrottung.

Alter Fragetext

Ich bin ein schönes Plätzchen suchen zu lernen, wie ich eine Seite in einer Funktion laden genannt kaufen den berüchtigten set_timeout() ein Screen-Scraping im Hintergrund zu verarbeiten.

Meine Idee ist es, die Ergebnisse von solchen Scraping in einer Statusleiste zu präsentieren, nur für den Fall, dass etwas aus dem letzten Lauf geändert wird.

Gibt es eine versteckte Überlagerung oder eine andere Täuschung?

Antwort

6

Bei XUL/Firefox, was Sie brauchen, ist die nsIIOService-Schnittstelle, die Sie wie folgt zu erreichen:

var mIOS = Components.classes["@mozilla.org/network/io-service;1"]. 
    getService(Components.interfaces.nsIIOService); 

Dann müssen Sie einen Kanal erstellen, und öffnen Sie eine asynchrone Verbindung:

var channel = mIOS.newChannel(urlToOpen, 0, null); 
channel.asyncOpen(new StreamListener(), channel); 

der Schlüssel hier ist das StreamListener Objekt:

var StreamListener = function() { 
    return { 
     QueryInterface: function(aIID) { 
      if (aIID.equals(Components.interfaces.nsIStreamListener) || 
       aIID.equals(Components.interfaces.nsISupportsWeakReference) || 
       aIID.equals(Components.interfaces.nsISupports)) 
       return this; 
      throw Components.results.NS_NOINTERFACE; 

     onStartRequest: function(aRequest, aContext) 
      { return 0; }, 

     onStopRequest: function(aRequest, aChannel /* aContext */, aStatusCode) 
      { return 9; }, 

     onDataAvailable: function(aRequest, aContext, aStream, aOffset, aCount) 
      { return 0; } 
    }; 
} 

Sie haben um die Details in den onStartRequest, onStopRequest, onDataAvailable Funktionen zu füllen, aber das sollte genug sein, um Sie in Gang zu bringen. Sie können sehen, wie ich diese Schnittstelle in meiner Firefox-Erweiterung verwendet habe (sie heißt IdentFavIcon und kann auf der Mozilla Add-ons-Seite gefunden werden).

Der Teil, über den ich unsicher bin, ist, wie Sie diese Seite Anfrage von Zeit zu Zeit auslösen können, set_timeout() sollte wahrscheinlich funktionieren, obwohl.

Edit:

  1. Siehe Beispiel here (siehe Abschnitt Herunterladen von Bildern) für ein Beispiel, wie heruntergeladene Daten in einer einzigen Variablen zu sammeln; und
  2. Siehe this page zum Konvertieren einer HTML-Quelle in einen DOM-Baum.

HTH.

+0

könnte die resultierende "Seite" dann als DOM-Objekt verwendet werden? –

+0

Ich habe versucht, dies in meinem Schnitt zu beantworten. –

1

Aus privilegiertem JavaScript, d. H. JS in einer Erweiterung, können Sie versteckte iframe s erstellen; Das Herunterladen der angegebenen Seite ist so einfach wie das Festlegen des Ortes in diesem Rahmen.

Wenn Sie eine einfache, statische Seite, die Sie besitzen, herunterziehen, sollte set_timeout in Ordnung sein. Aber in diesem Fall, warum nicht XHR verwenden?

Wenn Sie willkürliche Seiten, solche mit dynamischen Elementen oder jede Menge Inhalt abreißen, empfehle ich stattdessen, Ihr Scharren der Seite mit Document.onload Event-Handlern auszulösen. Es ist viel zuverlässiger, und Sie können schlau werden, die Seite zum frühestmöglichen Zeitpunkt zu scrappen, aber wenn Sie wissen, dass der erforderliche Inhalt da ist.

Ich glaube nicht, dass es ein bestimmtes Tutorial zu diesem Thema gibt, aber die Mozilla Developer Center, die Sie sicher schon gefunden haben, ist absolut exzellent - die beste technische Dokumentation meiner Meinung nach!

+0

Bietet XHR auf einer Erweiterung Zugriff auf andere Domänen? Kann ich Firefox-DOM-Funktionen für HTML aus XHR verwenden? –

3

Ich bin nicht sicher, ob ich die Frage ganz verstanden, sondern versuchen, ein paar offensichtliche Alternative Fragen zu beantworten:

Wenn Sie statische Web-Seite suchen sind Schaben BeautifulSoup (Python) ist eines der besten und einfachsten .

Wenn Sie nach Änderungen auf einer Ajax-basierten Seite suchen, die sich im Laufe der Zeit ändert, müssen Sie den Code in einer Endlosschleife ausführen. Aber rufen Sie die Site nicht zu häufig ab, da sie einen Bandbreitenverbrauch erkennt und möglicherweise Ihre IP-Adresse blockiert.

Wenn Sie suchen, um einige Javascript gerenderten Ticker oder etwas zu kratzen, kann das nicht getan werden, bis die Seite gerendert wird, daher nicht mit BeautifulSoup allein möglich. Sie müssen einen kopflosen Browser wie Crowbar - Similie (verwendet XULRunner) verwenden, der den Javascript-Inhalt auf einem Headless-Browser rendert und die Ausgabe dieses gerenderten Inhalts kann als Eingabe für den BeautifulSoup-Scraper verwendet werden.

+0

Ich muss es in einer Symbolleiste tun, die eine Erweiterung von Firefox ist. Siehe meine Klarstellung. –