2009-03-14 37 views
6

Ich beantwortete einige Quizfragen für ein Interview und die Frage war, wie würde ich Screen Scraping machen. Das heißt, den Inhalt einer Webseite auswählen, vorausgesetzt, Sie haben keine besser strukturierte Möglichkeit, die Informationen direkt abzufragen (z. B. einen Webdienst).Screen Scraping: Reguläre Ausdrücke oder XQuery-Ausdrücke?

Meine Lösung war eine XQuery Ausdruck verwenden. Der Ausdruck war ziemlich lang, weil der Inhalt, den ich brauchte, ziemlich tief in der HTML-Hierarchie war. Ich musste einen fairen Weg durch die Vorfahren suchen, bevor ich ein Element mit einem id Attribut fand. Zum Beispiel sieht wie folgt aus einer Amazon.com-Seite für Produkt-Maß Schaben:

//a[@id="productDetails"] 
/following-sibling::table 
//h2[contains(child::text(), "Product Details")] 
/following-sibling::div 
//li 
/b[contains(child::text(), "Product Dimensions:")] 
/following-sibling::text() 

, dass ein ziemlich bösen Ausdruck ist, aber das ist, warum Amazon einen API Web-Service zur Verfügung stellt. Wie auch immer, es ist nur ein Beispiel. Die Frage ging nicht um Amazon, es geht um Screen Scraping.

Der Interviewer mochte meine Lösung nicht. Er hielt es für fragil, da eine Änderung des Seitendesigns von Amazon das Umschreiben des XQuery-Ausdrucks erfordern würde. Das Debuggen eines XQuery-Ausdrucks, der nichts auf der Seite entspricht, auf die er angewendet wird, ist schwierig.

Ich war nicht mit seinen Aussagen nicht einverstanden, aber ich dachte nicht, seine Lösung war eine Verbesserung: er dachte, es ist besser, einen regulären Ausdruck zu verwenden, und nach Inhalt und Markup in der Nähe des Versandgewichtes zu suchen. Zum Beispiel, mit Perl:

Mein Gegenargument war, dass dies auch anfällig für Amazon ihren HTML-Code ändern. Sie könnten HTML-Tags in Großbuchstaben buchstabieren (<LI>) oder CSS-Attribute hinzufügen oder <b> zu <span> ändern oder die Bezeichnung "Product Dimensions:" zu "Dimensions:" oder viele andere Arten von Änderungen ändern. Mein Punkt war, dass reguläre Ausdrücke die Schwächen, die er in meiner XQuery-Lösung hervorrief, nicht lösen.

Darüber hinaus können reguläre Ausdrücke jedoch falsch positive Ergebnisse finden, sofern Sie dem Ausdruck nicht genügend Kontext hinzufügen. Es kann auch unbeabsichtigt Inhalt zuordnen, der zufällig in einem Kommentar oder einer Attributzeichenfolge oder einem CDATA-Abschnitt enthalten ist.

Meine Frage ist, welche Technologie verwenden Sie Bildschirm scraping? Warum haben Sie diese Lösung gewählt? Gibt es einen zwingenden Grund, einen zu verwenden? Oder nie den anderen benutzen? Gibt es neben den oben gezeigten eine dritte?

PS: Nehmen wir als Argument an, dass es keine Web-Service-API oder einen direkteren Weg gibt, den gewünschten Inhalt zu erhalten.

Antwort

3

Ich würde einen regulären Ausdruck verwenden, aus den Gründen, die der Manager gab, ein paar (mehr tragbar, einfacher für externe Programmierer zu folgen, usw.).

Ihr Gegenargument trifft nicht den Punkt, dass seine Lösung im Hinblick auf lokalen Änderungen zerbrechlich war, während Ihr in Bezug auf globalen Veränderungen zerbrechlich ist. Alles, was seinen Willen bricht, wird wahrscheinlich deinen brechen, aber nicht umgekehrt.

Schließlich ist es viel einfacher, Slop/Flex in seine Lösung zu bauen (wenn Sie zum Beispiel mit mehreren kleinen Variationen in der Eingabe zu tun haben).

4

Ich würde einen regulären Ausdruck verwenden, aber nur, weil die meisten HTML-Seiten kein gültiger XML-Code sind, sodass Sie XQUERY nie zum Laufen bringen würden.

Ich weiß XQuery nicht, aber das sieht für mich wie ein XPATH-Ausdruck aus. Wenn ja, sieht es bei so vielen "//" Operatoren etwas teuer aus.

