2009-03-14 10 views
6

Odpowiedziałem na kilka pytań do wywiadu, a pytanie dotyczyło sposobu, w jaki zrobię skrobanie ekranu. Oznacza to, że wybieranie treści ze strony internetowej, zakładając, że nie masz lepiej zorganizowanego sposobu bezpośredniego wyszukiwania informacji (np. Usługi internetowej).Skrobanie ekranu: wyrażenia regularne lub wyrażenia XQuery?

Moim rozwiązaniem było użycie wyrażenia XQuery. Wyrażenie było dość długie, ponieważ zawartość, której potrzebowałem, była dość głęboka w hierarchii HTML. Musiałem przeszukać przodków w uczciwy sposób, zanim znalazłem element z atrybutem id. Na przykład, zgarniania stronę Amazon.com o produkt Wymiary wygląda następująco:

//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() 

To dość nieprzyjemny wyraz, ale dlatego Amazon udostępnia API usług internetowych. W każdym razie to tylko jeden przykład. Pytanie nie dotyczyło Amazona, chodzi o skrobanie ekranu.

Wywiad nie spodobał się mojemu rozwiązaniu. Myślał, że jest delikatny, ponieważ zmiana projektu strony przez Amazon może wymagać przepisania wyrażenia XQuery. Debugowanie wyrażenia XQuery, które nie pasuje do niczego na stronie, na które zostało zastosowane, jest trudne.

Nie zgadzałem się z jego oświadczeniami, ale nie sądziłem, że jego rozwiązanie stanowi jakąkolwiek poprawę: pomyślał, że lepiej użyć wyrażenia regularnego i wyszukać treść i oznaczenia w pobliżu ciężaru przesyłki. Na przykład, przy użyciu Perl:

$html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s; 

mój kontrargument, że to jest również podatne na Amazon zmieniając ich kod HTML. Mogą literować znaczniki HTML wielkimi literami (<LI>) lub dodawać atrybuty CSS lub zmienić <b> na <span> lub zmienić etykietę "Wymiary produktu:" na "Wymiary:" lub wiele innych rodzajów zmian. Chodzi mi o to, że wyrażenia regularne nie rozwiązują słabości, które wywoływał w moim rozwiązaniu XQuery.

Ale dodatkowo wyrażenia regularne mogą znajdować fałszywe trafienia, chyba że dodasz wystarczająco kontekstu do wyrażenia. Może także przypadkowo dopasować zawartość, która znajduje się wewnątrz komentarza, lub ciąg znaków atrybutu lub sekcji CDATA.

Moje pytanie brzmi, jakiej technologii używasz do skrobania ekranu? Dlaczego wybrałeś to rozwiązanie? Czy jest jakiś ważny powód, aby go użyć? Lub nigdy nie używać drugiej? Czy istnieje trzeci wybór oprócz tych, które pokazałem powyżej?

PS: Załóżmy dla celów argumentu, że nie ma interfejsu API usług internetowych ani innego bardziej bezpośredniego sposobu zdobycia pożądanej treści.

Odpowiedz

3

Używałbym wyrażeń regularnych, z powodów, które podał menedżer, zabezpieczyć kilka (bardziej przenośne, łatwiejsze dla zewnętrznych programistów, itp.).

Twój licznik argumentem zdobywa punkt, że jego rozwiązanie było delikatne w odniesieniu do lokalnych zmian natomiast twój jest nietrwały w odniesieniu do globalnych zmian. Wszystko, co łamie jego wolę, prawdopodobnie łamie twoją, ale nie na odwrót.

Wreszcie, o wiele łatwiej jest budować slop/flex w swoim rozwiązaniu (jeśli, na przykład, masz do czynienia z wieloma niewielkimi zmianami w danych wejściowych).

4

Używałbym wyrażenia regularnego, ale tylko dlatego, że większość stron HTML nie jest poprawnym kodem XML, więc nigdy nie dostaniesz XQUERY do pracy.

Nie znam XQuery, ale dla mnie wygląda to na wyrażenie XPATH. Jeśli tak, to wygląda na trochę drogiego z tak wieloma operatorami "//" w nim.

