2012-01-20 15 views
5

Pracuję nad małym projektem, aby przeanalizować zawartość niektórych stron, które uważam za interesujące; jest to prawdziwy projekt DIY, który robię dla mojej rozrywki/oświecenia, więc chciałbym napisać jak najwięcej na mój własny, jak to możliwe.Jak zaprojektować robota indeksującego?

Oczywiście będę potrzebować danych do podania mojej aplikacji, i pomyślałem, że napiszę małego robota, który zajmie może 20k stron HTML i zapisze je w plikach tekstowych na moim dysku twardym. Jednak gdy przyjrzałem się SO i innym stronom, nie mogłem znaleźć żadnych informacji, jak to zrobić. Czy to możliwe? Wygląda na to, że są dostępne opcje open-source (webpshinx?), Ale chciałbym napisać to sam, jeśli to możliwe.

Schemat jest jedynym dobrze znanym językiem, ale pomyślałem, że skorzystam z tego projektu, aby nauczyć się trochę Java, więc byłbym zainteresowany, gdyby istniały jakiekolwiek biblioteki rakietowe lub Java, które byłyby pomocne w tym .

Więc myślę podsumować moje pytanie, jakie są dobre zasoby, aby zacząć na ten temat? Jak mogę poprosić mojego robota do zażądania informacji z innych serwerów? Czy będę musiał napisać do tego prosty parser, czy jest to niepotrzebne, biorąc pod uwagę, że chcę wziąć cały plik HTML i zapisać go jako txt?

+0

nie trzeba parser jeśli nie zamierzamy analizować, ale parsowanie stałaby wyciągnięciu linki znacznie łatwiejsze. Nie wiesz, gdzie masz problemy; dostępnych jest wiele przykładów - co do tej pory otrzymałeś? –

+0

Czy zamierzasz samemu wykonać wszystkie gniazda i wypowiadać surowe HTTP na serwerach? Czy jesteś zadowolony z używania narzędzi wyższego poziomu do żądania określonych adresów URL? (Czy jesteś bardziej zainteresowany stroną sieciową lub stroną do analizy HTML?) – sarnold

+0

Dave, czy mógłbyś wskazać przykład? Byłoby to bardzo pomocne. Sarnold, nigdy tak naprawdę nie robiłem programowania sieciowego - tylko niektóre rzeczy z modułem web-server/insta w rakiecie, który pobiera żądanie i wysyła odpowiedź. Nie jestem nawet pewien, jak napisać program, który sam wysyła odpowiedź. –

Odpowiedz

0

Proponuję zaglądnąć do robota sieciowego open source dla java znanego jako crawler4j.

Jest bardzo prosty w obsłudze i zapewnia bardzo dobre zasoby i opcje przeszukiwania.

5

Jest to całkowicie wykonalne i na pewno można to zrobić za pomocą Rakiety. Możesz rzucić okiem na biblioteki PLaneT; W szczególności, Neil Van Dyke za HtmlPrag:

http://planet.racket-lang.org/display.ss?package=htmlprag.plt&owner=neil

.. to prawdopodobnie miejsce, aby rozpocząć. Powinieneś być w stanie pobrać zawartość strony internetowej do przeanalizowanego formatu w jednym lub dwóch wierszach kodu.

Daj mi znać, jeśli masz jakieś pytania na ten temat.

+0

A następnie użyj sxpath (implementacja XPath), aby wyodrębnić części; zobacz pakiet SXML2 napisany przez autora tej odpowiedzi: http://planet.racket-lang.org/display.ss?package=sxml2.plt&owner=clements –

+0

Dzięki za skierowanie mnie w te stronę, zdecydowanie zamierzam sprawdzić je. –

0

Jeśli znasz schemat i chcesz przejść do Javy, dlaczego nie zaczniesz od Clojure?

Możesz wykorzystać swoją wiedzę na temat seplenień i skorzystać z bibliotek parsujących HTML java *, aby uzyskać coś działającego. Następnie, jeśli chcesz rozpocząć przenoszenie części do Javy, aby nauczyć się nieco, możesz napisać bity funkcji w Javie i podłączyć je do kodu Clojure.

Powodzenia!

* Widziałem kilka pytań SO na ten temat.

+0

Moja troska o ten pomysł jest taka, że ​​składnia clojure jest wystarczająco odmienna od schematu, że skończyłbym konsultować dokumentację clojure tak samo, jak java i uczył się dwóch języków jednocześnie. Czyżbym nie rozwiał tutaj różnic? –

+0

To jest seplenienie, jest kilka formularzy, które prawdopodobnie nie są w schemacie, a gdy już znajdziesz ich w sednie, po prostu odniosą się do tego, które funkcje spełniają. http://clojuredocs.org (szybki ref) jest naprawdę dobry. Myślę, że odbierzesz to bardzo szybko. Uważam też, że może to być dobra umiejętność rynkowa. – Bill

0

