Scrapy爬虫抓取的URL与文章标题无法写入CSV文件求助
Scrapy爬虫CSV无数据问题修复
核心问题分析
你的代码里closed方法的实现完全错误:
- 调用
self.get_title_politics_section(None)毫无意义,这个方法需要接收Scrapy的响应对象,传None不仅会报错,也无法获取之前爬取到的所有Item。 - Scrapy不会自动把爬取的Item存储到爬虫实例中,你需要主动收集或者用官方推荐的方式输出文件。
另外原代码还有两个小问题:
- CSS选择器里的
body>div是HTML转义字符,应该改成body > div - 判断
link_to_add in article_links逻辑错误,article_links是相对路径列表,link_to_add是绝对路径,永远不会匹配,会导致重复添加链接,应该改成判断是否在article_links_cleaned中
方案一:使用Scrapy内置Feed输出(推荐)
Scrapy自带Feed Exporter,能自动处理Item的输出,无需手动写CSV写入逻辑,代码更简洁可靠:
import scrapy from scrapy.crawler import CrawlerProcess import re class News_Spider(scrapy.Spider): name="news_spider" def start_requests(self): url="https://www.irishtimes.com/politics/" yield scrapy.Request(url=url,callback=self.parse_front) def parse_front(self,response): # 解析爱尔兰时报政治版块页面 date_reg_exp = re.compile('[-/]politics[-/]\d{4}[-/]\d{2}[-/]\d{2}') article_links = response.css('body > div a::attr(href)').extract() article_links_cleaned=[] print(article_links) for link in article_links: matches_list=date_reg_exp.findall(link) if len(matches_list)>0: link_to_add="https://www.irishtimes.com"+link # 修正重复判断逻辑 if link_to_add not in article_links_cleaned: article_links_cleaned.append(link_to_add) for link_to_follow in article_links_cleaned: yield response.follow(url=link_to_follow,callback=self.get_title_politics_section) def get_title_politics_section(self,response): title = response.css("h1.article__heading::text").get() # 处理标题可能为空的情况 yield {"url": response.url, "title": title or "无标题"} # 配置Feed输出CSV,替代手动closed方法 process=CrawlerProcess(settings={ "FEEDS": { "articles.csv": { "format": "csv", "fields": ["url", "title"], "encoding": "utf-8", "overwrite": True, }, }, }) process.crawl(News_Spider) process.start()
方案二:手动收集Item并写入CSV
如果坚持要手动处理写入,需要在爬虫实例中维护一个列表存储所有Item,在get_title_politics_section中添加Item,最后在closed方法中写入:
import scrapy from scrapy.crawler import CrawlerProcess import csv import re class News_Spider(scrapy.Spider): name="news_spider" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 初始化列表存储Item self.items = [] def start_requests(self): url="https://www.irishtimes.com/politics/" yield scrapy.Request(url=url,callback=self.parse_front) def parse_front(self,response): date_reg_exp = re.compile('[-/]politics[-/]\d{4}[-/]\d{2}[-/]\d{2}') article_links = response.css('body > div a::attr(href)').extract() article_links_cleaned=[] print(article_links) for link in article_links: matches_list=date_reg_exp.findall(link) if len(matches_list)>0: link_to_add="https://www.irishtimes.com"+link if link_to_add not in article_links_cleaned: article_links_cleaned.append(link_to_add) for link_to_follow in article_links_cleaned: yield response.follow(url=link_to_follow,callback=self.get_title_politics_section) def get_title_politics_section(self,response): title = response.css("h1.article__heading::text").get() item = {"url": response.url, "title": title or "无标题"} # 将Item添加到列表 self.items.append(item) yield item def closed(self, reason): # 从self.items中获取所有爬取到的数据写入CSV with open("articles.csv", "w", newline="", encoding="utf-8") as file: fieldnames = ["url", "title"] writer = csv.DictWriter(file, fieldnames=fieldnames) writer.writeheader() for item in self.items: writer.writerow(item) process=CrawlerProcess() process.crawl(News_Spider) process.start()
内容的提问来源于stack exchange,提问作者Ben L
相关产品推荐
相关产品推荐

