Scrapy: проверка значения в файле csv перед добавлением

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

Это мой настраиваемый конвейер - pipelines.py

class CheckCsvPipeline(object):
    def __init__(self):
        csv_path = r"C:\Users\HP\PycharmProjects\ToScrape\book\items.csv"
        self.csvfile = open(csv_path, 'r')
        self.readCsv = csv.reader(self.csvfile, delimiter=',')

    def process_item(self, item, spider):
        for row in self.readCsv:
            if item['title'] in row:
                raise DropItem("This title exists: %s" %item)
            else:
                return item

Вот мой паук:

import scrapy

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

    def parse(self, response):
        books = response.xpath('//h3/a/@href').extract()
        for book in books:
            absolute_url = response.urljoin(book)
            yield scrapy.Request(absolute_url, callback=self.parse_book)

        # process next page
        next_page_url = response.xpath('//a[text()="next"]/@href').extract_first()
        absolute_next_page_url = response.urljoin(next_page_url)
        yield scrapy.Request(absolute_next_page_url)

    def parse_book(self, response):
        title = response.css('h1::text').extract_first()
        price = response.xpath('//*[@class="price_color"]/text()').extract_first()

        yield {'title':title, 'price': price}

Я запускаю паука со следующим кодом, но он по-прежнему добавляет существующие значения.

scrapy crawl books -o items.csv
0
0
321
1

Ответы 1

Я предлагаю вам вести список заголовков в вашем пауке, а затем внутри конвейера проверить, существует ли заголовок уже в этих списках, а затем не yield его.

class CheckCsvPipeline(object):
    def __init__(self):
        pass

    def process_item(self, item, spider):
        if item['title'] in spider.allTitles:

            raise DropItem("This title exists: %s" % item)
        else:

            return item

в своем пауке, сделай это

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

    allTitles = []

    def parse(self, response):
        books = response.xpath('//h3/a/@href').extract()
        for book in books:
            absolute_url = response.urljoin(book)
            yield scrapy.Request(absolute_url, callback=self.parse_book)

        # process next page
        next_page_url = response.xpath('//a[text()="next"]/@href').extract_first()
        absolute_next_page_url = response.urljoin(next_page_url)
        yield scrapy.Request(absolute_next_page_url)

    def parse_book(self, response):
        title = response.css('h1::text').extract_first()

        self.allTitles.extend([ title ])

        price = response.xpath('//*[@class="price_color"]/text()').extract_first()

        yield {'title':title, 'price': price}

Когда я передаю элемент в конвейер, он дает мне «AttributeError: объект« генератор »не имеет атрибутов« полей ». Вместо этого я написал return item, но на этот раз файл csv пуст.

Land Owner 12.04.2018 11:22

@LandOwner Ой, извините, да, вам нужно использовать return вместо yield в конвейере, вы не получили csv? вы запускали скребок вот так scrapy crawl mySpider -o outputFile.csv

Umair Ayub 12.04.2018 11:54

Да, я запускаю паука, как вы показали, но мой файл csv всегда пуст. Я всегда получаю предупреждение о падении This title exists. Я изменил переменную allTitles, но все равно выдает ту же ошибку

Land Owner 12.04.2018 12:09

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