引言:从抓取到洞察的关键一跃
上一篇我们用Selenium突破了动态页面抓取瓶颈,获得了豆瓣《肖申克的救赎》短评原始数据。但直接拿到的JSON或CSV往往充满噪声:空字符串、重复记录、格式混乱的评分......若跳过清洗直接分析,结论必然失真。本文聚焦"数据准备"这一被低估的环节,用Pandas将脏数据转化为干净的分析基表,并衔接SnowNLP完成基础情感量化。所有操作均针对中文影评场景优化,代码即插即用。
数据加载与初步诊断
假设Selenium导出的数据保存为comments_raw.csv,首步是快速评估数据质量:
python
import pandas as pd
# 读取时指定编码,避免中文乱码
df = pd.read_csv('comments_raw.csv', encoding='utf-8-sig')
# 一键生成数据健康报告
print("=== 数据概览 ===")
print(f"总行数: {len(df)}")
print(f"列名: {list(df.columns)}")
print("\n=== 缺失值统计 ===")
print(df.isnull().sum())
print("\n=== 数据类型 ===")
print(df.dtypes)
print("\n=== 前3行样本 ===")
print(df.head(3))
关键观察点 :重点关注
content列的空值比例、user列的重复率、以及是否存在非字符串类型的评论内容。这些是后续清洗的优先级依据。
核心清洗四步法:构建可信分析基表
第一步:去除完全重复记录
爬虫重试或翻页逻辑缺陷常导致重复数据,需优先清理:
python
# 按内容+用户联合去重(避免不同用户对相同内容的误删)
before = len(df)
df.drop_duplicates(subset=['user', 'content'], keep='first', inplace=True)
print(f"去重后减少 {before - len(df)} 条记录")
第二步:处理缺失值与异常值
短评内容为空则失去分析价值,直接删除;用户名缺失可保留但标记:
python
# 删除内容为空的行
df = df[df['content'].notna() & (df['content'].str.strip() != '')]
# 用户名缺失填充占位符,避免后续分组报错
df['user'] = df['user'].fillna('匿名用户')
# 重置索引(drop后索引不连续会影响后续操作)
df.reset_index(drop=True, inplace=True)
第三步:文本标准化
统一全角/半角、去除多余空白、转换大小写,为NLP做准备:
python
import re
def clean_text(text):
if not isinstance(text, str):
return ''
# 全角转半角
text = text.translate(str.maketrans(' !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~',
' !"# $ %&\'()*+,-./:;<=>?@[\ $ ^_`{|}~'))
# 合并连续空白字符
text = re.sub(r'\s+', ' ', text).strip()
return text
df['clean_content'] = df['content'].apply(clean_text)
第四步:验证清洗效果
清洗后必须复核,避免过度处理丢失有效信息:
python
print("=== 清洗后数据质量 ===")
print(f"有效记录数: {len(df)}")
print(f"内容平均长度: {df['clean_content'].str.len().mean():.1f} 字符")
print(f"空内容剩余: {(df['clean_content'] == '').sum()} 条")
避坑提醒:切勿盲目删除短文本!"神作""泪目"等极简评论恰恰是高浓度情感信号。清洗目标是"规范",而非"筛选"。
情感分析接入:SnowNLP轻量级实践
清洗后的clean_content可直接用于情感打分。SnowNLP专为中文设计,无需训练即可输出0-1情感值(越接近1越积极):
python
from snownlp import SnowNLP
# 批量计算情感得分(注意:大数据量时需分批处理防内存溢出)
df['sentiment_score'] = df['clean_content'].apply(
lambda x: SnowNLP(x).sentiments if x else 0.5
)
# 划分情感区间便于解读
df['sentiment_label'] = pd.cut(
df['sentiment_score'],
bins=[0, 0.4, 0.6, 1],
labels=['负面', '中性', '正面'],
include_lowest=True
)
# 查看情感分布
print(df['sentiment_label'].value_counts(normalize=True).round(3))
重要说明:SnowNLP对讽刺、反语识别较弱,结果仅作趋势参考。生产环境建议结合人工标注校准阈值,或使用BERT等深度学习模型提升精度。
结果导出与分析就绪
将清洗+打标后的数据持久化,供可视化或建模使用:
python
# 仅保留分析所需字段,减小文件体积
output_cols = ['user', 'clean_content', 'sentiment_score', 'sentiment_label']
df[output_cols].to_csv('comments_cleaned.csv', index=False, encoding='utf-8-sig')
print("✅ 清洗完成!数据已保存至 comments_cleaned.csv")
合规与伦理重申
本流程所用数据仅限个人学习研究。发布分析结果时须匿名化处理用户名,不引用具体评论原文,不关联真实身份。数据清洗不仅是技术动作,更是对用户隐私的尊重------我们处理的每一行文本,都曾是一个人的真实表达。
总结:清洗是分析的道德与技术基石
从Selenium抓取到Pandas清洗,再到SnowNLP打分,这条链路看似简单,实则暗藏无数细节陷阱。真正决定分析价值的,不是算法多炫酷,而是数据是否干净、处理是否透明、结论是否可追溯。当你下次面对杂乱的原始数据不再烦躁,而是将其视为理解用户声音的必经之路时,便掌握了数据科学最朴素也最重要的心法。下一篇,我们将用Matplotlib把情感分布转化为直观图表,让数字自己讲述《肖申克的救赎》为何穿越三十年仍打动人心。记住:好的分析始于敬畏数据,成于严谨清洗。