2016-06-06 18 views
7

Voglio utilizzare Scrapy sul sito Web di Dmoz che usano nei loro tutorial, ma invece di limitarsi a leggere i libri nell'URL dei libri (http://www.dmoz.org/Computers/Programming/Languages/Python/Books/) utilizzando le coppie Item/Field, desidero creare un Itemloader che leggerà i valori desiderati (nome, titolo, descrizione).Utilizzo di Scrapy Itemloader in un loop

Questo è il mio file items.py:

from scrapy.item import Item, Field 
from scrapy.contrib.loader import ItemLoader 
from scrapy.contrib.loader.processor import Identity 


class DmozItem(Item): 
    title = Field(
     output_processor=Identity() 
     ) 
    link = Field(
     output_processor=Identity() 
     ) 
    desc = Field(
     output_processor=Identity() 
     ) 


class MainItemLoader(ItemLoader): 
    default_item_class = DmozItem 
    default_output_processor = Identity() 

E il mio file di ragno:

import scrapy 
from scrapy.spiders import Spider 
from scrapy.loader import ItemLoader 
from tutorial.items import MainItemLoader, DmozItem 
from scrapy.selector import Selector 


class DmozSpider(Spider): 
    name = 'dmoz' 
    allowed_domains = ["dmoz.org"] 
    start_urls = [ 
     "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/" 
    ] 

    def parse(self, response): 
     for sel in response.xpath('//div[@class="site-item "]/div[@class="title-and-desc"]'): 
      l = MainItemLoader(response=response) 
      l.add_xpath('title', '/a/div[@class="site-title"]/text()') 
      l.add_xpath('link', '/a/@href') 
      l.add_xpath('desc', '/div[@class="site-descr "]/text()') 
      yield l.load_item() 

Ho provato un certo numero di diverse alternative. Sospetto che il problema principale sia nella parte "response = response" della dichiarazione di itemloader, ma non posso creare teste o code della documentazione scrapy a riguardo. Potresti usare la sintassi del selector = "blah" dove dovrei guardare?

Se lo eseguo, ottengo un elenco di 22 parentesi vuote (il numero corretto di libri). Se cambio la prima barra in ogni linea add_xpath per essere una doppia barra, ottengo 22 liste identiche contenenti TUTTI i dati (non sorprendentemente).

Come posso scrivere questo in modo che itemloader crei un nuovo elenco contenente i campi desiderati per ciascun libro diverso?

Grazie!

risposta

11

È necessario lasciare che il vostro ItemLoader lavoro all'interno di una specifica selettore, non response:

l = MainItemLoader(selector=sel) 
l.add_xpath('title', './a/div[@class="site-title"]/text()') 
l.add_xpath('link', './a/@href') 
l.add_xpath('desc', './div[@class="site-descr "]/text()') 
yield l.load_item() 

Si noti inoltre i punti all'inizio del espressioni XPath.

+1

Grazie mille! Non posso credere che la soluzione sia stata così semplice! Come follow-up, credo che sia così, ma gradirei una conferma: non è possibile utilizzare regex nell'effettiva istruzione add_xpath, ma si tratta piuttosto di un processore di input, corretto? Ancora una volta, grazie, questo è stato un tale gadget. –

+2

@PauloBlack, puoi ancora usare le espressioni regolari - usa l'argomento 're', sample [here] (http://doc.scrapy.org/en/latest/topics/loaders.html#scrapy.loader.ItemLoader. add_xpath). – alecxe