2013-06-10 10 views
12

Sto raschiando 23770 pagine Web con un raschietto per web piuttosto semplice utilizzando scrapy. Sono abbastanza nuovo di scrapy e persino python, ma sono riuscito a scrivere un ragno che fa il lavoro. È, tuttavia, molto lento (ci vogliono circa 28 ore per eseguire la scansione delle 23770 pagine).Rasaerba per rasatura rapida

Ho guardato la pagina web scrapy e le mailing list e stackoverflow, ma non riesco a trovare raccomandazioni generiche per la scrittura di crawler veloci comprensibili per i principianti. Forse il mio problema non è lo spider in sé, ma il modo in cui lo eseguo. Tutti i suggerimenti sono benvenuti!

Ho elencato il mio codice qui sotto, se necessario.

from scrapy.spider import BaseSpider 
from scrapy.selector import HtmlXPathSelector 
from scrapy.item import Item, Field 
import re 

class Sale(Item): 
    Adresse = Field() 
    Pris = Field() 
    Salgsdato = Field() 
    SalgsType = Field() 
    KvmPris = Field() 
    Rum = Field() 
    Postnummer = Field() 
    Boligtype = Field() 
    Kvm = Field() 
    Bygget = Field() 

class HouseSpider(BaseSpider): 
    name = 'House' 
    allowed_domains = ["http://boliga.dk/"] 
    start_urls = ['http://www.boliga.dk/salg/resultater?so=1&type=Villa&type=Ejerlejlighed&type=R%%C3%%A6kkehus&kom=&amt=&fraPostnr=&tilPostnr=&iPostnr=&gade=&min=&max=&byggetMin=&byggetMax=&minRooms=&maxRooms=&minSize=&maxSize=&minsaledate=1992&maxsaledate=today&kode=&p=%d' %n for n in xrange(1, 23770, 1)] 

    def parse(self, response): 
     hxs = HtmlXPathSelector(response) 
     sites = hxs.select("id('searchresult')/tr") 
     items = []  
     for site in sites: 
      item = Sale() 
      item['Adresse'] = site.select("td[1]/a[1]/text()").extract() 
      item['Pris'] = site.select("td[2]/text()").extract() 
      item['Salgsdato'] = site.select("td[3]/text()").extract() 
      Temp = site.select("td[4]/text()").extract() 
      Temp = Temp[0] 
      m = re.search('\r\n\t\t\t\t\t(.+?)\r\n\t\t\t\t', Temp) 
      if m: 
       found = m.group(1) 
       item['SalgsType'] = found 
      else: 
       item['SalgsType'] = Temp 
      item['KvmPris'] = site.select("td[5]/text()").extract() 
      item['Rum'] = site.select("td[6]/text()").extract() 
      item['Postnummer'] = site.select("td[7]/text()").extract() 
      item['Boligtype'] = site.select("td[8]/text()").extract() 
      item['Kvm'] = site.select("td[9]/text()").extract() 
      item['Bygget'] = site.select("td[10]/text()").extract() 
      items.append(item) 
     return items 

Grazie!

+1

La prima cosa che puoi fare a questo proposito è usare i thread (vedi le informazioni rilevanti nel doc della libreria standard), per eseguire, ad esempio, 5/10 download allo stesso tempo, il che può ovviamente comportare un grande tempo di esecuzione miglioramento. Oltre a questo, non vedo alcun modo semplice per accelerare le cose, come il tuo codice sembra semplice. – michaelmeyer

+0

@doukremt: Grazie! Ho esaminato la documentazione e sembra abbastanza semplice per quello che mi serve. È correttamente inteso che per ogni connessione dovrei chiamare 'thread.start_new_thread (parse)'? O otterrò solo due connessioni ciascuna raschiando tutte le 23770 pagine? – Mace

+0

scrapy è in realtà asincrono, quindi viene scaricato in parallelo (puoi impostare quante richieste simultanee fa). –

risposta

20

Ecco una collezione di cose da provare:

  • versione uso ultima Scrapy (se non si utilizza già)
  • controllo se middleware non standard sono utilizzati
  • cercare di aumentare CONCURRENT_REQUESTS_PER_DOMAIN, CONCURRENT_REQUESTS impostazioni (docs)
  • disattivare la registrazione LOG_ENABLED = False (docs)
  • provare yield zione di un elemento in un ciclo invece di raccogliere elementi nella lista items e restituendo loro
  • uso cache locale DNS (vedi this thread)
  • controllo se questo sito è utilizzando la soglia di download e limita la velocità di download (vedi this thread)
  • registro l'utilizzo della CPU e della memoria durante l'esecuzione del ragno - vedere se ci sono problemi ci
  • provare eseguire lo stesso ragno sotto scrapyd servizio
  • vedere se grequests + lxml si esibirà meglio (chiedere se avete bisogno di aiuto all'implementazione questo sol ution)
  • provare a eseguire Scrapy su pypy, vedere Running Scrapy on PyPy

Speranza che aiuta.

+0

Grazie! I punti sono ordinati dopo il miglioramento della pertinenza/performance? – Mace

+0

Beh, non c'è un ordine speciale qui, ma controllerei i problemi non correlati a scrapy, come prima il limite di download del sito. – alecxe

+0

Come posso verificarlo? Ho esaminato il thread, ma non riesco a vedere dove si menziona come verificare se questo è il caso? – Mace

5

Guardando il tuo codice, direi che gran parte di quel tempo è trascorso in richieste di rete piuttosto che elaborare le risposte. Tutti i suggerimenti che @alecxe fornisce nella sua risposta si applicano, ma suggerirei l'impostazione HTTPCACHE_ENABLED, poiché memorizza nella cache le richieste ed evita di farlo una seconda volta. Sarebbe utile per seguire le scansioni e anche lo sviluppo offline. Vedere ulteriori informazioni nella documentazione: http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#module-scrapy.contrib.downloadermiddleware.httpcache

+0

Buon punto, grazie! – alecxe

+0

Grazie, ci proverò. Ho provato alcuni dei punti indicati da @alecxe. All'inizio lo scraping è molto veloce, ma poi diventa piuttosto lento, e ottengo scarti falliti, perché i graffi durano più di 180 secondi. Senza saperlo, sembra che io stia colpendo troppo la pagina o che riduca la velocità di risposta poiché tutte le richieste provengono dallo stesso IP. Qualche idea su questo? – Mace

+0

@barraponto: l'impostazione di 'HTTPCACHE_ENABLED' uguale a' True' mi ha davvero aiutato !! Ora il mio problema è che ottengo il "500 Internal Server Error" molto. Ho provato a impostare il tempo di ritardo su 5 secondi e 'CONCURRENT_REQUESTS_PER_DOMAIN = 2', ma non aiuta. – Mace

0

Lavoro anche sul web rottamazione, utilizzando ottimizzato C#, e finisce per CPU legato, quindi sono il passaggio a C.

parsing del codice HTML soffia la cache dati della CPU, e abbastanza sicuro che la tua CPU non stia usando SSE 4.2, dato che puoi accedere a questa funzione solo usando C/C++.

Se si esegue il calcolo matematico, si esegue rapidamente il calcolo ma non il limite di memoria.