Scrapy爬虫能提取数据但无法写入.csv文件,求助排查原因
问题分析与解决方案
核心问题
你的代码存在逻辑割裂和无效操作,导致CSV仅写入表头无数据:
- 手动用Selenium处理页面后生成的
response,其数据写入逻辑可能未获取到目标元素; - 后续启动的Scrapy爬虫完全独立于Selenium处理流程,爬取的是原始未处理页面(
start_urls指向的初始站点),自然无法拿到需要的数据; - 冗余的文件操作进一步混淆了数据流向。
具体原因排查
1. 手动写入部分可能未获取到数据
在手动写入CSV的循环前添加打印,确认是否真的抓取到.anime_row元素:
# 手动写入循环前加入 print(f"找到目标元素数量: {len(response.css('.anime_row'))}") for anime in response.css('.anime_row'): title = anime.css('.anime_title a::text').get() views = anime.css('.anime_views::text').get() date = anime.css('.anime_date::text').get() print(f"抓取数据: {title}, {views}, {date}") # 打印单条数据 writer.writerow({'title': title, 'views': views, 'date': date})
如果打印结果为0或空值,说明:
- CSS选择器错误:检查页面源码,确认元素class是否正确(比如是否是
.anime-row而非.anime_row)、嵌套结构是否匹配; - 页面未正确加载:
time.sleep的等待时间不足,或点击按钮后页面跳转/数据异步加载未完成,建议替换为Selenium显式等待:from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待按钮出现并点击 btn = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.btn-primary')) ) btn.click() # 等待目标数据元素加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.anime_row')) )
2. Scrapy爬虫未复用Selenium处理后的页面
你启动的SiteSpider爬取的是start_urls中的原始站点,完全没有用到Selenium处理后的页面,这部分代码属于冗余操作,要么删除,要么修改为复用已处理的response:
# 去掉原有爬虫类,改为直接使用处理后的response写入 # 保留Selenium处理代码和手动写入逻辑,删除SiteSpider和process启动部分
推荐解决方案(统一Scrapy+Selenium流程)
将Selenium集成到Scrapy爬虫中,让爬虫直接使用处理后的页面,同时用Scrapy官方的Feed Exports管理CSV写入,更规范可靠:
from selenium import webdriver import time from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from scrapy.crawler import CrawlerProcess import scrapy from scrapy.http import HtmlResponse class SiteSpider(scrapy.Spider): name = 'site_spider' def start_requests(self): # Selenium处理页面流程 driver = webdriver.Chrome() driver.get("here's the site I'm getting info from") # 滚动查找按钮 scroll_pause_time = 1 screen_height = driver.execute_script("return window.screen.height;") j = 1 while True: driver.execute_script(f"window.scrollTo(0, {screen_height}*{j});") j += 1 time.sleep(scroll_pause_time) if len(driver.find_elements(By.CSS_SELECTOR, '.btn-primary')) > 0: break # 显式等待按钮并点击 btn = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.btn-primary')) ) btn.click() # 等待数据加载 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.anime_row')) ) # 滚动到底部加载全部数据 start_time = time.time() i = 1 while True: driver.execute_script(f"window.scrollTo(0, {screen_height}*{i});") i += 1 time.sleep(scroll_pause_time) if driver.execute_script("return document.body.scrollHeight <= window.pageYOffset + window.innerHeight;") or (time.time() - start_time >= 10): break # 生成Scrapy响应对象 response = HtmlResponse(url=driver.current_url, body=driver.page_source, encoding='utf-8') driver.quit() yield response def parse(self, response): # 遍历抓取数据并返回item for anime in response.css('.anime_row'): yield { 'title': anime.css('.anime_title a::text').get(), 'views': anime.css('.anime_views::text').get(), 'date': anime.css('.anime_date::text').get() } # 配置Scrapy导出CSV process = CrawlerProcess(settings={ 'FEEDS': { 'site_org.csv': { 'format': 'csv', 'fields': ['title', 'views', 'date'], 'overwrite': True, 'encoding': 'utf-8' } } }) process.crawl(SiteSpider) process.start() print('Results saved to site_org.csv')
内容的提问来源于stack exchange,提问作者Aintripin
相关产品推荐
相关产品推荐

