2013-05-28 20 views
7

Voglio raschiare dati da un sito Web che ha campi di testo, pulsanti ecc. E il mio requisito è quello di riempire i campi di testo e inviare il modulo per ottenere i risultati e quindi raschiare i punti dati dalla pagina dei risultati .Scrapy dati Python con Scrapy

Voglio sapere che Scrapy ha questa funzione o Se qualcuno può raccomandare una libreria in Python per eseguire questa operazione?

(a cura)
voglio raschiare i dati dal seguente sito web:
http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentType

La mia esigenza è quella di selezionare i valori da ComboBoxes e colpire il pulsante di ricerca e raschiare i punti di dati dal risultato pagina.

P.S. Sto usando il driver di selenio Firefox per raschiare i dati da qualche altro sito ma quella soluzione non è buona perché il driver di selenio Firefox dipende da EXE di FireFox i.e Firefox deve essere installato prima di eseguire il raschietto.

Il driver di selenio Firefox consuma circa 100 MB di memoria per un'istanza e il mio requisito è di eseguire un sacco di istanze alla volta per rendere rapido il processo di scraping, quindi anche la limitazione della memoria.

Firefox si blocca a volte durante l'esecuzione del raschietto, non so perché. Inoltre ho bisogno di una finestra di scraping inferiore che non è possibile in caso di driver Selenium Firefox.

Il mio obiettivo finale è quello di eseguire i raschietti su Heroku e ho un ambiente Linux laggiù in modo che il selenio driver di Firefox non funzioni su Heroku. Grazie

risposta

15

In sostanza, hai un sacco di strumenti tra cui scegliere:

Questi strumenti hanno scopi diversi, ma possono essere mescolati tra loro a seconda del compito.

Scrapy è uno strumento potente e molto intelligente per la scansione di siti Web, l'estrazione di dati. Ma, quando si tratta di manipolare la pagina: facendo clic sui pulsanti, forme di riempimento - diventa più complicata:

  • a volte, è facile simulare riempimento/invio di moduli facendo sottostante form action direttamente in Scrapy
  • a volte, devi usare altri strumenti per aiutare scrapy - come meccanizza o selenio

Se la tua domanda è più specifica, ti aiuterà a capire che tipo di strumenti dovresti usare o scegliere.

Dai un'occhiata a un esempio di interessante miscela di selenio &. Qui, compito il selenio è quello di fare clic sul pulsante e fornire dati per gli elementi Scrapy:

import time 
from scrapy.item import Item, Field 

from selenium import webdriver 

from scrapy.spider import BaseSpider 


class ElyseAvenueItem(Item): 
    name = Field() 


class ElyseAvenueSpider(BaseSpider): 
    name = "elyse" 
    allowed_domains = ["ehealthinsurance.com"] 
    start_urls = [ 
    'http://www.ehealthinsurance.com/individual-family-health-insurance?action=changeCensus&census.zipCode=48341&census.primary.gender=MALE&census.requestEffectiveDate=06/01/2013&census.primary.month=12&census.primary.day=01&census.primary.year=1971'] 

    def __init__(self): 
     self.driver = webdriver.Firefox() 

    def parse(self, response): 
     self.driver.get(response.url) 
     el = self.driver.find_element_by_xpath("//input[contains(@class,'btn go-btn')]") 
     if el: 
      el.click() 

     time.sleep(10) 

     plans = self.driver.find_elements_by_class_name("plan-info") 
     for plan in plans: 
      item = ElyseAvenueItem() 
      item['name'] = plan.find_element_by_class_name('primary').text 
      yield item 

     self.driver.close() 

UPDATE:

Ecco un esempio su come utilizzare Scrapy nel tuo caso:

from scrapy.http import FormRequest 
from scrapy.item import Item, Field 
from scrapy.selector import HtmlXPathSelector 

from scrapy.spider import BaseSpider 


class AcrisItem(Item): 
    borough = Field() 
    block = Field() 
    doc_type_name = Field() 


