Scrapy框架数据可视化完全指南
你想掌握Scrapy框架的数据可视化方法,核心逻辑是「先存储数据,再提取数据,最后调用可视化库绘图」——Scrapy本身不提供可视化功能,需搭配Python主流数据可视化库(Matplotlib、Seaborn、Pandas)实现,流程清晰且可直接复刻,以下是详细实操教程,覆盖从数据存储到可视化绘图的全流程。
一、前置基础:数据可视化的核心流程
Scrapy实现数据可视化的3个关键步骤,缺一不可:
- 爬取并存储数据:通过Scrapy爬取数据,将其存储为易读取的格式(优先CSV/JSON,方便后续提取);
- 提取并预处理数据:使用Pandas读取存储的文件,进行简单数据预处理(去重、缺失值填充、格式转换);
- 调用可视化库绘图:结合Matplotlib/Seaborn绘制图表,优化图表样式并保存结果。
必备前置准备(搭建测试环境)
- 安装依赖库:
# 核心可视化库
pip install matplotlib seaborn pandas
# 解决Matplotlib中文乱码(可选,Windows/Mac通用)
pip install pyplotz
- 已有Scrapy爬取数据:使用之前的名言爬取项目,已存储为
quotes.csv(包含content、author、tags、born_date字段),若无,可先运行爬虫生成测试数据。 - 数据预览:先通过Pandas读取数据,验证数据完整性:
import pandas as pd
# 读取Scrapy存储的CSV文件
df = pd.read_csv("quotes.csv", encoding="utf_8_sig")
# 预览前5行数据
print("数据预览:")
print(df.head())
# 查看数据基本信息(字段、非空值、格式)
print("\n数据基本信息:")
print(df.info())
二、核心实操:3种常见可视化场景(基于Scrapy爬取数据)
以下所有场景均基于Scrapy爬取的quotes.csv数据,从简单到复杂,代码可直接运行。
场景1:基础统计可视化(作者名言数量排行,Matplotlib+Pandas)
需求说明
统计每个作者的名言产出数量,绘制柱状图(TOP10作者),直观展示作者产出差异。
完整代码
import pandas as pd
import matplotlib.pyplot as plt
# 解决Matplotlib中文乱码(若无需中文,可注释)
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示异常
def visualize_author_quote_count():
# 1. 读取Scrapy存储的CSV数据(核心:提取已爬取数据)
df = pd.read_csv("quotes.csv", encoding="utf_8_sig")
# 2. 数据预处理(Scrapy爬取数据可能存在重复,先去重)
df_clean = df.drop_duplicates(subset=["content"]) # 按名言内容去重
df_clean = df_clean[df_clean["author"].notna()] # 过滤作者为空的脏数据
# 3. 统计核心数据(作者名言数量)
author_count = df_clean["author"].value_counts().head(10) # TOP10作者
# 4. 绘制柱状图(Matplotlib核心绘图)
fig, ax = plt.subplots(figsize=(12, 6))
bars = ax.bar(author_count.index, author_count.values, color="#2E86AB", alpha=0.8)
# 5. 优化图表样式(添加标签、标题、数值标注)
ax.set_title("Scrapy爬取:名言作者产出数量TOP10", fontsize=16, pad=20)
ax.set_xlabel("作者姓名", fontsize=12)
ax.set_ylabel("名言数量(条)", fontsize=12)
ax.tick_params(axis="x", rotation=45) # 横坐标作者姓名旋转45度,避免重叠
# 给每个柱状图添加数值标注
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height + 0.1,
f"{int(height)}", ha="center", va="bottom", fontsize=10)
# 6. 保存图表(避免运行后图表一闪而过)
plt.tight_layout() # 自动调整布局,避免内容被截断
plt.savefig("作者名言数量TOP10.png", dpi=300, bbox_inches="tight")
plt.show()
if __name__ == "__main__":
visualize_author_quote_count()
运行结果
生成作者名言数量TOP10.png图片,清晰展示TOP10作者的名言产出数量,无中文乱码,柱状图带数值标注,样式规整。
关键技巧
- 数据预处理是可视化的前提:Scrapy爬取的数据可能存在重复和空值,必须先通过
drop_duplicates()和notna()过滤; - 中文乱码解决:设置
plt.rcParams["font.family"]为系统支持的中文字体(SimHei为黑体,Windows/Mac均支持); - 图表保存:使用
plt.savefig()在plt.show()之前保存,避免图表关闭后无法保存。
场景2:标签分布可视化(热门标签词云+频次分布图,Seaborn)
需求说明
统计名言标签的出现频次,绘制横向柱状图(TOP15标签),并生成词云图,直观展示热门标签。
完整代码
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud # 额外安装:pip install wordcloud
# 解决中文乱码
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False
def visualize_tag_distribution():
# 1. 读取Scrapy存储的CSV数据
df = pd.read_csv("quotes.csv", encoding="utf_8_sig")
# 2. 数据预处理(处理标签字段:逗号分隔转列表,展开统计)
df_clean = df.drop_duplicates(subset=["content"]).reset_index(drop=True)
df_clean = df_clean[df_clean["tags"].notna()] # 过滤标签为空的数据
# 拆分标签(逗号分隔→列表→展开为一维数组)
tags_list = []
for tags in df_clean["tags"]:
if isinstance(tags, str) and tags != "":
tags_list.extend([tag.strip() for tag in tags.split(",")])
# 3. 统计标签频次
tags_series = pd.Series(tags_list)
tags_count = tags_series.value_counts().head(15) # TOP15标签
# 4. 绘制横向柱状图(Seaborn,更美观)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 8))
# 4.1 横向柱状图
sns.barplot(x=tags_count.values, y=tags_count.index, ax=ax1, color="#A23B72", alpha=0.8)
ax1.set_title("Scrapy爬取:名言标签频次TOP15", fontsize=14, pad=15)
ax1.set_xlabel("标签出现频次(次)", fontsize=12)
ax1.set_ylabel("标签名称", fontsize=12)
# 给横向柱状图添加数值标注
for i, v in enumerate(tags_count.values):
ax1.text(v + 0.1, i, f"{v}", va="center", fontsize=10)
# 5. 生成词云图
tags_text = " ".join(tags_list) # 拼接为空格分隔的字符串,用于词云生成
wordcloud = WordCloud(
width=800, height=400,
background_color="white",
font_path="simhei.ttf", # 中文词云必须指定字体文件(Windows:simhei.ttf,Mac:Arial Unicode.ttf)
max_words=100,
colormap="viridis"
).generate(tags_text)
# 5.1 绘制词云图
ax2.imshow(wordcloud, interpolation="bilinear")
ax2.axis("off") # 关闭坐标轴
ax2.set_title("Scrapy爬取:名言标签词云图", fontsize=14, pad=15)
# 6. 保存图表
plt.tight_layout()
plt.savefig("标签分布可视化.png", dpi=300, bbox_inches="tight")
plt.show()
if __name__ == "__main__":
visualize_tag_distribution()
运行结果
生成标签分布可视化.png图片,左侧为TOP15标签横向柱状图,右侧为标签词云图,热门标签字体更大,视觉效果直观。
关键技巧
- 标签数据处理:Scrapy爬取的标签是逗号分隔的字符串,需先拆分为列表,再展开为一维数组进行统计;
- Seaborn绘图优势:相比Matplotlib,样式更美观,代码更简洁,适合快速生成统计图表;
- 中文词云注意事项:必须指定
font_path为本地中文字体文件路径,否则中文无法正常显示。
场景3:整合Scrapy Pipeline(可视化自动化,爬取完成后自动绘图)
需求说明
通过Scrapy Pipeline实现「爬取完成→数据存储→自动可视化」,无需手动运行绘图代码,提升效率。
步骤1:编写可视化Pipeline(pipelines.py)
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
# 解决中文乱码
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False
class DataVisualizationPipeline:
"""Scrapy可视化Pipeline:爬取完成后自动生成图表"""
def __init__(self):
# 配置文件路径和图表保存路径
self.csv_path = "quotes.csv"
self.chart_save_path = "scrapy_visualization_charts"
# 创建图表保存目录(不存在则自动创建)
if not os.path.exists(self.chart_save_path):
os.makedirs(self.chart_save_path)
def close_spider(self, spider):
"""爬虫关闭时执行(仅执行一次):读取数据并生成可视化图表"""
spider.logger.info("开始执行自动数据可视化...")
# 1. 检查CSV文件是否存在
if not os.path.exists(self.csv_path):
spider.logger.error(f"CSV文件不存在:{self.csv_path},无法进行可视化")
return
# 2. 读取并预处理数据
try:
df = pd.read_csv(self.csv_path, encoding="utf_8_sig")
df_clean = df.drop_duplicates(subset=["content"]).reset_index(drop=True)
df_clean = df_clean[df_clean["author"].notna()]
spider.logger.info(f"成功读取数据,清洗后数据量:{len(df_clean)}条")
except Exception as e:
spider.logger.error(f"读取/预处理数据失败:{e}")
return
# 3. 生成作者名言数量柱状图(TOP10)
try:
author_count = df_clean["author"].value_counts().head(10)
fig, ax = plt.subplots(figsize=(12, 6))
bars = ax.bar(author_count.index, author_count.values, color="#2E86AB", alpha=0.8)
ax.set_title("Scrapy爬取:名言作者产出数量TOP10", fontsize=16, pad=20)
ax.set_xlabel("作者姓名", fontsize=12)
ax.set_ylabel("名言数量(条)", fontsize=12)
ax.tick_params(axis="x", rotation=45)
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height + 0.1,
f"{int(height)}", ha="center", va="bottom", fontsize=10)
# 保存图表到指定目录
author_chart_path = os.path.join(self.chart_save_path, "作者名言数量TOP10.png")
plt.tight_layout()
plt.savefig(author_chart_path, dpi=300, bbox_inches="tight")
plt.close() # 关闭图表,释放内存
spider.logger.info(f"成功生成作者名言数量图表:{author_chart_path}")
except Exception as e:
spider.logger.error(f"生成作者名言数量图表失败:{e}")
# 4. 生成标签频次横向柱状图(TOP15)
try:
if "tags" in df_clean.columns and df_clean["tags"].notna().any():
tags_list = []
for tags in df_clean["tags"]:
if isinstance(tags, str) and tags != "":
tags_list.extend([tag.strip() for tag in tags.split(",")])
if tags_list:
tags_count = pd.Series(tags_list).value_counts().head(15)
fig, ax = plt.subplots(figsize=(10, 8))
sns.barplot(x=tags_count.values, y=tags_count.index, ax=ax, color="#A23B72", alpha=0.8)
ax.set_title("Scrapy爬取:名言标签频次TOP15", fontsize=14, pad=15)
ax.set_xlabel("标签出现频次(次)", fontsize=12)
ax.set_ylabel("标签名称", fontsize=12)
for i, v in enumerate(tags_count.values):
ax.text(v + 0.1, i, f"{v}", va="center", fontsize=10)
# 保存图表
tags_chart_path = os.path.join(self.chart_save_path, "标签频次TOP15.png")
plt.tight_layout()
plt.savefig(tags_chart_path, dpi=300, bbox_inches="tight")
plt.close()
spider.logger.info(f"成功生成标签频次图表:{tags_chart_path}")
except Exception as e:
spider.logger.error(f"生成标签频次图表失败:{e}")
spider.logger.info("自动数据可视化执行完成,图表已保存至:{self.chart_save_path}")
步骤2:启用可视化Pipeline(settings.py)
ITEM_PIPELINES = {
# 数据清洗Pipeline(优先级200)
'data_clean_spider.pipelines.DataCleaningPipeline': 200,
# 数据存储Pipeline(优先级300)
'data_clean_spider.pipelines.CsvFileStoragePipeline': 300,
# 自动可视化Pipeline(优先级400,最后执行)
'data_clean_spider.pipelines.DataVisualizationPipeline': 400,
}
步骤3:运行爬虫验证结果
scrapy crawl quote_spider
运行结果
- 爬虫爬取完成后,自动创建
scrapy_visualization_charts目录; - 目录内生成
作者名言数量TOP10.png和标签频次TOP15.png; - 爬虫日志中输出可视化执行状态,无报错则说明执行成功。
关键技巧
- 可视化Pipeline在
close_spider()中执行:该方法仅在爬虫关闭时运行一次,避免重复绘图,提升效率; - 目录创建:使用
os.makedirs()创建图表保存目录,避免文件保存失败; - 内存优化:使用
plt.close()关闭绘制完成的图表,释放内存,避免大规模爬取时内存溢出。
三、常见可视化问题与解决方案汇总
| 问题类型 | 典型表现 | 核心解决方案 |
|---|---|---|
| 中文乱码 | 图表中中文显示为方框/问号 | 1. 设置plt.rcParams中文字体;2. 词云指定font_path字体文件 |
| 图表内容截断 | 坐标轴标签、标题超出图表范围 | 1. 使用plt.tight_layout();2. 保存时添加bbox_inches="tight" |
| 数据为空/统计异常 | 图表无数据/频次为0 | 1. 检查Scrapy存储的CSV文件是否有数据;2. 加强数据预处理,过滤空值/无效数据 |
| 内存溢出 | 大规模数据可视化时程序崩溃 | 1. 使用plt.close()关闭图表;2. 分批处理数据,避免一次性加载全部数据 |
| 词云无中文显示 | 词云图仅显示英文,中文不显示 | 1. 下载中文字体文件(如simhei.ttf);2. 准确指定font_path为字体文件路径 |
四、实操注意事项与优化技巧
- 数据格式优先选择CSV:Scrapy爬取数据存储为CSV,Pandas读取效率最高,兼容性最好,适合可视化预处理;
- 可视化库选型:
- 简单统计图表(柱状图、折线图):优先Matplotlib,灵活可控;
- 美观统计图表(横向柱状图、热力图):优先Seaborn,代码简洁,样式美观;
- 文本类数据(标签、标题):优先WordCloud,视觉效果直观;
- 避免在爬虫运行中实时绘图:爬虫运行时专注于数据爬取和存储,可视化放在爬虫关闭后执行,避免影响爬取效率;
- 图表优化细节:
- 添加清晰的标题、坐标轴标签,提升图表可读性;
- 选择合适的图表尺寸(
figsize),避免内容拥挤; - 使用统一的配色方案,提升图表美观度;
- 大规模数据可视化优化:
- 采用抽样统计(如抽取10%数据进行可视化),避免数据量过大导致绘图缓慢;
- 使用批量处理方式,分批次生成图表,避免内存溢出;
- 结果备份:将生成的图表和预处理后的数据统一保存到指定目录,方便后续分析和归档。
浙公网安备 33010602011771号