Я хочу проверить заголовок элемента в файле 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
Я предлагаю вам вести список заголовков в вашем пауке, а затем внутри конвейера проверить, существует ли заголовок уже в этих списках, а затем не 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}
@LandOwner Ой, извините, да, вам нужно использовать return вместо yield в конвейере, вы не получили csv? вы запускали скребок вот так scrapy crawl mySpider -o outputFile.csv
Да, я запускаю паука, как вы показали, но мой файл csv всегда пуст. Я всегда получаю предупреждение о падении This title exists
. Я изменил переменную allTitles, но все равно выдает ту же ошибку
Когда я передаю элемент в конвейер, он дает мне «AttributeError: объект« генератор »не имеет атрибутов« полей ». Вместо этого я написал return item, но на этот раз файл csv пуст.