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.
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. –
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
Sì, per favore, sarà davvero utile per me se puoi dare un piccolo esempio di implementazione. –