2008-09-19 11 views
60

He pensado en intentar escribir un rastreador simple que pueda rastrear y generar una lista de sus hallazgos para los sitios web y el contenido de nuestra OSFL.¿Cómo escribir un rastreador?

¿Alguien tiene alguna idea sobre cómo hacer esto? ¿Dónde apuntas el rastreador para comenzar? ¿Cómo devuelve sus hallazgos y sigue rastreando? Cómo sabe lo que encuentra, etc., etc.

Respuesta

0

Use wget, haga una succión web recursiva, que arrojará todos los archivos en su disco duro, luego escriba otro script para revisar todos los archivos descargados y analizarlos.

Editar: o tal vez curl en lugar de wget, pero no estoy familiarizado con curl, no sé si lo hace descargas recursivas como wget.

1

Puede hacer una lista de palabras y hacer un hilo por cada palabra buscada en google.
Luego, cada hilo creará un nuevo hilo para cada enlace que encuentre en la página.
Cada hilo debe escribir lo que encuentra en una base de datos. Cuando cada hilo termina de leer la página, termina.
Y ahí tienes una gran base de datos de enlaces en tu base de datos.

4

Los rastreadores son simples en concepto.

Obtiene una página raíz a través de HTTP GET, la analiza para buscar direcciones URL y ponerlas en una cola a menos que ya se hayan analizado (por lo que necesita un registro global de las páginas que ya ha analizado).

Puede usar el encabezado Content-type para descubrir el tipo de contenido y limitar su rastreador a solo analizar los tipos de HTML.

Puede quitar las etiquetas HTML para obtener el texto sin formato, en el que puede hacer análisis de texto (para obtener etiquetas, etc., el contenido de la página). Incluso podrías hacer eso en las etiquetas alt/title para las imágenes si tienes eso avanzado.

Y en segundo plano, puede tener un grupo de hilos comiendo URL de la cola y haciendo lo mismo. Desea limitar el número de subprocesos, por supuesto.

4

Wikipedia tiene un buen artículo sobre web crawlers, que cubre muchos de los algoritmos y consideraciones.

Sin embargo, no me molestaría en escribir mi propio rastreador. Es mucho trabajo, y como solo necesitas un "simple rastreador", estoy pensando que todo lo que realmente necesitas es un off-the-shelf crawler. Hay muchos rastreadores de código abierto y gratuito que probablemente harán todo lo que necesites, con muy poco trabajo de tu parte.

5

Si los sitios de su NPO son relativamente grandes o complejos (tener páginas dinámicas que efectivamente crearán un "agujero negro" como un calendario con un enlace de "día siguiente"), sería mejor usar un rastreador web real, como Heritrix.

Si los sitios suman un número reducido de páginas, puede salirse con la suya simplemente usando curl o wget. Solo recuerda si empiezan a crecer o si comienzas a hacer que tu script sea más complejo para usar solo un rastreador real o al menos ver su origen para ver qué están haciendo y por qué.

Algunos problemas (hay más):

  • Los agujeros negros (como se describe)
  • reintentos (lo que si usted consigue un 500?)
  • redireccionamientos
  • de control de flujo (de lo contrario puede ser una carga para los sitios)
  • aplicación robots.txt
+0

¿Puede usted por favor darnos una idea de tratar los temas que usted menciona? En particular, los agujeros negros? – Shabbyrobe

+0

La salida habitual de los agujeros negros es la programación de un límite configurable para cada dominio o URL que coincida con la expresión regular (es decir, si la URL coincide con esto o el dominio es eso, avance después de 1000 páginas coincidentes recuperadas). El control de flujo se implementa típicamente en páginas por segundo por dominio (generalmente lo hacen esperar más de un segundo para evitar ser una carga). –

142

