Il modo più efficiente (tempo, costo) per raschiare 5 milioni di pagine Web?


8

Ho un elenco di pagine Web che devo scrape, analizzare e quindi archiviare i dati risultanti in un database. Il totale è di circa 5.000.000.

La mia attuale assunzione del modo migliore per affrontare questo è di distribuire ~ 100 istanze EC2, fornire a ciascuna istanza 50.000 pagine da raschiare e quindi lasciarla in esecuzione, quindi una volta completato il processo unire i database. Il presupposto è che occorrerebbe circa un giorno per l'esecuzione (600 ms per caricare, analizzare e salvare ogni pagina).

Qualcuno ha esperienza nel fare un così grande volume di scraping delle pagine in un tempo limitato? Ho già fatto grandi numeri (1,5 m), ma proveniva da una singola macchina e il completamento ha richiesto poco più di una settimana.

Il collo di bottiglia nella mia situazione è il download delle pagine, l'analisi è qualcosa che non richiede più di 2ms, quindi qualcosa che può semplificare il processo di download delle pagine è quello che sto cercando.


Quando si dice un elenco di pagine Web, si tratta solo di una semplice pagina Web o di interi siti come un forum o qualcosa del genere? Inoltre, anche se vai in giro, ci sono regole in atto per i siti che vuoi raschiare (o è solo questa la prima cosa che mette in atto la teoria?)
tombull89

Ho più casi in cui questa risposta è rilevante per me, per il bene della domanda ho dato una figura arbitraria che poteva essere facilmente visualizzata e il tipo di pagina web varia, ma per la domanda si può presumere che sia un forum che viene raschiato se ti piace. Il fatto che il sito consenta o meno lo scraping non è un problema (per la domanda comunque)
sam

Per chiarire il punto sul tipo di pagine Web: ogni pagina Web è indipendente da qualsiasi altra, può essere raschiata in qualsiasi ordine e non può fare affidamento sul fatto che un'altra venga raschiata. Potrebbe essere fatto avanti, indietro, randomizzato, non importa.
sam,

Vedo. Non so come EC2 gestirà i download, ma alcuni utenti SF più esperti potrebbero avere qualche idea. Inoltre, off-topic, ma è questo il citricsquid del MinecraftForums? È un nome abbastanza ... unico ...
tombull89,

mmhmm che sono I.
sam

Risposte:


7

Lavorando sul presupposto che il tempo di download (e quindi l'utilizzo della larghezza di banda) sia il tuo fattore limitante, darei i seguenti suggerimenti:

Innanzitutto, scegli le istanze m1.large. Dei tre "livelli" delle prestazioni I / O (che include la larghezza di banda), le istanze m1.large e m1.xlarge offrono entrambe prestazioni I / O "elevate". Poiché il tuo compito non è associato alla CPU, la scelta meno costosa sarà quella preferibile.

In secondo luogo, la tua istanza sarà in grado di scaricare molto più velocemente di quanto qualsiasi sito possa pubblicare pagine - non scaricare una singola pagina alla volta su una determinata istanza, esegui l'attività contemporaneamente - dovresti essere in grado di fare almeno 20 pagine contemporaneamente (anche se , Immagino che probabilmente puoi fare 50-100 senza difficoltà). (Prendi l'esempio del download da un forum dal tuo commento, ovvero una pagina dinamica che impiegherà del tempo a generare il server, e ci sono altri utenti che utilizzano quella larghezza di banda dei siti, ecc.). Continuare ad aumentare la concorrenza fino a raggiungere i limiti della larghezza di banda dell'istanza. (Naturalmente, non effettuare più richieste simultanee allo stesso sito).

Se stai davvero cercando di massimizzare le prestazioni, potresti prendere in considerazione l'avvio di istanze in zone geograficamente appropriate per ridurre al minimo la latenza (ma ciò richiederebbe la geolocalizzazione di tutti i tuoi URL, il che potrebbe non essere pratico).

