2011-11-08 12 views
5

Tak więc jestem względnie nowy dla Pythona, i aby się nauczyć, rozpocząłem pisanie programu, który przechodzi do trybu online na wikipedia, znajduje pierwszy link w sekcji przeglądu losowego artykułu, podąża za tym linkiem i kontynuuje, dopóki nie wejdzie w pętlę lub nie znajdzie strony filozofii (jak szczegółowe here), a następnie powtarza ten proces dla nowego losowego artykułu określoną liczbę razy. Następnie chcę zebrać wyniki w jakiejś formie użytecznej struktury danych, tak żebym mógł przekazać dane do R za pomocą Rpy library, dzięki czemu mogę narysować jakiś schemat sieci (R jest całkiem dobry w rysowaniu takich rzeczy) z każdym węzeł na diagramie reprezentującym odwiedzane strony i strzałki, które są ścieżkami zaczerpniętymi z początkowego artykułu na stronę filozofii.Schemat filozofii Wikipedii w python i R

Nie mam problemu ze zwróceniem Pythona, by zwrócił dość rozbudowany html z wiki, ale są pewne problemy, których nie jestem w stanie zrozumieć. Do tej pory wybrałem pierwszy link za pomocą cssselector z biblioteki lxml. Wybiera dla pierwszego ogniwa (w tag), który jest bezpośrednim potomkiem tagu AP, który jest bezpośrednim potomkiem znacznika div class = „mw-content-ltr” tak:

user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)' 
    values = {'name' : 'David Kavanagh', 
     'location' : 'Belfast', 
     'language' : 'Python' } 
    headers = { 'User-Agent' : user_agent } 
    encodes = urllib.urlencode(values) 
    req = urllib2.Request(url, encodes, headers) 
    page = urllib2.urlopen(req) 
    root = parse(page).getroot() 
    return root.cssselect("div.mw-content-ltr>p>a")[0].get('href') 

Ten kod znajduje się w funkcji, za pomocą której znajduję pierwszy link na stronie. Działa to w większości przypadków, ale problem polega na tym, że pierwszy link znajduje się wewnątrz jakiegoś innego znacznika, a nie jest bezpośrednim potomkiem znacznika p, na przykład powiedzmy tagu b lub czegoś, za czym tęsknię. Jak widać z powyższego artykułu wiki, odnośniki kursywą lub nawiasami nie kwalifikują się do gry, co oznacza, że ​​nigdy nie dostaję linku kursywą (dobrze), ale często uzyskuję linki, które znajdują się w nawiasach (złe) i czasami brakuje pierwszego linku na stronie, na przykład pierwszego linku w artykule na krześle, który jest taboretem, ale jest pogrubiony, więc go nie rozumiem. Próbowałem usunąć klauzulę bezpośredniego potomka, ale często otrzymuję linki, które znajdują się "powyżej" sekcji przeglądu, które zwykle znajdują się w bocznym polu, w znaczniku p, w tabeli, w tym samym dziale, co sekcja przeglądu.

więc pierwsza część moje pytanie brzmi:

Jak mogłem używać cssselectors lub jakaś inna funkcja lub biblioteki, aby wybrać pierwszy link w głównej sekcji, która nie znajduje się wewnątrz nawiasów lub kursywą. Myślałem o używaniu wyrażeń regularnych do przejrzenia surowego html, ale wydaje mi się, że to bardzo niefrasobliwe rozwiązanie i pomyślałem, że może być coś ładniejszego, o czym nie pomyślałem.

Obecnie przechowuję wyniki na liście list. Mam więc listę zwaną ścieżkami, w której znajdują się listy zawierające ciągi zawierające tytuł artykułu wiki.