Se le reinventar la rueda, para estar seguro. Pero aquí está lo esencial:

  • una lista de URL no visitados - semilla esto con una o más páginas de partida
  • una lista de URLs visitadas - por lo que no van en círculos
  • Un conjunto de reglas para las URL que no le interesan, para que no indexe toda la Internet

Colóquelas en el almacenamiento permanente para que pueda detener e iniciar el rastreador sin perder el estado.

algoritmo es:

while(list of unvisited URLs is not empty) { 
    take URL from list 
    remove it from the unvisited list and add it to the visited list 
    fetch content 
    record whatever it is you want to about the content 
    if content is HTML { 
     parse out URLs from links 
     foreach URL { 
      if it matches your rules 
       and it's not already in either the visited or unvisited list 
       add it to the unvisited list 
     } 
    } 
} 
+4

+1 Claro, agradable, respuesta general. – gorsky

+2

Una gran respuesta, pero cuando dices reinventar la rueda, ¿dónde están exactamente los frameworks de rastreo web de código abierto gratuitos? posiblemente para Java pero no he encontrado ninguno para .net. –

+9

http://en.wikipedia.org/wiki/Web_crawler#Open-source_crawlers – slim

28

La parte complicada de un rastreador es si desea modificar la escala para un gran número de sitios web/peticiones. En esta situación, tendrá que hacer frente a algunos problemas como:

  • Imposibilidad de mantener información en una base de datos de todos.

  • No hay suficiente RAM para hacer frente a enormes índice (s)

  • Multithread rendimiento y concurrencia

  • trampas orugas (bucle infinito creado por el cambio de direcciones URL, calendarios, sesiones ids ...) y duplicado contenido.

  • de rastreo de más de un ordenador

  • códigos HTML incorrecto

  • errores HTTP constante desde los servidores

  • Bases de datos sin compresión, cosa que hacen que su necesidad de espacio sobre 8x más grande.

  • Recorra las rutinas y las prioridades.

  • Usa solicitudes con compresión (Deflate/gzip) (bueno para cualquier tipo de rastreador).

Y algunas cosas importantes

  • Respeto robots.txt

  • y un retraso rastreador en cada petición a los servidores web no te asfixian.

+2

¡Gran respuesta! Puede manejar los problemas de RAM utilizando un Filtro Bloom. –

+0

Creo que la respuesta a los primeros 1-3 y 5 es AWS de Amazon. Hashs puede resolver el "contenido duplicado". La biblioteca de Scraping como Beautiful Soup puede manejar 6. 7- verifica tus encabezados http. 8 - usa una base de datos con compresión. etc. – CpILL

7

multiproceso Web de rastreadores

Si desea rastrear sitio web grande de tamaño, entonces debería escribir una oruga multi-hilo. conectando, obteniendo y escribiendo información rastreada en archivos/base de datos: estos son los tres pasos para rastrear, pero si usa un solo subproceso de su CPU y la utilización de la red se vierte.

Un rastreador web con varias hebras necesita dos estructuras de datos: enlaces visitados (esto debe implementarse como hashmap o trai) y enlaces a ser visitado (esto es una cola).

El rastreador web utiliza BFS para recorrer la World Wide Web.

Algoritmo de un rastreador web básica: -

  1. Añadir una o más URL de semillas para linksToBeVisited. El método para agregar una url a linksToBeVisited debe estar sincronizado.
  2. Inserta un elemento de linksToBeVisited y agrégalo a los enlaces visitados. Este método pop para pop url de linksToBeVisited debe estar sincronizado.
  3. Obtenga la página de internet.
  4. Analice el archivo y agregue cualquier enlace hasta ahora no visitado encontrado en la página a linksToBeVisited. Las URL se pueden filtrar si es necesario. El usuario puede proporcionar un conjunto de reglas para filtrar las URL que se analizarán.
  5. La información necesaria que se encuentra en la página se guarda en la base de datos o archivo.
  6. repita los pasos 2 a 5 hasta que la cola esté enlazada a enlacesHacia vacía.

    Aquí es un fragmento de código en la forma de sincronizar los hilos ....

    public void add(String site) { 
        synchronized (this) { 
        if (!linksVisited.contains(site)) { 
        linksToBeVisited.add(site); 
        } 
        } 
    } 
    
    public String next() { 
        if (linksToBeVisited.size() == 0) { 
        return null; 
        } 
         synchronized (this) { 
         // Need to check again if size has changed 
         if (linksToBeVisited.size() > 0) { 
          String s = linksToBeVisited.get(0); 
          linksToBeVisited.remove(0); 
          linksVisited.add(s); 
          return s; 
         } 
        return null; 
        } 
        } 
    

