2010-04-11 6 views
7

Creé una pequeña araña web en Python que estoy usando para recopilar URL. No estoy interesado en el contenido. En este momento, guardo todas las URL visitadas en un conjunto en la memoria, porque no quiero que mi spider visite las URL dos veces. Por supuesto, esa es una forma muy limitada de lograr esto.Almacenamiento de URL mientras Spidering

Entonces, ¿cuál es la mejor manera de realizar un seguimiento de mis URL visitadas?

¿Debo usar una base de datos?

  • cuál? MySQL, SQLite, PostgreSQL?
  • ¿cómo debo guardar las URL? ¿Como clave principal al intentar insertar cada URL antes de visitarla?

¿O debería escribir en un archivo?

  • ¿un archivo?
  • archivos múltiples? ¿cómo debería diseñar la estructura de archivos?

Estoy seguro de que hay libros y muchos artículos sobre este tema o sobre temas similares. ¿Me puede dar algunos consejos sobre lo que debería leer?

+0

Este es un problema bastante pesado, depende de cuán fuerte sea su solución :) El mayor problema con el que se encontrará son sitios que colocan cookies y números aleatorios en sus URL, lo que lleva a un espacio de rastreo infinito para obtener atrapado, en algún momento tendrá que comenzar a eliminar duplicados en función del contenido. – Stephen

Respuesta

7

Estos parecen ser los aspectos importantes para mí:

  1. que no pueda cumplir las direcciones URL en la memoria como memoria RAM obtendrá demasiado alto
  2. Es necesario búsquedas rápidas existencia de al menos O (logn)
  3. Usted necesita inserciones rápidas

Hay muchas maneras de hacer esto y depende de lo grande que hará que su base de datos. Creo que una base de datos SQL puede proporcionar un buen modelo para su problema.

Probablemente todo lo que necesita es una base de datos SQLite. Por lo general, las búsquedas de cadena para verificación de existencia es una operación lenta. Para acelerar esto, puede crear un hash CRC de la URL y almacenar tanto el CRC como la URL en su base de datos. Tendría un índice en ese campo CRC.

  • cuando se inserta: insertar el URL y el hash
  • Cuando usted quiere hacer una búsqueda de existencia: Se toma el CRC de la potencialmente nueva URL y comprobar si está en su base de datos ya.

Hay por supuesto una posibilidad de colisión en los hashes de URL, pero si el 100% de expansión no es importante para usted, entonces puede tomar el golpe de no tener una dirección URL en su base de datos cuando se produce una colisión.

También podría disminuir las colisiones de muchas maneras. Por ejemplo, puede aumentar el tamaño de su CRC (CRC8 en lugar de CRC4) y usar un algoritmo de hash de mayor tamaño. O use CRC así como la longitud de la URL.

1

Ya que es probable que usted verá URL similares en tiempos similares (por ejemplo, mientras que spidering un sitio web, verá muchos enlaces a la página principal del sitio web) Le aconsejo que guarde las URL en un diccionario hasta que su memoria se vuelva limitada (solo codifique un número razonable como 10M URL o similar) y luego vacíe el diccionario a CDB database file cuando se convierta en demasiado grande.

De esta manera, la mayoría de sus comprobaciones de URL estarán en la memoria (que es rápida) mientras que las que no están en la memoria todavía requerirán solo 1-2 lecturas del disco para verificar que las haya visitado.

4

Depende de la escala del spidering que vaya a realizar y del tipo de máquina en la que lo esté haciendo. Supongamos que una URL típica es una cadena de 60 bytes más o menos, un conjunto en memoria tomará un poco más de 100 bytes por URL (los conjuntos y dictados en Python nunca pueden crecer más del 60% de su capacidad, por razones de velocidad). Si tiene un equipo de 64 bits (y una distribución de Python) con aproximadamente 16 GB de RAM disponibles, seguramente podría dedicar más de 10 GB al conjunto crucial en cuestión, lo que le permite arañar fácilmente alrededor de 100 millones de URL más o menos; pero en el otro extremo, si tienes una máquina de 32 bits con 3 GB de RAM, claramente no puedes dedicar mucho más que un GB al conjunto crucial, lo que te limita a aproximadamente 10 millones de URL. Sqlite ayudaría en el mismo rango de tamaño en que una máquina de 32 bits no podría hacerlo, pero una de generosas capacidades de 64 bits podría, digamos, 100 o 200 millones de URL.

