4、数据清洗实战:处理缺失值、去重、去除HTML标签、统一文本编码(Unicode)、正则表达式入门。

各位同学,欢迎来到数据清洗实战环节。

说实话,在新闻情绪分析这个领域,我踩过最大的坑不是模型选型,也不是调参,而是——数据太脏。你想想看,从网上爬下来的新闻文本,什么乱七八糟的东西都有。缺失值、重复内容、HTML标签乱飞、编码错乱……如果不把这些处理好,模型学出来的东西,说白了就是垃圾进垃圾出。

我个人习惯,拿到数据的第一件事,不是看分布,不是画图,而是先做清洗。今天这一章,我就带你把这几个核心操作过一遍。

4.1 处理缺失值

新闻数据里,缺失值很常见。比如某条新闻的正文字段是空的,或者发布时间缺失。怎么办?

我一般分三步走:

  • 检测缺失:用 df.isnull().sum() 快速定位
  • 判断策略:如果缺失比例超过 50%,直接删掉整行;如果只是少量缺失,看情况填充
  • 执行操作:用 df.dropna()df.fillna()

举个例子:

import pandas as pd

# 假设 df 是新闻数据集
print(df.isnull().sum())

# 删除正文为空的新闻
df = df.dropna(subset=['content'])

# 用空字符串填充标题缺失
df['title'] = df['title'].fillna('')

嗯,这里要注意:千万别一股脑全删。我在项目中遇到过,某次删了太多行,导致样本量不够,模型直接崩了。所以,先看比例,再动手。

4.2 去重

新闻数据里重复很常见。同一篇新闻被多个网站转载,或者爬虫重复抓取。去重是必须的。

我常用的方法:

  • 完全去重df.drop_duplicates()
  • 按关键列去重:比如按标题去重 df.drop_duplicates(subset=['title'])

但这里有个坑:有些新闻标题一样,内容却不同(比如更新版)。所以,我建议你按「标题+发布时间」联合去重,更稳妥。

# 按标题和发布时间联合去重
df = df.drop_duplicates(subset=['title', 'publish_time'])

我曾经因为只按标题去重,结果把同一事件的不同报道版本删掉了,导致模型学到的信息不完整。后来改了策略,效果好了很多。

4.3 去除HTML标签

爬虫抓下来的新闻,经常带着一堆HTML标签。比如 <p>内容</p><br> 这些。模型可看不懂这些,必须去掉。

我推荐用 BeautifulSoup 或者正则表达式。BeautifulSoup 更安全,正则更快。看你的场景。

from bs4 import BeautifulSoup

def clean_html(text):
    soup = BeautifulSoup(text, 'html.parser')
    return soup.get_text()

df['content'] = df['content'].apply(clean_html)

如果你不想引入第三方库,也可以用正则:

import re

def clean_html_re(text):
    return re.sub(r'<[^>]+>', '', text)

我个人习惯用 BeautifulSoup,因为它还能处理一些不规范的标签。正则虽然快,但遇到嵌套标签容易出错。

4.4 统一文本编码(Unicode)

编码问题,是数据清洗里最让人头疼的。你想想看,有的新闻是UTF-8,有的是GBK,还有的是Latin-1。如果不统一,后面分词、建模全乱套。

我的做法是:

  • 先检测编码:用 chardet
  • 再统一转为 UTF-8
import chardet

def detect_and_fix_encoding(text_bytes):
    result = chardet.detect(text_bytes)
    encoding = result['encoding']
    return text_bytes.decode(encoding, errors='ignore')

# 假设你读取的是字节数据
with open('news.txt', 'rb') as f:
    raw = f.read()
text = detect_and_fix_encoding(raw)

嗯,这里有个小技巧:如果数据量很大,别一条条检测,太慢了。可以抽样检测,然后统一用检测到的编码去解码。

我曾经在做一个多语言新闻项目时,因为编码没处理好,模型训练到一半直接报错。排查了半天,才发现是某条俄语新闻的编码不对。从那以后,我每次清洗数据都会先过一遍编码检测。

4.5 正则表达式入门

正则表达式,说白了就是文本匹配的瑞士军刀。在数据清洗里,它无处不在。

我常用的几个场景:

  • 去除特殊字符(如标点、emoji)
  • 提取特定模式(如邮箱、电话号码)
  • 替换不规范写法

先看几个基础语法:

模式含义示例
.匹配任意字符(除换行)a.b 匹配 "acb"
*匹配前一个字符0次或多次ab*c 匹配 "ac", "abc"
+匹配前一个字符1次或多次ab+c 匹配 "abc", "abbc"
?匹配前一个字符0次或1次ab?c 匹配 "ac", "abc"
\d匹配数字\d+ 匹配 "123"
\w匹配字母、数字、下划线\w+ 匹配 "hello_123"
[]字符集[aeiou] 匹配元音字母

实战例子:去除新闻正文里的所有非中文字符(保留中文、数字、标点)

import re

def clean_text(text):
    # 只保留中文、英文、数字、常见标点
    pattern = r'[^\u4e00-\u9fa5a-zA-Z0-9,。!?、;:""''()【】《》\s]'
    return re.sub(pattern, '', text)

df['content'] = df['content'].apply(clean_text)

你可能会问:为什么要保留中文?因为新闻情绪分析,中文是核心。去掉中文,那还分析什么?

正则表达式入门不难,但想精通需要大量练习。我建议你每次遇到新的清洗需求,先想想能不能用正则解决。久而久之,你就熟练了。

核心要点总结

  • 缺失值:先检测比例,再决定删除还是填充
  • 去重:按关键列联合去重,避免误删
  • HTML标签:BeautifulSoup 或正则,推荐前者
  • 编码统一:用 chardet 检测,转 UTF-8
  • 正则:从基础语法开始,逐步应用到实际场景

我的小建议

数据清洗没有标准答案。每个项目的数据都不一样,你需要根据实际情况灵活调整。但记住一点:清洗得越干净,模型效果越好。别嫌麻烦。

注意

正则表达式虽然强大,但不要滥用。有些复杂的文本处理,用专门的NLP库(如jieba、spaCy)会更高效。正则适合做「规则明确」的清洗任务。

数据清洗核心流程 原始新闻数据 1. 处理缺失值 2. 去重 3. 去除HTML标签 4. 统一编码 5. 正则表达式清洗 6. 输出干净数据 清洗后的新闻数据

好了,这一章的内容就到这里。数据清洗虽然琐碎,但它是整个新闻情绪分析项目的基石。你想想看,如果数据本身就有问题,后面再好的模型也白搭。所以,别嫌麻烦,一步步来。

下一章,我们会进入文本预处理环节,包括分词、去停用词、词性标注等。到时候见。

专注资料整理