2012-01-20 6 views
5

Sto lavorando a un piccolo progetto per analizzare il contenuto di alcuni siti che trovo interessanti; questo è un vero progetto fai-da-te che sto facendo per il mio spettacolo/illuminazione, quindi mi piacerebbe codificarne il più possibile da solo.Come progettare un crawler bot?

Ovviamente, avrò bisogno di dati per alimentare la mia applicazione, e stavo pensando che avrei scritto un piccolo crawler che avrebbe richiesto forse 20k pagine di html e le avrebbe scritte in file di testo sul mio disco rigido. Tuttavia, quando ho dato un'occhiata a SO e ad altri siti, non sono riuscito a trovare alcuna informazione su come farlo. È fattibile? Sembra che ci siano opzioni open source disponibili (webpshinx?), Ma mi piacerebbe scriverlo da solo, se possibile.

Lo schema è l'unica lingua che conosco bene, ma ho pensato di utilizzare questo progetto per apprendere qualcosa di Java, quindi sarei interessato se ci sono librerie racket o java che potrebbero essere utili per questo .

Quindi, per riassumere la mia domanda, quali sono alcune buone risorse per iniziare? Come posso convincere il crawler a richiedere informazioni ad altri server? Dovrò scrivere un parser semplice per questo, o è inutile visto che voglio prendere l'intero file html e salvarlo come txt?

+0

non è necessario un parser, se non avete intenzione di analizzare, ma l'analisi avrebbe fatto tirando fuori i collegamenti molto più facile. Non sei sicuro di dove hai problemi; ci sono molti esempi disponibili - cosa hai ottenuto finora? –

+0

Hai intenzione di eseguire tutti i socket manualmente e parlare in modo raw HTTP ai server? O sei contento di utilizzare strumenti di livello superiore per richiedere URL specifici? (Sei più interessato al lato networking o al lato HTML-parsing?) – sarnold

+0

Dave, potresti indicare un esempio? Sarebbe molto utile. Sarnold, non ho mai fatto alcuna programmazione web, solo alcune cose con il modulo web server/insta in rack, che accetta una richiesta e produce una risposta. Quindi non sono nemmeno sicuro di come scrivere un programma che invii una risposta in sé. –

risposta

0

Suggerisco di esaminare il web crawler open source per java noto come crawler4j.

È molto semplice da utilizzare e offre ottime risorse e opzioni per la scansione.

5

Questo è del tutto fattibile e si può sicuramente farlo con Racket. Si consiglia di dare un'occhiata alle librerie PLaneT; In particolare, HtmlPrag di Neil Van Dyke:

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

.. è probabilmente il punto di partenza. Dovresti essere in grado di estrarre il contenuto di una pagina web in un formato analizzato in una o due righe di codice.

Fatemi sapere se avete domande su questo.

+0

E quindi utilizzare sxpath (implementazione di XPath) per estrarre i pezzi; vedere il pacchetto SXML2 gestito dall'autore di questa risposta: http://planet.racket-lang.org/display.ss?package=sxml2.plt&owner=clements –

+0

Grazie per avermi indirizzato verso questi, ho intenzione di controllare fuori. –

0

Se si conosce lo schema e si desidera semplificare in Java, perché non si inizia con Clojure?

È possibile sfruttare la propria conoscenza di Lisp e sfruttare le librerie di analisi java html * disponibili per ottenere risultati operativi. Quindi se vuoi iniziare a passare parti di esso in Java per imparare un po ', puoi scrivere bit di funzionalità in Java e collegarli al codice Clojure.

Buona fortuna!

* Ho visto diverse domande SO su questo.

+0

La mia preoccupazione per questa idea è che la sintassi del clojure è sufficientemente diversa dallo schema che finirei per consultare la documentazione dei clojure tanto quanto java e imparare due lingue contemporaneamente. Sto soffiando le differenze qui? –

+0

Si tratta di una lisc, ci sono alcune forme che probabilmente non sono in schema, e una volta ottenuto il succo di quelle si limiterebbe a fare riferimento a quali funzioni fanno cosa. http://clojuredocs.org (il quick ref) è davvero buono per questo. Penso che lo raccoglieresti molto velocemente. Penso anche che potrebbe essere una buona abilità commerciabile da avere. – Bill

0

Se fossi in te, non scriverei un crawler: utilizzerei uno dei tanti strumenti gratuiti che scaricano localmente siti Web per la navigazione offline (ad esempio http://www.httrack.com/) per eseguire lo spidering. Potrebbe essere necessario modificare le opzioni per disabilitare il download delle immagini, ecc., Ma questi strumenti saranno molto più robusti e configurabili di qualsiasi altra cosa tu stesso abbia scritto.

Una volta fatto, avrete a disposizione un sacco di file HTML localmente da poter alimentare alla vostra applicazione.

Ho eseguito molte analisi testuali di file HTML; come un ragazzo Java, la mia libreria preferita per la distinzione HTML in testo (di nuovo, non è qualcosa che si desidera eseguire) è l'eccellente parser Jericho: http://jericho.htmlparser.net/docs/index.html

MODIFICA: rileggendo la domanda, sembra che tu sia impostato per scrivere il proprio crawler; In tal caso, consiglierei a Commons HttpClient di eseguire il download e ancora Jericho per estrarre i link e elaborarli in nuove richieste.

1

Avendo fatto questo da solo in Racket, ecco cosa suggerirei.

Inizia con un approccio "Unix strumenti":

  • Usa curl per fare il lavoro di scaricare ogni pagina (è possibile eseguire da Racket usando system) e memorizzare l'output in un file temporaneo.
  • Utilizzare Racket per estrarre gli URI dai tag <a>.
    • È possibile "imbrogliare" ed eseguire una ricerca di stringa di espressioni regolari.
    • Oppure, farlo "nel modo giusto" con un vero parser HTML, come spiega la grande risposta di John Clements.
    • Considerare forse prima eseguire il trucco, quindi tornare indietro per farlo nel modo giusto.

A questo punto ci si può fermare, o, si potrebbe tornare indietro e sostituire curl con il proprio codice per fare il download. Per questo è possibile utilizzare il modulo net/url di Racket.

Perché vi suggerisco di provare curl, prima, è che ti aiuta a fare qualcosa di più complicato di quanto possa sembrare:

  • Vuoi seguire 30x reindirizzamenti?
  • Vuoi accettare/memorizzare/fornire cookie (il sito potrebbe comportarsi in modo diverso altrimenti)?
  • Vuoi utilizzare HTTP keep-alive?
  • E così via.

Utilizzando curl per esempio come questo:

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

rappresenta è un sacco di codice che si sarebbe altrimenti bisogno di scrivere da zero in Racket. Per fare tutto ciò che i flag della riga di comando curl stanno facendo per te.

In breve: iniziare con il caso più semplice di utilizzo degli strumenti esistenti. Usa Racket quasi come uno script di shell. Se questo è abbastanza buono per te, basta. Altrimenti, sostituisci gli strumenti uno alla volta con il tuo codice personalizzato.

0

L'ho fatto in Perl anni fa (molto più facile, anche senza il modulo webcrawler).

Ti suggerisco di leggere la documentazione di wget e di utilizzare lo strumento come fonte di ispirazione. Wget è il netcat del webcrawling; il suo set di funzionalità ti ispirerà.

Il programma deve accettare un elenco di URL da cui iniziare e aggiungerli a un elenco di URL da provare. Devi quindi decidere se vuoi raccogliere ogni url o solo aggiungere quelli dai domini (e sottodomini?) Forniti nella lista iniziale.

ti ho fatto un abbastanza robusto punto di partenza nello Schema:

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