Почему мой паук Scrapy только счищает некоторые из моих данных? - PullRequest
0 голосов
/ 03 июня 2018

Я пытаюсь использовать Scrapy для очистки данных IMDb (информация об эпизодах и список актеров) для каждого эпизода Закон и порядок: SVU .После запуска приведенного ниже кода я экспортирую его в CSV через командную строку с помощью «scrapy crawl svu -o svu.csv».

Приведенный ниже код успешно извлекает информацию об эпизодах, но CSV не содержит приведениесписок.Как исправить код для извлечения и экспорта информации об эпизодах и списке актеров?

Мои мысли и попытки:

  • Я считаю, что список актеров извлечен, потому что онотображается в терминале при запуске паука, поэтому это может быть проблема экспорта.
  • Если я закомментирую свой первый оператор Yield (информация об эпизоде), список приведения успешно экспортируется.Это заставляет меня думать, что это не просто проблема экспорта.

Спасибо за помощь!

import scrapy

class SvuSpider(scrapy.Spider):
    name = "svu"
    start_urls = [
        'https://www.imdb.com/title/tt0629700/?ref_=ttep_ep1'
    ]

    def parse(self, response):
        # Gather episode information
        yield {
            'season': response.xpath("//div[@class='bp_heading']/text()")[0].extract(),
            'episode': response.xpath("//div[@class='bp_heading']/text()")[1].extract(),
            'episode_name': response.xpath("//h1[@itemprop='name']/text()").extract_first().strip(),
            'date_published': response.xpath("//div[@class='subtext']/a/meta[@itemprop='datePublished']/@content").extract(),
            'rating_value': response.xpath("//span[@itemprop='ratingValue']/text()").extract(),
            'rating_count': response.xpath("//span[@itemprop='ratingCount']/text()").extract()
        }

        # Follow link to full cast list
        for a in response.xpath("//div[@class='see-more']/a"):
            yield response.follow(a, callback=self.parse_cast)

        # Follow link to next episode
        for a in response.xpath("//a[@class='bp_item np_next']"):
            yield response.follow(a, callback=self.parse)

    def parse_cast(self,response):
        # Gather cast list data
        for actor in response.xpath("//table[@class='cast_list']"):
            yield {
                'actor': response.xpath("//td[@itemprop='actor']/a/span[@itemprop='name']/text()").extract(),
                'character': response.xpath("//td[@class='character']/a/text()").extract()
            }

1 Ответ

0 голосов
/ 03 июня 2018

Я добавил изменения в ваш код.Кроме того, я покажу вам, как использовать Предметы и Конвейеры.

spiders / svu.py

# -*- coding: utf-8 -*-
import scrapy
from ..items import EpisodeItem, CastItem

class SvuSpider(scrapy.Spider):
    name = "svu"
    start_urls = [
        'https://www.imdb.com/title/tt0629700/?ref_=ttep_ep1'
    ]

    def parse(self, response):
        # Gather episode information
        item = EpisodeItem(
            season=response.xpath("//div[@class='bp_heading']/text()")[0].extract(),
            episode=response.xpath("//div[@class='bp_heading']/text()")[1].extract(),
            episode_name=response.xpath("//h1[@itemprop='name']/text()").extract_first().strip(),
            date_published=response.xpath("//div[@class='subtext']/a/meta[@itemprop='datePublished']/@content").extract(),
            rating_value=response.xpath("//span[@itemprop='ratingValue']/text()").extract(),
            rating_count=response.xpath("//span[@itemprop='ratingCount']/text()").extract()
        )
        yield item

        # Follow link to full cast list
        for a in response.xpath("//div[@class='see-more']/a"):
            yield response.follow(a, callback=self.parse_cast)

        # Follow link to next episode
        for a in response.xpath("//a[@class='bp_item np_next']"):
            yield response.follow(a, callback=self.parse)

    def parse_cast(self,response):
        # Gather cast list data
        for actor in response.xpath("//table[@class='cast_list']"):
            character = response.xpath("//td[@class='character']/a/text()").extract()
            character.extend(response.xpath("//td[@class='character']/text()").extract())
            character = [c.strip().replace('\n ', '') for c in character if c.strip()]
            item = CastItem(
                actor=response.xpath("//td[@itemprop='actor']/a/span[@itemprop='name']/text()").extract(),
                character=character
            )
            yield item

items.py

from scrapy import Item, Field

    class EpisodeItem(Item):
        season = Field()
        episode = Field()
        episode_name = Field()
        date_published = Field()
        rating_value = Field()
        rating_count = Field()

    class CastItem(Item):
        actor = Field()
        character = Field()

pipelines.py

from scrapy import signals
from scrapy.exporters import CsvItemExporter

from .items import CastItem, EpisodeItem

class IMDBPipeline(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):
        item_names = ['episode', 'cast']
        self.files = self.files = {n: open('%s.csv' % n, 'w+b') for n in item_names}
        self.exporters = {n: CsvItemExporter(f) for n, f in self.files.items()}
        for exporter in self.exporters.values():
            exporter.start_exporting()

    def spider_closed(self, spider):
        for exporter in self.exporters.values():
            exporter.finish_exporting()

        for file in self.files.values():
            file.close()

    def process_item(self, item, spider):
        if isinstance(item, EpisodeItem):
            self.exporters['episode'].export_item(item)

        if isinstance(item, CastItem):
            self.exporters['cast'].export_item(item)

        return item

Добавить в файл настроек:

ITEM_PIPELINES = {
    'PROJECT_NAME.pipelines.IMDBPipeline': 300,
}

Будьте осторожны.Вам нужно заменить PROJECT_NAME на вашу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...