Gdybym był tobą, nie napisałbym robota - korzystałbym z jednego z wielu darmowych narzędzi, które pobierają strony internetowe lokalnie do przeglądania w trybie offline (na przykład http://www.httrack.com/), aby zrobić spidering. Może być konieczne dostosowanie opcji, aby wyłączyć pobieranie obrazów, itp., Ale narzędzia te będą znacznie bardziej niezawodne i konfigurowalne niż cokolwiek, co sam napiszesz.

Gdy to zrobisz, będziesz mieć całą masę plików HTML lokalnie, które możesz podać do swojej aplikacji.

Zrobiłem wiele analizy tekstowej plików HTML; jako Java, moja ulubiona biblioteka do destylowania HTML-a do tekstu (znowu, nie jest to coś, co chcesz samemu przetasować) to doskonały parser Jericho: http://jericho.htmlparser.net/docs/index.html

EDYCJA: ponowne przeczytanie twojego pytania, wygląda na to, że jesteś ustaw na pisanie własnego robota; jeśli tak, polecam Commons HttpClient, aby pobrać i nadal Jericho wyciągnąć linki i przetworzyć je na nowe zapytania.

1

Po wykonaniu tego samodzielnie w Racket, oto co chciałbym zasugerować.

start z podejściem „Unix” Narzędzia:

  • Zastosowanie curl zrobić pracę pobierając każdą stronę (można go wykonać z użyciem system Racket) i przechowywania danych wyjściowych w pliku tymczasowym.
  • Użyj rakiety, aby wyodrębnić identyfikatory URI ze znaczników <a>.
    • Możesz "oszukiwać" i wykonywać wyszukiwanie w łańcuchu wyrażeń regularnych.
    • Albo, zrób to "właściwą drogę" z prawdziwym parserem HTML, jak wyjaśnia świetna odpowiedź Johna Clementsa.
    • Zastanów się, może najpierw zrobić oszustwo, a następnie wrócić później, aby zrobić to we właściwy sposób.

W tym momencie można zatrzymać lub, można wrócić i zastąpić curl z własnego kodu wykonać pobieranie. Do tego możesz użyć modułu Racket o numerze net/url.

Dlaczego Proponuję próbuje curl, po pierwsze, jest to, że pozwala zrobić coś bardziej skomplikowanego, niż mogłoby się wydawać:

  • chcesz śledzić 30x przekierowań?
  • Czy chcesz akceptować/przechowywać/udostępniać pliki cookie (strona może zachowywać się inaczej w przeciwnym razie)?
  • Czy chcesz używać protokołu HTTP do podtrzymywania aktywności?
  • I tak dalej.

Korzystanie curl na przykład tak:

(define curl-core-options 
    (string-append 
    "--silent " 
    "--show-error " 
    "--location " 
    "--connect-timeout 10 " 
    "--max-time 30 " 
    "--cookie-jar " (path->string (build-path 'same "tmp" "cookies")) " " 
    "--keepalive-time 60 " 
    "--user-agent 'my crawler' " 
    "--globoff ")) 

(define (curl/head url out-file) 
    (system (format "curl ~a --head --output ~a --url \"~a\"" 
        curl-core-options 
        (path->string out-file) 
        url))) 

(define (curl/get url out-file) 
    (system (format "curl ~a --output ~a --url \"~a\"" 
        curl-core-options 
        (path->string out-file) 
        url))) 

oznacza to dużo kodu, który normalnie trzeba napisać od podstaw w Racket. Aby zrobić wszystko, co robią te flagi linii komend curl.

W skrócie: Zacznij od najprostszego przypadku użycia istniejących narzędzi. Używaj Rakiet prawie jako skryptu powłoki. Jeśli to ci wystarczy, przestań. W przeciwnym razie zamień narzędzia, jeden po drugim, za pomocą własnego kodu.

0

Zrobiłem to w Perlu lata temu (o wiele łatwiej, nawet bez modułu webcrawler).

Proponuję przeczytać dokumentację wget i użyć narzędzia do inspiracji. Wget jest netcat webcrawling; jego zestaw funkcji zainspiruje Cię.

Twój program powinien zaakceptować listę adresów URL na początek i dodać je do listy adresów URL, które można wypróbować. Następnie musisz zdecydować, czy chcesz zebrać każdy adres URL, czy tylko dodać te z domen (i subdomen?) Podane na początkowej liście.

I sprawiło, że dość silny punkt wyjścia na schemacie:

(define (crawl . urls) 
    ;; I would use regular expressions for this unless you have a special module for this 
    ;; Hint: URLs tend to hide in comments. referal tags, cookies... Not just links. 
    (define (parse url) ...) 
    ;; For this I would convert URL strings to a standard form then string= 
    (define (url= x y) ...) 
    ;; use whatever DNS lookup mecanism your implementation provides 
    (define (get-dom) ...) 
    ;; the rest should work fine on its own unless you need to modify anything 
    (if (null? urls) (error "No URLs!") 
     (let ([doms (map get-dom urls)]) 
     (let crawl ([done '()]) 
      (receive (url urls) (car+cdr urls) 
      (if (or (member url done url=) 
         (not (member (get-dom url) doms url=))) 
       (crawl urls done) 
       (begin (parse url) (display url) (newline) 
        (crawl (cons url done))))))))) 
Powiązane problemy