2012-01-20 16 views
5

Estoy trabajando en un pequeño proyecto para analizar el contenido de algunos sitios que me parecen interesantes; este es un verdadero proyecto de bricolaje que estoy haciendo para mi entretenimiento/iluminación, así que me gustaría codificar la mayor cantidad posible por mi cuenta como sea posible.¿Cómo diseñar un robot de rastreo?

Obviamente, voy a necesitar datos para alimentar mi aplicación, y estaba pensando en escribir un pequeño rastreador que tomaría aproximadamente 20k páginas de html y escribirlas en archivos de texto en mi disco duro. Sin embargo, cuando eché un vistazo a SO y otros sitios, no pude encontrar ninguna información sobre cómo hacer esto. ¿Es factible? Parece que hay opciones de código abierto disponibles (¿webpshinx?), Pero me gustaría escribir esto yo mismo si es posible.

Scheme es el único idioma que conozco bien, pero pensé que usaría este proyecto para aprender algo de Java, así que me interesaría si hay alguna biblioteca de java o de raqueta que sería útil para esto. .

Así que supongo que para resumir mi pregunta, ¿cuáles son algunos buenos recursos para comenzar con esto? ¿Cómo puedo hacer que mi rastreador solicite información de otros servidores? ¿Tendré que escribir un analizador simple para esto, o es innecesario dado que quiero tomar todo el archivo html y guardarlo como txt?

+0

no necesita un programa de análisis si no se va a analizar, pero el análisis haría sacando enlaces significativamente más fácil. No estoy seguro de dónde tienes problemas; hay muchos ejemplos disponibles, ¿qué has conseguido hasta ahora? –

+0

¿Tiene la intención de hacer que todos los enchufes funcionen y hable HTTP sin formato a los servidores? ¿O está satisfecho con el uso de herramientas de nivel superior para solicitar URL específicas? (¿Estás más interesado en el lado de la creación de redes o en el lado de análisis de HTML?) – sarnold

+0

Dave, ¿podrías señalar un ejemplo? Eso sería de gran ayuda. Sarnold, nunca he hecho ninguna programación web, solo algunas cosas con el servidor web/módulo insta en racket, que toma una solicitud y produce una respuesta. Así que no estoy seguro de cómo escribir un programa que envíe una respuesta. –

Respuesta

0

Sugiero buscar en el rastreador web de código abierto para java conocido como crawler4j.

Es muy simple de usar y proporciona muy buenos recursos y opciones para su rastreo.

5

Esto es completamente factible, y definitivamente puede hacerlo con Racket. Es posible que desee echar un vistazo a las bibliotecas PLaneT; En particular, HtmlPrag de Neil Van Dyke:

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

.. es probablemente el lugar para comenzar. Debería poder extraer el contenido de una página web en un formato analizado en una o dos líneas de código.

Deseo saber si tiene alguna pregunta al respecto.

+0

Y luego use sxpath (implementación de XPath) para extraer las piezas; vea el paquete SXML2 mantenido por el autor de esta respuesta: http://planet.racket-lang.org/display.ss?package=sxml2.plt&owner=clements –

+0

Gracias por apuntarme hacia esto, definitivamente voy a verificar ellos afuera. –

0

Si conoce el esquema, y ​​desea ingresar a Java, ¿por qué no comienza con Clojure?

Puede aprovechar su conocimiento de lisp y aprovechar las bibliotecas * de análisis de html java para obtener algo que funcione. Luego, si quiere comenzar a transitar partes de él a Java para aprender un poco, puede escribir bits de funcionalidad en Java y conectarlos al código de Clojure.

¡Buena suerte!

* He visto varias preguntas AS sobre esto.

+0

Mi preocupación con esta idea es que la sintaxis de clojure es lo suficientemente diferente del esquema que terminaría consultando la documentación de clojure tanto como java, y aprendiendo dos idiomas a la vez. ¿Estoy sobre soplando las diferencias aquí? –

+0

Es un ceceo, hay algunas formas que probablemente no están en el esquema, y ​​una vez que tenga la esencia de las mismas, simplemente estaría haciendo referencia a qué funciones hacen qué. http://clojuredocs.org (la referencia rápida) es realmente bueno para eso. Creo que lo recogerías muy rápido. También creo que podría ser una buena habilidad comercializable. – Bill

0

Si yo fuera tú, no escribiría un rastreador: utilizaría una de las muchas herramientas gratuitas que descargan sitios web localmente para la navegación sin conexión (por ejemplo, http://www.httrack.com/) para hacer el spidering. Es posible que necesite ajustar las opciones para desactivar la descarga de imágenes, etc., pero esas herramientas serán mucho más sólidas y configurables que cualquier otra cosa que escriba usted mismo.

Una vez hecho esto, tendrá una gran cantidad de archivos HTML localmente que puede alimentar a su aplicación.

He realizado muchos análisis textuales de archivos HTML; como un chico Java, mi biblioteca de elección para destilar HTML en texto (una vez más, no es algo que quieras rodar) es el excelente analizador de Jericho: http://jericho.htmlparser.net/docs/index.html

EDIT: releyendo tu pregunta, parece que estás configurar para escribir su propio rastreador; de ser así, recomendaría Commons HttpClient para realizar la descarga, y aún así Jericho sacará los enlaces y los procesará en nuevas solicitudes.

1

Habiendo hecho esto yo mismo en Racket, esto es lo que yo sugeriría.

de inicio con un enfoque de "herramientas de Unix":

  • Uso curl para hacer el trabajo de descarga de cada página (se puede ejecutarlo desde la raqueta usando system) y almacenar el resultado en un archivo temporal.
  • Use Racket para extraer los URI de las etiquetas <a>.
    • Puede "hacer trampa" y hacer una búsqueda de cadenas de expresiones regulares.
    • O hazlo "de la manera correcta" con un verdadero analizador de HTML, como explica la gran respuesta de John Clements.
    • Considera tal vez haciendo el truco primero, luego volviendo más tarde para hacerlo de la manera correcta.

En este punto se podía parar, o bien, se podía volver atrás y vuelva a colocar curl con su propio código para hacer las descargas. Para esto puede usar el módulo net/url de Racket.

Por eso sugiero tratando curl, en primer lugar, es que le ayuda a hacer algo más complicado de lo que parece:

  • ¿Quieres seguir 30x redirecciones?
  • ¿Desea aceptar/almacenar/proporcionar cookies (el sitio puede comportarse de otra manera)?
  • ¿Desea utilizar HTTP keep-alive?
  • Y así sucesivamente.

Usando curl por ejemplo, así:

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

representa es mucho de código que de otro modo debería escribir desde cero en la raqueta. Para hacer todas las cosas que esas banderas de línea de comando curl están haciendo por usted.

En resumen: comience con el caso más simple de usar herramientas existentes. Usa Racket casi como un script de shell. Si eso es lo suficientemente bueno para ti, detente. De lo contrario, sustituya las herramientas una por una con su código personalizado.

0

Lo hice en Perl hace años (mucho más fácil, incluso sin el módulo webcrawler).

Le sugiero que lea la documentación de wget y utilice la herramienta como fuente de inspiración. Wget es la netcat de redcrawling; su conjunto de características te inspirará.

Su programa debe aceptar una lista de URL para comenzar y agregarlas a una lista de URL para probar. Luego, debe decidir si desea recopilar cada url o solo agregar aquellas de los dominios (y subdominios?) Provistos en la lista inicial.

le hice a un punto de partida bastante robusto en el Esquema:

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