Scrapy: возвращайте каждый элемент в новую строку csv с помощью загрузчика элементов

Я пытаюсь создать вывод в формате CSV для выбранных элементов, содержащихся в определенном классе (название, ссылка, цена), который анализирует каждый элемент в своем собственном столбце и каждый экземпляр в своей строке с использованием загрузчиков элементов и модуля элементов.

Я могу произвести вывод с помощью автономного паука (без использования модуля элементов), однако я пытаюсь изучить правильный способ детализации элементов в модуле элементов, чтобы в конечном итоге я мог масштабировать проекты, используя надлежащие состав. (Я детализирую этот код как 'Код паука вывода рабочей строки' ниже)

Я также попытался включить решения, определенные или обсужденные в связанных сообщениях; особенно:

Запись загрузчика элементов по элементам в XML или CSV с помощью Scrapy отправлено Сэм

Scrapy возвращает несколько предметов отправлено Зана Даниэль

используя цикл for, как он отмечает в нижней части раздела комментариев. Однако я могу заставить scrapy принять цикл for, это просто не приводит к каким-либо изменениям, то есть элементы по-прежнему сгруппированы в отдельных полях, а не выводятся в независимые строки.

Ниже приведена подробная информация о коде, содержащемся в двух попытках проекта - 'Код паука вывода рабочей строки', который не включает модуль элементов и загрузчик элементов, и 'Код паука вывода нерабочей строки'-- и соответствующие выходные данные каждой из них.

Код паука вывода рабочей строки: btobasics.py

import scrapy
import urlparse

class BasicSpider(scrapy.Spider):
    name = 'basic'
    allowed_domains = ['http://http://books.toscrape.com/']
    start_urls = ['http://books.toscrape.com//']

    def parse(self, response):
        titles = response.xpath('//*[@class="product_pod"]/h3//text()').extract()
        links = response.xpath('//*[@class="product_pod"]/h3/a/@href').extract()
        prices = response.xpath('//*[@class="product_pod"]/div[2]/p[1]/text()').extract()

        for item in zip(titles, links, prices):
        # create a dictionary to store the scraped info
            scraped_info = {
                'title': item[0],
                'link': item[1],
                'price': item[2],
            }

            # yield or give the scraped info to scrapy
            yield scraped_info

Выполните команду для создания CSV: $ scrapy crawl basic -o output.csv

Вывод рабочей строки БЕЗ СТРУКТУРИРОВАННЫХ ПОГРУЗЧИКОВ ЭЛЕМЕНТОВ

Код паука вывода нерабочей строки: btobasictwo.py

import datetime
import urlparse
import scrapy

from btobasictwo.items import BtobasictwoItem

from scrapy.loader.processors import MapCompose
from scrapy.loader import ItemLoader


class BasicSpider(scrapy.Spider):
    name = 'basic'
    allowed_domains = ['http://http://books.toscrape.com/']
    start_urls = ['http://books.toscrape.com//']

    def parse(self, response):
        # Create the loader using the response
        links = response.xpath('//*[@class="product_pod"]')
        for link in links:
            l = ItemLoader(item=BtobasictwoItem(), response=response)

            # Load fields using XPath expressions
            l.add_xpath('title', '//*[@class="product_pod"]/h3//text()',
                        MapCompose(unicode.strip))
            l.add_xpath('link', '//*[@class="product_pod"]/h3/a/@href',
                        MapCompose(lambda i: urlparse.urljoin(response.url, i)))
            l.add_xpath('price', '//*[@class="product_pod"]/div[2]/p[1]/text()',
                        MapCompose(unicode.strip))
            # Log fields
            l.add_value('url', response.url)
            l.add_value('date', datetime.datetime.now())

            return l.load_item()

Код элементов вывода нерабочей строки: btobasictwo.items.py

from scrapy.item import Item, Field


class BtobasictwoItem(Item):
    # Primary fields
    title = Field()
    link = Field()
    price = Field()
    # Log fields
    url = Field()
    date = Field()

Выполните команду для создания CSV: $ scrapy crawl basic -o output.csv

Вывод нерабочих строк кода с помощью STRUCTURED ITEM LOADERS

Как видите, при попытке включить модуль элементов, загрузчики элементов и цикл for для структурирования данных он не разделяет экземпляры по строкам, а скорее помещает все экземпляры определенного элемента (заголовок, ссылка, цена) в 3 поля.

Буду очень признателен за любую помощь в этом вопросе и извиняюсь за длинный пост. Я просто хотел задокументировать как можно больше, чтобы любой, кто хочет помочь, мог сам запустить код и / или полностью оценить проблему из моей документации. (пожалуйста, оставьте комментарий с указанием длины сообщения, если вы считаете, что это неуместно).

Спасибо большое

0
0
469
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо указать вашему ItemLoader использовать другой selector:

def parse(self, response):
    # Create the loader using the response
    links = response.xpath('//*[@class="product_pod"]')
    for link in links:
        l = ItemLoader(item=BtobasictwoItem(), selector=link)

        # Load fields using XPath expressions
        l.add_xpath('title', './/h3//text()',
                    MapCompose(unicode.strip))
        l.add_xpath('link', './/h3/a/@href',
                    MapCompose(lambda i: urlparse.urljoin(response.url, i)))
        l.add_xpath('price', './/div[2]/p[1]/text()',
                    MapCompose(unicode.strip))
        # Log fields
        l.add_value('url', response.url)
        l.add_value('date', datetime.datetime.now())

        yield l.load_item()

Я попытался внести изменения в строку 5, как вы предлагаете. Однако это не повлияло на результат. Я также пробовал такие варианты, как: 'l = ItemLoader (item = BtobasictwoItem (), selector = links)' и 'l = ItemLoader (item = BtobasictwoItem (), selector = link, response = response)' Я что-то упустил. Нужно ли мне как-то поправить код?

R.Zane 15.09.2018 20:12

Огромное спасибо. Я смог произвести намеченный результат, заменив код в соответствии с инструкциями с поправкой к «return» в последней строке на «yield». Я попытался отредактировать ваш вклад, но создал собственную ошибку, сославшись на «ответ» вместо «возврат». Еще раз спасибо .... большое!

R.Zane 16.09.2018 00:02

@dldatacowboy Извините, я пропустил эту часть. Не забудьте принять мой ответ :-)

gangabass 16.09.2018 03:01

Другие вопросы по теме