Scrapy爬取数据生成DataFrame时提示df未定义如何解决
Scrapy爬取结果转DataFrame报错修复方案
代码核心错误点
name 'df' is not defined只是表层报错,代码存在多层逻辑和语法问题:
- 变量作用域错误:
items列表定义在文章遍历的for循环内部,若页面CSS选择器未匹配到对应元素(比如原代码设置的起始页是网站首页,根本没有div.list_article_detail节点),循环不会执行,items变量根本不会被创建,后续调用items生成df时就会触发未定义错误;就算循环执行,每次循环都会把items重置为空列表,之前存储的数据会被直接覆盖。 - 执行逻辑错位:Scrapy的
parse方法是异步回调函数,每个分页请求返回后都会独立执行一次parse,把生成DataFrame的逻辑写在parse内部,会导致每加载一个分页就尝试生成一次df,根本无法聚合全量爬取数据。 - 爬取逻辑漏洞:
- 文章遍历循环内提取到
item后没有做追加操作,循环结束后只会保留最后一篇文章的信息,前面的内容全部丢失 - 文章链接硬编码为栏目固定地址,没有提取每篇文章对应的真实跳转url
- 分页追加数据的逻辑和文章提取逻辑完全脱节,追加的永远是最后一次循环生成的单条item,完全无法收集全部分页数据
- 文章遍历循环内提取到
- 依赖缺失:代码使用pandas生成DataFrame,但没有提前导入pandas库。
标准修复方案
Scrapy官方推荐使用Item Pipeline做爬取后的数据聚合处理,不要在parse回调中直接维护全局列表或生成DataFrame,避免异步执行导致的数据错乱、变量未定义问题。
1. 修正爬虫核心逻辑
import scrapy class LaquotidienneSpider(scrapy.Spider): name = 'laquotidienne' # 修正起始地址,和后续分页规则保持一致,从经济栏目第一页开始爬取 start_urls = ['https://laquotidienne.ma/articles/economie/1'] def parse(self, response): # 遍历当前页所有文章条目 for article in response.css('div.list_article_detail'): raw_link = article.css('a::attr(href)').get() item = { "title": article.css('a::text').get().replace('\n', ' ').strip(), "link": response.urljoin(raw_link), # 自动补全文章相对链接为绝对地址 "date": article.css('span::text').get().strip() if article.css('span::text').get() else None } # 单条数据提取完成后直接yield交给pipeline处理,不需要本地维护列表 yield item # 分页逻辑:基于当前页码生成下一页地址,最多爬取到500页 current_page_num = int(response.url.rstrip('/').split('/')[-1]) if current_page_num < 500: next_page = f"https://laquotidienne.ma/articles/economie/{current_page_num + 1}" yield response.follow(next_page, callback=self.parse)
2. 编写Pipeline聚合数据生成DataFrame
打开项目下的pipelines.py文件,添加如下处理逻辑:
import pandas as pd class LaquotidienneDataPipeline: def open_spider(self, spider): # 爬虫启动时初始化空列表,用于存储所有爬取到的条目 self.all_articles = [] def process_item(self, item, spider): # 每接收到一条爬取数据就追加到列表 self.all_articles.append(dict(item)) return item def close_spider(self, spider): # 所有爬取任务完成后,统一生成包含title、link、date三列的DataFrame df = pd.DataFrame(self.all_articles, columns=['title', 'link', 'date']) # 可按需将结果存储为csv文件 df.to_csv('laquotidienne_eco_articles.csv', index=False, encoding='utf-8-sig') # 如需外部调用df,可将其绑定到spider实例属性 spider.result_df = df
3. 开启Pipeline配置
打开项目下的settings.py文件,找到ITEM_PIPELINES配置项,取消注释并添加自定义pipeline:
ITEM_PIPELINES = { '替换为你的项目名称.pipelines.LaquotidienneDataPipeline': 300, }
注意:不要尝试在
parse方法中用全局变量收集数据,Scrapy的异步调度机制会导致数据重复、丢失,甚至触发跨线程变量访问错误,使用pipeline聚合数据是最稳定的实现方式。
内容的提问来源于stack exchange,提问作者Sebastian280797
相关产品推荐
相关产品推荐

