2015-09-23 22 views
10

Ho uno Spider che cancella i dati che non possono essere salvati in una classe di articolo.Scrapy, Python: più classi di oggetti in una pipeline?

Per illustrazione, ho un elemento del profilo e ogni elemento del profilo potrebbe avere un numero sconosciuto di commenti. Questo è il motivo per cui voglio implementare l'elemento del profilo e l'elemento del commento. So che posso passarli alla mia pipeline semplicemente usando la resa.

  1. Tuttavia, non so come una pipeline con una funzione parse_item possa gestire due classi di articoli diverse?

  2. Oppure è possibile utilizzare diverse funzioni di parse_item?

  3. Oppure devo utilizzare più pipeline?

  4. Oppure è possibile scrivere un iteratore in un campo di elementi di scrapy?


comments_list=[] 
comments=response.xpath(somexpath) 
for x in comments.extract(): 
     comments_list.append(x) 
    ScrapyItem['comments'] =comments_list 

risposta

1

Il modo semplice è quello di avere il parser comprende due sotto-parser, uno per ogni tipo di dati. Il parser principale determina il tipo dall'input e passa la stringa alla subroutine appropriata.

Un secondo approccio consiste nell'includere i parser in sequenza: uno analizza i profili e ignora tutto il resto; il secondo analizza i commenti e ignora tutto il resto (lo stesso principio di cui sopra).

Questo ti porta avanti?

9

Per impostazione predefinita, ogni elemento passa attraverso ogni pipeline.

Ad esempio, se produci uno ProfileItem e uno CommentItem, entrambi passeranno attraverso tutte le condotte. Se si dispone di una configurazione di pipeline per i tipi di tracce voce, quindi il metodo di process_item potrebbe assomigliare:

def process_item(self, item, spider): 
    self.stats.inc_value('typecount/%s' % type(item).__name__) 
    return item 

Quando un ProfileItem passa attraverso, 'typecount/ProfileItem' viene incrementato. Quando un CommentItem passa, 'typecount/CommentItem' viene incrementato.

Si può avere un manico gasdotto un solo tipo di articolo di richiesta, però, se la manipolazione che tipo di elemento è unico, controllando il tipo di elemento prima di procedere:

def process_item(self, item, spider): 
    if not isinstance(item, ProfileItem): 
     return item 
    # Handle your Profile Item here. 

Se tu avessi i due process_item metodi di cui sopra setup in diverse pipeline, l'articolo passerà attraverso entrambi, essendo tracciati e in fase di elaborazione (o ignorati sul secondo).

Inoltre si potrebbe avere una configurazione gasdotto per gestire tutti gli elementi 'connesse':

def process_item(self, item, spider): 
    if isinstance(item, ProfileItem): 
     return self.handleProfile(item, spider) 
    if isinstance(item, CommentItem): 
     return self.handleComment(item, spider) 

def handleComment(item, spider): 
    # Handle Comment here, return item 

def handleProfile(item, spider): 
    # Handle profile here, return item 

Oppure, si potrebbe rendere ancora più complessa e sviluppare un sistema di tipo delegazione che carica le classi e chiama i metodi gestore predefinito, simile a come Scrapy gestisce middleware/pipeline. Dipende da te quanto sia complesso il tuo bisogno e cosa vuoi fare.

5

Definire più Articoli è una cosa complicata quando si esportano i dati se hanno una relazione (Profilo 1 - N Commenti per esempio) e si devono esportarli insieme perché ogni elemento viene elaborato in momenti diversi dalle condotte . Un approccio alternativo per questo scenario è quello di definire un campo personalizzato Scrapy ad esempio:

class CommentItem(scrapy.Item): 
    profile = ProfileField() 

class ProfileField(scrapy.item.Field): 
    # your business here 

Ma data la situazione in cui si deve avere 2 elementi, si raccomanda vivamente di utilizzare una pipeline diverso per ognuno di questi tipi di oggetti e le istanze esportatore anche diversi in modo da ottenere queste informazioni in file diversi (se si sta utilizzando i file):

settings.py

ITEM_PIPELINES = { 
    'pipelines.CommentsPipeline': 1, 
    'pipelines.ProfilePipeline': 1, 
} 

pipelines.py

class CommentsPipeline(object): 
    def process_item(self, item, spider): 
     if isinstance(item, CommentItem): 
      # Your business here 

class ProfilePipeline(object): 
    def process_item(self, item, spider): 
     if isinstance(item, ProfileItem): 
      # Your business here