sitemapspider requests how example crawl scrapy pipeline multiple-tables

requests - Scrapy: Sugerencia para múltiples devoluciones/artículos a la base de datos



scrapy requests (1)

Conceptualmente, los elementos de Scrapy generalmente se refieren a una sola "cosa" que se raspa (en su caso, una película) y tienen Campos que representan los datos que componen esta "cosa". Así que considere tener:

class MovieItem(scrapy.item.Item): title = Field() director = Field() actors = Field()

Luego, cuando raspe los artículos:

item = MovieItem() title = hxs.select(''//some/long/xpath'').extract() item[''title''] = title actors = hxs.select(''//some/long/xpath'').extract() item[''actors''] = actors return item

Los métodos de análisis de araña siempre deben devolver o ceder objetos scrapy.item.Item o scrapy.http.Request objects.

A partir de ahí, la forma en que procesa los MovieItems depende de usted. Puede tener una interconexión para cada propiedad de MovieItem, pero no es recomendable. Lo que recomendaría en su lugar es tener un solo objeto MySQLPersistancePipeline que tenga métodos para persistir en cada uno de los campos del MovieItem. Entonces algo así como:

class MySQLPersistancePipeline(object): ... def persist_producer(self, item): self.cursor.execute(''insert into producers ...'', item[''producer'']) def persist_actors(self, item): for actor in item[''actors'']: self.cursor.execute(''insert into actors ...'', actor) def process_item(self, item, spider): persist_producer(item) persist_actors(item) return item

Para profundizar en el encabezado de esta pregunta: estoy robando información del sitio web de la película. Actualmente tengo una MySQL datos MySQL poblada con movie titles , movie urls , etc. Ahora voy a tomar esas urls de la base de datos y establecerlas como mis start_urls dentro de una nueva spider . Cada url es un enlace a la página web de [insertar película de la revista], se transmite mucha más información. La información que me interesa es:

  • distribuidor (es decir, Fox)
  • clasificación (es decir, Pg-13)
  • director
  • género (es decir, comedia)
  • actores
  • productor / s

De estos, distribuidor, calificación, director y género tendrán una ''cosa'' asociada con ellos de cada página web de la película (una clasificación, un director, etc.). Habrá múltiples, por supuesto, múltiples actores y, dependiendo, múltiples productores (películas de nombre más grande / la mayoría de las películas). Aquí es donde tengo un problema. Quiero establecer un pipeline'' which puts each piece of info in an appropriate tabla pipeline'' which puts each piece of info in an appropriate within my base de database. So, a table for director, a table for rating, etc. Each table will also have MySQL database. So, a table for director, a table for rating, etc. Each table will also have database. So, a table for director, a table for rating, etc. Each table will also have título de la película ". Puedo decir el problema de esta manera:

Tengo problemas para conciliar cómo construir una pipeline adecuada con una spider adecuada. No estoy seguro de si puedo devolver varias cosas de una araña y enviarlas a diferentes pipelines (crear diferentes elementos para tratar con atributos single , y un elemento diferente para tratar con atributos ''múltiples'') o si usar la misma canalización y de alguna manera especifique qué va a dónde (no estoy seguro si solo puedo devolver una cosa después de raspar). Mostraré mi código y espero que el problema se aclare. * Nota: aún no está completo. Solo intento completar los espacios en blanco con cómo hacer esto.

Araña:

class ActorSpider(BaseSpider): import sys; sys.path.append("/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages") import MySQLdb db = MySQLdb.connect(db = ''testdb'', user=''testuser'', passwd=''test'') dbc = db.cursor() name = ''ActorSpider'' allowed_domains = [''movie website''] #start_urls = #HAVE NOT FILLED THIS IN YET- WILL BE A SELECT STATEMENT, GATHERING ALL URLS def parse(self, response): hxs = HtmlXPathSelector(response) #Expect only singular items (ie. one title, one rating, etc.) single_info = SingleItem() title = hxs.select(''[title tags here]'').extract() distributor = hxs.select(''[distributor tags here]'').extract() rating = hxs.select(''[rating tags here]'').extract() director = hxs.select(''[director tags here]'').extract() genre = hxs.select(''[genre tags here]'').extract() single_items = [] single_info[''title''] = title single_info[''distributor''] = distributor single_info[''rating''] = rating single_info[''director''] = director single_info[''genre''] = genre single_items.append(single_info) #Note: not sure if I want to return this or the single info #return single_items #Multiple items in a field multi_info = MultiItem() actors = hxs.select(''[actor tags here]'').extract() producers = hxs.select(''[producer tags here]'').extract() actor_items= [] for i in range(len(actors)): multi_info[''title''] = title multi_info[''actor''] = actors[i] actor_items.append(multi_info) #return actor_items - can I have multiple returns in my code to specify which pipeline is used, or which table this should be inserted into producer_items = [] for i in range(len(producers)): multi_info[''title''] = title multi_info[''producer''] = producers[i] producer_items.append(multi_info) #return producer_items - same issue - are multiple returns allowed? Should I try to put both the ''single items'' and ''multiple items'' in on big ''items'' list? Can scrapy figure that out or how would I go about specifying?

He comentado en una serie de preguntas que pueden ser poco claras: no estoy seguro de cómo dirigir todo para que termine en la tabla adecuada. Esto puede ser más claro cuando lee la tubería, que es:

class IndMoviePipeline(object): def __init__(self): ''initiate the database connnection'' self.conn = MySQLdb.connect(user=''testuser'', passwd=''test'', db=''testdb'', host=''localhost'', charset=''utf8'', use_unicode=True) self.cursor = self.conn.cursor() def process_item(self, item, spider): try: if ''producer'' in item: self.cursor.execute("""INSERT INTO Producers (title, producer) VALUES (%s, %s)""", (item[''title''], item[''producer''])) elif ''actor'' in item: self.cursor.execute("""INSERT INTO Actors (title, actor) VALUES (%s, %s)""", (item[''title''], item[''actor''])) else: self.cursor.execute("""INSERT INTO Other_Info (title, distributor, rating, director, genre) VALUES (%s, %s, %s, %s, %s)""", (item[''title''], item[''distributor''], item[''rating''], item[''director''], item[''genre''])) #NOTE: I will likely change ''Other_Info'' table to just populating the original table from which the URLS will be pulled self.conn.commit() except MySQLdb.Error, e: print "Error %d: %s" % (e.args[0], e.args[1]) return item

Creo que eso funcionará para dirigir el item a la table apropiada dentro de la base de datos. En base a esto, creo que funcionaría tener una gran lista de items y anexarle todo, así que:

items = [] items.append(single_info) for i in range(len(producers)): multi_info[''title''] = title multi_info[''producer''] = producers[i] items.append(multi_info) for i in range(len(actors)): multi_info[''title''] = title multi_info[''actor''] = actors[i] items.append(multi_info)

Simplemente dejando que la pipeline solucione todo esto con esas declaraciones if . No estoy seguro, sin embargo, si esta es la mejor manera de hacer esto y realmente agradecería sugerencias.