class AcrisSpider(BaseSpider): 
    name = "acris" 
    allowed_domains = ["a836-acris.nyc.gov"] 
    start_urls = ['http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentType'] 


    def parse(self, response): 
     hxs = HtmlXPathSelector(response) 
     document_classes = hxs.select('//select[@name="combox_doc_doctype"]/option') 

     form_token = hxs.select('//input[@name="__RequestVerificationToken"]/@value').extract()[0] 
     for document_class in document_classes: 
      if document_class: 
       doc_type = document_class.select('.//@value').extract()[0] 
       doc_type_name = document_class.select('.//text()').extract()[0] 
       formdata = {'__RequestVerificationToken': form_token, 
          'hid_selectdate': '7', 
          'hid_doctype': doc_type, 
          'hid_doctype_name': doc_type_name, 
          'hid_max_rows': '10', 
          'hid_ISIntranet': 'N', 
          'hid_SearchType': 'DOCTYPE', 
          'hid_page': '1', 
          'hid_borough': '0', 
          'hid_borough_name': 'ALL BOROUGHS', 
          'hid_ReqID': '', 
          'hid_sort': '', 
          'hid_datefromm': '', 
          'hid_datefromd': '', 
          'hid_datefromy': '', 
          'hid_datetom': '', 
          'hid_datetod': '', 
          'hid_datetoy': '', } 
       yield FormRequest(url="http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentTypeResult", 
            method="POST", 
            formdata=formdata, 
            callback=self.parse_page, 
            meta={'doc_type_name': doc_type_name}) 

    def parse_page(self, response): 
     hxs = HtmlXPathSelector(response) 

     rows = hxs.select('//form[@name="DATA"]/table/tbody/tr[2]/td/table/tr') 
     for row in rows: 
      item = AcrisItem() 
      borough = row.select('.//td[2]/div/font/text()').extract() 
      block = row.select('.//td[3]/div/font/text()').extract() 

      if borough and block: 
       item['borough'] = borough[0] 
       item['block'] = block[0] 
       item['doc_type_name'] = response.meta['doc_type_name'] 

       yield item 

Salva esso in spider.py ed eseguire tramite scrapy runspider spider.py -o output.json e in output.json si vedrà:

{"doc_type_name": "CONDEMNATION PROCEEDINGS ", "borough": "Borough", "block": "Block"} 
{"doc_type_name": "CERTIFICATE OF REDUCTION ", "borough": "Borough", "block": "Block"} 
{"doc_type_name": "COLLATERAL MORTGAGE ", "borough": "Borough", "block": "Block"} 
{"doc_type_name": "CERTIFIED COPY OF WILL ", "borough": "Borough", "block": "Block"} 
{"doc_type_name": "CONFIRMATORY DEED ", "borough": "Borough", "block": "Block"} 
{"doc_type_name": "CERT NONATTCHMENT FED TAX LIEN ", "borough": "Borough", "block": "Block"} 
... 

Spero che questo aiuti.

+0

Il driver Selenium di Firefox consuma circa 100 MB di memoria per un'istanza e il mio requisito è di eseguire un sacco di istanze alla volta per rendere rapido il processo di scraping, quindi c'è anche un limite di memoria. Firefox si blocca a volte durante l'esecuzione del raschietto, non so perché. Inoltre ho bisogno di una finestra di scraping inferiore che non è possibile in caso di driver Selenium Firefox. Il mio obiettivo finale è quello di eseguire i raschietti su Heroku e ho un ambiente Linux laggiù in modo che il selenio driver di Firefox non funzioni su Heroku. –

+0

Ok, sembra un semplice modulo html che invia una richiesta di post. Basta usare scrapy dovrebbe essere sufficiente. In teoria, dovrebbe essere così: raschiare la pagina principale, ottenere scelte dai campi selezionati, avviare [Richieste] (http://doc.scrapy.org/en/latest/topics/request-response.html # scrapy.http.Request) con un callback: esegue la ricerca per indicizzazione dei dati in elementi rugginosi. Se vuoi, posso fornire un esempio. – alecxe

+0

Sì, per favore, sarà davvero utile per me se puoi dare un piccolo esempio di implementazione. –

2

Personalmente utilizzerei mechanize perché non ho esperienza con scrapy. Tuttavia, una libreria chiamata scrapy appositamente creata per lo screen scraping dovrebbe essere pronta per l'operazione. Vorrei solo provare con entrambi e vedere quale è il lavoro migliore/più facile.

3

Se si vuole semplicemente inviare i dati del modulo ed estrarre dalla pagina risultante, mi piacerebbe andare per:

Il valore aggiunto Scrapy tiene davvero nella sua capacità di seguire collegamenti e scansionare un sito Web, non penso che sia lo strumento giusto per il lavoro se sai esattamente quello che stai cercando.

+1

È solo una mia opinione, ma preferisco decisamente lxml su B.S. Significativamente più veloce, e ha un parser di fallback per BS. Se si tenta di utilizzare lxml su html malformato, è sufficiente catturare l'eccezione e inserirla nel parser di zuppa incorporato in lxml. –