Druga część pytania to: Jak przejść przez tę listę list, aby przedstawić wiele ścieżek konwergentnych? Czy przechowywanie wyników w ten sposób jest dobrym pomysłem? Ponieważ schemat końcowy powinien wyglądać jak drzewo do góry nogami, pomyślałem o zrobieniu jakiejś klasy drzewiastej, ale to wygląda na dużo pracy dla czegoś, co jest koncepcyjnie, dość proste.

Wszelkie pomysły i sugestie będą mile widziane.
Cheers,
Davy

+0

Proszę nie umieszczać dwóch różnych pytań w jednym! – taleinat

+1

Piękna zupa może lepiej parsować HTML (IMO). Obiekt BS ma atrybuty (w sensie obiektowym), które zwracałyby znaczniki zagnieżdżone, a także atrybuty (w sensie znacznika HTML) znacznika. Powinien być zwinny. Dont ** nigdy ** używaj wyrażeń regularnych do parsowania HTML http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – aitchnyu

Odpowiedz

4

będę po prostu odpowiedzieć na drugie pytanie:

Na początek, po prostu zachować odwzorowanie dict jeden Wikipedii Tytuł artykułu do następnego. Ułatwi to szybkie i szybkie sprawdzenie, czy trafiłeś już w artykuł, który już znalazłeś. Zasadniczo jest to po prostu przechowywanie skierowanych wierzchołków wykresu, indeksowanych według ich pochodzenia.

Jeśli dojdziesz do punktu, w którym dyktando Pythona nie jest wystarczająco wydajne (ma znaczny nadmiar pamięci, gdy masz już problem z pamięcią), możesz znaleźć bardziej wydajną strukturę danych wykresów Twoje potrzeby.

EDIT

Ok, będę odpowiedzieć na pierwsze pytanie, jak również ...

do pierwszej części, bardzo polecam pomocą MediaWiki API zamiast się w wersji HTML i analizowania go. Interfejs API umożliwia odpytywanie dla niektórych typów łączy, na przykład po prostu międzygatunkowe lub po prostu międzyjęzykowe. Dodatkowo istnieje Python client libraries dla tego interfejsu API, co powinno uczynić używanie go z kodu Pythona prostym.

Nie analizuj kodu HTML witryny, jeśli zapewnia on wszechstronny i dobrze udokumentowany interfejs API!

+0

Cała angielska wikipedia to mniej niż 4M artykułów. Możesz prototypować wstawianie losowych 50-bajtowych ciągów 4M do skrótu, aby sprawdzić, czy interpreter sobie z tym poradzi. –

1

Dla pierwszej części, to nie jest możliwe, aby znaleźć wsporniki z selektorów CSS, bo o ile html jest zaniepokojony wsporniki są tylko tekst.

Gdybym był tobą, użyłbym selektorów, aby znaleźć wszystkie odpowiednie elementy akapitu, które są ważne dla gry.Następnie zajrzałbym do tekstu elementu akapitu i usunąłem to, co nie jest poprawne - na przykład wszystko między nawiasami, a wszystko pomiędzy pochyłymi znacznikami. Następnie przeszukuję ten przetworzony tekst pod kątem potrzebnych elementów łącza. To jest nieco ładniejsze niż ręczne przetwarzanie całego dokumentu HTML.

Nie jestem pewien, czy śledzę dokładnie to, co robisz dla drugiej części, ale co do reprezentowania wyników tego wyszukiwania jako drzewa: To jest zły pomysł, ponieważ szukasz cykli, które drzewa mogą ". t reprezentują.

Dla struktury danych będę miał listę "węzłów", gdzie węzeł reprezentuje stronę i ma adres URL oraz liczbę wystąpień. Następnie użyłbym algorytmu typu brute force do porównania list węzłów - jeśli te dwie listy mają taki sam węzeł, można je scalić, zwiększając liczbę "wystąpień" dla każdego węzła lustrzanego.

Nie używałbym standardowej "listy" pytona, ponieważ nie może się ona z powrotem zapisać. Może utwórz własną implementację listy powiązanej, aby zawierała węzły.