Una cosa da notare è che la larghezza di banda dell'istanza è variabile, a volte otterrai prestazioni più elevate e altre volte otterrai prestazioni inferiori. Nelle istanze più piccole, la variazione delle prestazioni è più significativa perché i collegamenti fisici sono condivisi da più server e uno di questi può ridurre la larghezza di banda disponibile. Tra m1.large istanze, all'interno della rete EC2 (stessa zona di disponibilità), dovresti avvicinarti alla velocità teorica di gigabit.

In generale, con AWS, è quasi sempre più efficiente andare con un'istanza più grande rispetto a più istanze più piccole (a meno che non si stia guardando specificamente qualcosa come il failover, ecc. Dove sono necessarie più istanze).

Non so che cosa implica la tua configurazione, ma quando ho già tentato in precedenza (tra 1 e 2 milioni di collegamenti, aggiornati periodicamente), il mio approccio era quello di mantenere un database dei collegamenti aggiungendo nuovi collegamenti quando venivano trovati e processi di fork per raschiare e analizzare le pagine. Un URL verrà recuperato (in modo casuale) e contrassegnato come in corso nel database, lo script scaricherà la pagina e, in caso di successo, contrassegnerà l'URL come scaricato nel database e invierà il contenuto a un altro script che ha analizzato la pagina, nuovi collegamenti sono stati aggiunti al database così come sono stati trovati. Il vantaggio del database qui era la centralizzazione: più script potevano interrogare il database contemporaneamente e (fino a quando le transazioni erano atomiche) si poteva essere certi che ogni pagina sarebbe stata scaricata una sola volta.

Un paio di ulteriori punti di menzione - ci sono limiti (credo 20) sul numero di istanze su richiesta che puoi eseguire contemporaneamente - se prevedi di superare tali limiti, dovrai richiedere AWS per aumentare il tuo account limiti. Sarebbe molto più economico per te eseguire istanze spot e aumentare i tuoi numeri quando il prezzo spot è basso (forse un'istanza su richiesta per mantenere tutto organizzato e le rimanenti istanze spot).

Se il tempo ha una priorità maggiore rispetto al costo, le istanze di calcolo del cluster offrono una larghezza di banda di 10 Gbps e dovrebbero produrre la massima larghezza di banda per il download.

Ricapitolando: prova alcune istanze di grandi dimensioni (anziché molte piccole istanze) ed esegui più download simultanei su ciascuna istanza: aggiungi più istanze se la larghezza di banda è limitata, passa a istanze più grandi se ti trovi associato a CPU / memoria.


4

Abbiamo provato a fare qualcosa di simile, ed ecco i miei 5 centesimi:

  1. Ottieni 2-3 server economici senza limiti, ad esempio non pagare per la larghezza di banda.

  2. Usa Python con asyncore. Asyncore è il vecchio modo di fare le cose, ma abbiamo scoperto che funziona più velocemente di qualsiasi altro metodo. L'aspetto negativo è che la ricerca DNS sta bloccando, cioè non "parallela". Usando asyncore siamo riusciti a raschiare URL di 1M per 40 minuti, usando singoli core XEON 4, 8 GB di RAM. La media del carico sul server era inferiore a 4 (che è eccellente per 4 core).

  3. Se non ti piace l'asyncore, prova gevent. Fa anche DNS non bloccando. Usando gevent, 1M è stato scaricato per circa 50 minuti sullo stesso hardware. Il carico medio sul server è stato enorme.

Nota che abbiamo testato molte librerie Python, come grequests, curl, liburl / liburl2, ma non abbiamo testato Twisted .

  1. Abbiamo testato PHP + curl + diversi processi, ha fatto il lavoro per circa un'ora, ma la media del carico sul server è stata enorme.

"Unmetered" di solito significa "ti chiudiamo quando ne abbiamo voglia", nella mia esperienza.
Ceejayoz,

nella mia esperienza, "Unmetered" significa limitato a circa 100 MBit
Nick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.