+0

Dies ist der Hauptgrund für die Vermeidung von XML-basierten Web Scraping. Kein XML-Prozessor ist so fehlerverzeihend wie ein Browser. Die Seite muss nur eine wohlgeformte Regel brechen, um XQuery vollständig unbrauchbar zu machen. – harpo

1

Tatsächlich finde ich CSS-Suchausdrücke einfacher zu lesen als beide. Es gibt wahrscheinlich mindestens eine Bibliothek in der Sprache Ihrer Wahl, die eine Seite analysiert und Ihnen ermöglicht, CSS-Anweisungen zum Auffinden bestimmter Elemente zu schreiben. Wenn es in der Nähe einen geeigneten Klassen- oder ID-Haken gibt, ist der Ausdruck ziemlich trivial. Greifen Sie andernfalls zu den Elementen, die Ihnen angemessen erscheinen, und durchlaufen Sie sie, um diejenigen zu finden, die Sie benötigen.

Für zerbrechlich, gut, sie sind alle zerbrechlich. Screen-Scraping ist per definitionem davon abhängig, dass der Autor dieser Seite sein Layout nicht drastisch ändert. Gehen Sie mit einer Lösung, die lesbar ist und später leicht geändert werden kann.

1

Eine nicht spröde Lösung zum Screen-Scraping? Viel Glück für den Interviewer: Nur weil reguläre Ausdrücke eine Menge Kontext wegwerfen, bedeutet das nicht, dass sie weniger brüchig sind, nur dass sie auf andere Weise brüchig sind. Sprödigkeit kann nicht einmal ein Nachteil sein: Wenn sich etwas in der Quellwebseite ändert, ist es Ihnen oft besser, wenn Ihre Lösung einen Alarm auslöst, anstatt zu versuchen, auf eine clevere (und unvorhersehbare) Weise zu kompensieren. Wie du angemerkt hast. Diese Dinge hängen immer von Ihren Annahmen ab: In diesem Fall, was eine wahrscheinliche Änderung darstellt.

Ich bin ziemlich begeistert von der HTML agility pack: Sie erhalten Toleranz von nicht-XHTML-kompatiblen Webseiten kombiniert mit der Ausdruckskraft von XPath.

2

Versuchen Sie JTidy oder BeautifulSoup funktioniert gut für mich. sicherlich // XPATH experssion ist ziemlich teuer zu verschrotten.

1

Reguläre Ausdrücke sind sehr schnell und arbeiten mit Nicht-XML-Dokumenten. Das sind wirklich gute Punkte gegen XQuery. Ich denke jedoch, dass einige Konverter XHTML wie ordentlich und vielleicht etwas einfacher XQuery, wie nur der letzte Teil von Ihnen:

//b[contains(child::text(), "Product Dimensions:")]/following-sibling::text() 

ist eine sehr gute Alternative.

Grüße,

Rafal Rusin

1

auf HTML-Seiten zu umgehen, ist es am besten HTMLAgilityPack (und mit einigen Linq-Codes) verwendet werden. Es ist eine großartige Möglichkeit, alle Elemente zu analysieren und/oder direkt mit XPath zu suchen. Meiner Meinung nach ist es genauer als RegEx und einfacher zu programmieren. Ich war ein bisschen zögerlich, es vorher zu benutzen, aber es ist sehr einfach, Ihrem Projekt hinzuzufügen, und ich denke, dass der de-Faktor-Standard für das Arbeiten mit html ist. http://htmlagilitypack.codeplex.com/

Viel Glück!

+0

Danke, ja, HTML Agility Pack wurde in einer anderen Antwort von Pontus Gagge vorgeschlagen. Ich frage mich, was HTML Agility Pack intern verwendet - XPath, reguläre Ausdrücke oder eine andere benutzerdefinierte DOM-Analyse oder etwas anderes. –

+1

Mit HtmlAgilityPack können Sie das gesamte DOM durch DocumentNode.ChildNodes durchlaufen. Zum Beispiel: Für jeden VoTag in voMyHTML.DocumentNode.Childnodes oder Sie können mit voMyHTML.DocumentNode.SelectSingleNode (vsXPath) in einem einzigen Knoten vergrößern oder Sie können auch LINQ verwenden: voElements = (Von voTag In voMyHTML.DocumentNode.ChildNodes Wo voTag.GetAttributeValue ("class") = "myClass" Wählen Sie voTag) –