Además de eso, recomiendo PostgreSQL, que también tiene la ventaja de poder ejecutarse en una máquina diferente (en una LAN rápida) básicamente sin problemas, lo que le permite dedicar su máquina principal a spidering. Supongo que MySQL & c estaría bien para eso también, pero me encanta el cumplimiento estándar y robustez de PostgreSQL ;-). Esto permitiría, digamos, unos miles de millones de URLs sin problemas (solo un disco rápido, o mejor una disposición de RAID, y tanta RAM como sea posible para acelerar las cosas, por supuesto).

Tratando de ahorrar memoria/almacenamiento mediante el uso de un hash de longitud fija en lugar de URLs que pueden ser bastante largo es bien si estás bien con un falso positivo ocasional que le impedirá arrastrándose lo que en realidad es un nuevo URL. Tales "colisiones" no necesitan ser del todo probables: incluso si solo usas 8 bytes para el hash, solo deberías tener un riesgo sustancial de colisión cuando miras miles de millones de URL (la "heurística de raíz cuadrada" para este problema bien conocido).

Con cadenas de 8 bytes para representar las URL, la arquitectura del conjunto en memoria debería admitir fácilmente mil millones de URL o más en una máquina bien dotada como se describe anteriormente.

Así, más o menos el número de URL quieres araña, y la cantidad de RAM se puede prescindir -?)

9

he escrito un montón de arañas. Para mí, un problema más grande que quedarse sin memoria es el potencial de perder todas las URL que ya has filtrado si el código o la máquina fallan o si decides que debes modificar el código. Si se queda sin memoria RAM, la mayoría de las máquinas y sistemas operativos en estos días estarán en la página, por lo que se ralentizará pero aún funcionará. Tener que reconstruir un conjunto de URL reunidas durante horas y horas de tiempo de ejecución porque ya no está disponible puede ser un duro golpe para la productividad.

Mantener la información en la memoria RAM que NO quiere perder es mala. Obviamente, una base de datos es el camino a seguir en ese punto porque necesita acceso aleatorio rápido para ver si ya ha encontrado una URL.Por supuesto, las búsquedas en memoria son más rápidas, pero la compensación de averiguar CUÁLES URLs para mantener en la memoria agrega sobrecarga. En lugar de intentar escribir código para determinar qué URL necesito/no necesito, lo guardo en la base de datos y me concentro en hacer que mi código sea limpio y fácil de mantener, y que mis consultas SQL y esquemas sean razonables. Haga que su campo URL sea un índice único y el DBM podrá encontrarlos en un instante mientras evita automáticamente los enlaces redundantes.

Su conexión a Internet y los sitios a los que accede probablemente sean mucho más lentos que su conexión a una base de datos en una máquina en su red interna. Una base de datos SQLite en la misma máquina puede ser la más rápida, aunque el DBM en sí mismo no es tan sofisticado como Postgres, que es mi favorito. Descubrí que poner la base de datos en otra máquina en el mismo interruptor que mi máquina de spidering es extremadamente rápida; Hacer que una máquina maneje el spidering, el análisis sintáctico y luego las lecturas/escrituras de la base de datos es bastante intensiva, de modo que si tiene una vieja caja, ejecute Linux, instale Postgres y vaya a la ciudad. Lanza algo de RAM extra en la caja si necesitas más velocidad. Tener esa caja separada para el uso de la base de datos puede ser muy agradable.

0

Considere Pickling por ahora: almacenamiento estructurado simple.

El kilometraje variará por supuesto porque, como han dicho los otros respondedores, agotarás rápidamente tu RAM.

Cuestiones relacionadas