+0

Jest to główny powód uniknięcia skrobania w Internecie opartego na XML. Żaden procesor XML nie jest tak wyrozumiały jak przeglądarka. Strona musi tylko złamać jedną zasadę dobrego uformowania, aby całkowicie zrezygnować z XQuery. – harpo

1

Rzeczywiście znajduję łatwiejsze do odczytania wyrażenia CSS niż jedno z nich. Prawdopodobnie istnieje co najmniej jedna biblioteka w wybranym języku, która będzie analizować stronę i umożliwia pisanie dyrektyw CSS w celu zlokalizowania poszczególnych elementów. Jeśli w pobliżu znajduje się odpowiednia klasa lub identyfikator, to wyrażenie jest dość trywialne. W przeciwnym razie, weź elementy, które wydają się odpowiednie i wykonaj ich iteracje, aby znaleźć te, których potrzebujesz.

Jeśli chodzi o kruche, to wszystkie są kruche. Skrobanie ekranu jest z definicji zależne od autora tej strony, który nie zmienia radykalnie układu. Przejdź do rozwiązania, które można odczytać i które można później łatwo zmienić.

1

Nie kruche rozwiązanie do skrobania ekranu? Życzę powodzenia ankieterowi: tylko dlatego, że wyrazy regularne wyrzucają dużo kontekstu, nie oznacza to, że są one mniej kruche: tylko, że są kruche w inny sposób. Kruchość może nie być nawet wadą: jeśli coś zmieni się na stronie źródłowej, często lepiej jest, jeśli twoje rozwiązanie budzi alarm, zamiast próbować kompensować w sprytny (i nieprzewidywalny) sposób. Jak zauważyłeś. Te rzeczy zawsze zależą od twoich założeń: w tym przypadku od tego, co stanowi prawdopodobną zmianę.

Ja raczej lubię HTML agility pack: otrzymujesz tolerancję stron internetowych niezgodnych z XHTML w połączeniu z ekspresyjną mocą XPath.

2

Wypróbuj JTidy lub BeautifulSoup działa dobrze dla mnie. z pewnością // Experssion XPATH jest dość kosztowny na złom.

1

Wyrażenia regularne są naprawdę szybkie i działają z dokumentami innymi niż XML. To są naprawdę dobre punkty przeciwko XQuery. Jednak myślę, że za pomocą jakiś konwerter do XHTML jak schludny i może nieco prostszej XQuery, jak tylko ostatniej części od Ciebie:

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

jest bardzo dobrą alternatywą.

Pozdrawiam,

Rafal Rusin

1

pracować na stronach HTML, najlepiej jest użyć HTMLAgilityPack (iz niektórych kodów LINQ). Jest to świetny sposób na przeanalizowanie wszystkich elementów i/lub wykonanie bezpośredniego wyszukiwania za pomocą XPath. Moim zdaniem jest bardziej dokładny niż RegEx i łatwiejszy do zaprogramowania. Byłem trochę niechętny, aby użyć go wcześniej, ale bardzo łatwo dodać go do swojego projektu i uważam, że jest to czynnik de normatywny dla pracy z html. http://htmlagilitypack.codeplex.com/

Powodzenia!

+0

Dzięki, tak, HTML Agility Pack został zasugerowany w innej odpowiedzi przez Pontus Gagge. Zastanawiam się, co HTML Agility Pack używa wewnętrznie - XPath, wyrażenia regularne lub inne niestandardowe parsowanie DOM lub coś innego. –

+1

Za pomocą programu HtmlAgilityPack można przechodzić przez cały obiekt DOM za pośrednictwem obiektu DocumentNode.ChildNodes. Na przykład: Dla każdego voTag w voMyHTML.DocumentNode.ChildNodes lub można przybliżyć do jednego węzła z voMyHTML.DocumentNode.SelectSingleNode (vsXPath) lub można nawet użyć LINQ: voElements = (Z voTag W voMyHTML.DocumentNode.ChildNodes Gdzie voTag.GetAttributeValue ("Klasa") = "myClass" Wybierz voTag) –