Canalización de Scrapy para exportar archivos csv en el formato correcto

Hice la mejora de acuerdo con la sugerencia de alexce a continuación. Lo que necesito es como la imagen de abajo. Sin embargo, cada fila / línea debe ser una revisión: con fecha, calificación, texto de revisión y enlace.

Necesito dejar que el procesador de artículos procese cada revisión de cada página.
Actualmente, TakeFirst () solo toma la primera revisión de la página. Así que 10 páginas, solo tengo 10 líneas / filas como en la imagen de abajo.

introduzca la descripción de la imagen aquí

El código de la araña está abajo:

import scrapy from amazon.items import AmazonItem class AmazonSpider(scrapy.Spider): name = "amazon" allowed_domains = ['amazon.co.uk'] start_urls = [ 'http://www.amazon.co.uk/product-reviews/B0042EU3A2/'.format(page) for page in xrange(1,114) ] def parse(self, response): for sel in response.xpath('//*[@id="productReviews"]//tr/td[1]'): item = AmazonItem() item['rating'] = sel.xpath('div/div[2]/span[1]/span/@title').extract() item['date'] = sel.xpath('div/div[2]/span[2]/nobr/text()').extract() item['review'] = sel.xpath('div/div[6]/text()').extract() item['link'] = sel.xpath('div/div[7]/div[2]/div/div[1]/span[3]/a/@href').extract() yield item 

Comencé desde cero y la siguiente araña debería correr con

scrapy crawl amazon -t csv -o Amazon.csv --loglevel=INFO

para que la apertura del archivo CSV con una hoja de cálculo se muestre para mí

introduzca la descripción de la imagen aquí

Espero que esto ayude 🙂

 import scrapy class AmazonItem(scrapy.Item): rating = scrapy.Field() date = scrapy.Field() review = scrapy.Field() link = scrapy.Field() class AmazonSpider(scrapy.Spider): name = "amazon" allowed_domains = ['amazon.co.uk'] start_urls = ['http://www.amazon.co.uk/product-reviews/B0042EU3A2/' ] def parse(self, response): for sel in response.xpath('//table[@id="productReviews"]//tr/td/div'): item = AmazonItem() item['rating'] = sel.xpath('./div/span/span/span/text()').extract() item['date'] = sel.xpath('./div/span/nobr/text()').extract() item['review'] = sel.xpath('./div[@class="reviewText"]/text()').extract() item['link'] = sel.xpath('.//a[contains(.,"Permalink")]/@href').extract() yield item xpath_Next_Page = './/table[@id="productReviews"]/following::*//span[@class="paging"]/a[contains(.,"Next")]/@href' if response.xpath(xpath_Next_Page): url_Next_Page = response.xpath(xpath_Next_Page).extract()[0] request = scrapy.Request(url_Next_Page, callback=self.parse) yield request 

Si el uso de -t csv (como lo propone Frank en los comentarios) no funciona para usted por alguna razón, siempre puede usar CsvItemExporter directamente en la canalización personalizada , por ejemplo:

 from scrapy import signals from scrapy.contrib.exporter import CsvItemExporter class AmazonPipeline(object): @classmethod def from_crawler(cls, crawler): pipeline = cls() crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) return pipeline def spider_opened(self, spider): self.file = open('output.csv', 'w+b') self.exporter = CsvItemExporter(self.file) self.exporter.start_exporting() def spider_closed(self, spider): self.exporter.finish_exporting() self.file.close() def process_item(self, item, spider): self.exporter.export_item(item) return item 

que necesita agregar a ITEM_PIPELINES :

 ITEM_PIPELINES = { 'amazon.pipelines.AmazonPipeline': 300 } 

Además, usaría un Cargador de artículos con procesadores de entrada y salida para unir el texto de revisión y reemplazar las nuevas líneas con espacios. Crear una clase de ItemLoader :

 from scrapy.contrib.loader import ItemLoader from scrapy.contrib.loader.processor import TakeFirst, Join, MapCompose class AmazonItemLoader(ItemLoader): default_output_processor = TakeFirst() review_in = MapCompose(lambda x: x.replace("\n", " ")) review_out = Join() 

Luego, úsalo para construir un Item :

 def parse(self, response): for sel in response.xpath('//*[@id="productReviews"]//tr/td[1]'): loader = AmazonItemLoader(item=AmazonItem(), selector=sel) loader.add_xpath('rating', './/div/div[2]/span[1]/span/@title') loader.add_xpath('date', './/div/div[2]/span[2]/nobr/text()') loader.add_xpath('review', './/div/div[6]/text()') loader.add_xpath('link', './/div/div[7]/div[2]/div/div[1]/span[3]/a/@href') yield loader.load_item()