+0

O simplemente podría usar node.js de forma asíncrona. –

+0

¡Aquí estoy hablando de un rastreador web, cómo node.js puede ser de alguna utilidad! – alienCoder

+0

Aquí estamos hablando de rastreadores de gran escala, javascript no se puede utilizar para tal rastreador. La mejor práctica es c o C++, java también funciona bien. – alienCoder

0

lo hice un simple rastreador web usando extensión reactiva en .NET.

https://github.com/Misterhex/WebCrawler

public class Crawler 
    { 
    class ReceivingCrawledUri : ObservableBase<Uri> 
    { 
     public int _numberOfLinksLeft = 0; 

     private ReplaySubject<Uri> _subject = new ReplaySubject<Uri>(); 
     private Uri _rootUri; 
     private IEnumerable<IUriFilter> _filters; 

     public ReceivingCrawledUri(Uri uri) 
      : this(uri, Enumerable.Empty<IUriFilter>().ToArray()) 
     { } 

     public ReceivingCrawledUri(Uri uri, params IUriFilter[] filters) 
     { 
      _filters = filters; 

      CrawlAsync(uri).Start(); 
     } 

     protected override IDisposable SubscribeCore(IObserver<Uri> observer) 
     { 
      return _subject.Subscribe(observer); 
     } 

     private async Task CrawlAsync(Uri uri) 
     { 
      using (HttpClient client = new HttpClient() { Timeout = TimeSpan.FromMinutes(1) }) 
      { 
       IEnumerable<Uri> result = new List<Uri>(); 

       try 
       { 
        string html = await client.GetStringAsync(uri); 
        result = CQ.Create(html)["a"].Select(i => i.Attributes["href"]).SafeSelect(i => new Uri(i)); 
        result = Filter(result, _filters.ToArray()); 

        result.ToList().ForEach(async i => 
        { 
         Interlocked.Increment(ref _numberOfLinksLeft); 
         _subject.OnNext(i); 
         await CrawlAsync(i); 
        }); 
       } 
       catch 
       { } 

       if (Interlocked.Decrement(ref _numberOfLinksLeft) == 0) 
        _subject.OnCompleted(); 
      } 
     } 

     private static List<Uri> Filter(IEnumerable<Uri> uris, params IUriFilter[] filters) 
     { 
      var filtered = uris.ToList(); 
      foreach (var filter in filters.ToList()) 
      { 
       filtered = filter.Filter(filtered); 
      } 
      return filtered; 
     } 
    } 

    public IObservable<Uri> Crawl(Uri uri) 
    { 
     return new ReceivingCrawledUri(uri, new ExcludeRootUriFilter(uri), new ExternalUriFilter(uri), new AlreadyVisitedUriFilter()); 
    } 

    public IObservable<Uri> Crawl(Uri uri, params IUriFilter[] filters) 
    { 
     return new ReceivingCrawledUri(uri, filters); 
    } 
} 

y se puede usar de la siguiente manera:

Crawler crawler = new Crawler(); 
IObservable observable = crawler.Crawl(new Uri("http://www.codinghorror.com/")); 
observable.Subscribe(onNext: Console.WriteLine, 
onCompleted:() => Console.WriteLine("Crawling completed")); 
Cuestiones relacionadas