您的位置:首页 >Python实现对新闻数据去重处理的方法详解
发布于2026-08-05 阅读(0)
扫一扫,手机访问
做新闻爬虫、新闻数据分析、舆情项目的时候,大家肯定会遇到一个头疼的问题:海量重复新闻数据。同一篇新闻被多家网站转载,标题改一两个字、内容局部修修补补、发布时间不同,但本质就是同一条新闻。如果不去重,统计结果失真、数据库膨胀、分析结果被重复样本干扰,整个项目都会跑偏。

新闻去重和普通文本去重还真不太一样——不能简单粗暴地直接比字符串。常见的坑:标题多一两个字、换行空格不同、HTML标签残留、转载时增删导语,直接拿==全等匹配,会漏掉大量重复样本。
这篇文章会从简单到工业可用,分享几套Python处理新闻数据的实用方案,涵盖精准去重、模糊去重、海量新闻场景优化,希望能帮到正在做类似项目的朋友。
适用场景:新闻标题完全一致,只是来源、发布时间字段不一样。原理很简单:把标题做md5哈希,保存哈希值,新来的数据判断哈希是否已经存在。
优点:速度极快,内存占用低;缺点:标题稍微改动就失效,转载改标题就识别不出重复。
import hashlib
def get_md5(text: str) -> str:
"""文本生成md5"""
return hashlib.md5(text.strip().encode("utf-8")).hexdigest()
news_list = [
{"title": "人工智能行业迎来新一轮发展机遇", "content": "正文1...", "source": "A网"},
{"title": "人工智能行业迎来新一轮发展机遇", "content": "正文1...", "source": "B网"},
{"title": "大模型应用落地加速", "content": "正文2...", "source": "C网"},
]
seen = set()
distinct_news = []
for item in news_list:
title = item["title"].strip()
h = get_md5(title)
if h not in seen:
seen.add(h)
distinct_news.append(item)
print(f"原始:{len(news_list)} 去重后:{len(distinct_news)}")
需要提醒的是:转载新闻经常修改标题,比如加个【快讯】、改个标点,标题md5就直接失效了。这种方案适合小规模、标题几乎不变的数据集。
新闻网页拿到的数据常常混杂HTML标签、换行、空格、特殊符号、【】、#、摘要标记。无论后面用哪种算法,一定要先清洗文本,这一步直接决定了去重效果的下限。
import re
def clean_news_text(text: str) -> str:
"""清洗新闻文本,去掉干扰符号"""
if not text:
return ""
# 去除html标签
text = re.sub(r"<.*?>", "", text)
# 去掉各类特殊符号、换行、多余空格
text = re.sub(r"[【】《》#@nrt]", "", text)
text = re.sub(r"s+", "", text)
return text.strip()
使用建议:优先清洗标题,条件允许可以清洗正文片段。清洗后再做哈希、相似度计算,准确率能提升一大截。
新闻去重最经典的算法当属SimHash。核心思想:把长文本转为指纹,指纹相似度高就判定为重复新闻。即使改几个字、增删几句话,依然可以识别是同一篇新闻。非常适合转载新闻、正文局部改动、标题微调的场景。
import hashlib
def get_hash(s):
return int(hashlib.md5(s.encode("utf-8")).hexdigest(), 16)
def simhash(text: str, bit=64):
words = list(text)
v = [0]*bit
for word in words:
h = get_hash(word)
for i in range(bit):
if h >> i & 1:
v[i] +=1
else:
v[i] -=1
fingerprint = 0
for i in range(bit):
if v[i]>0:
fingerprint |= 1 << i
return fingerprint
def hamming_distance(h1, h2):
return bin(h1 ^ h2).count("1")
# 测试
news1_title = clean_news_text("人工智能行业迎来新一轮发展机遇")
news2_title = clean_news_text("【快讯】人工智能行业迎来新一轮发展机遇!")
fp1 = simhash(news1_title)
fp2 = simhash(news2_title)
dist = hamming_distance(fp1, fp2)
print(f"汉明距离:{dist}")
# 新闻业务经验阈值:汉明距离 <=3 判定为重复新闻
if dist <=3:
print("判定为重复新闻")
业务经验阈值:
注意:完整simhash工程实现一般用分词(jieba)而不是按单字切割,效果更好。
import jieba
def simhash_by_jieba(text:str, bit=64):
words = jieba.lcut(text)
v = [0]*bit
for w in words:
h = get_hash(w)
for i in range(bit):
if h >> i &1:
v[i] +=1
else:
v[i] -=1
fp =0
for i in range(bit):
if v[i]>0:
fp |= 1 <
真实项目里,海量新闻库直接两两计算汉明距离速度很慢,一般会做分桶,把指纹分段存储,只对比同桶内指纹,大幅降低计算量。
四、使用文本相似度:difflib 快速比对
适合小数据集,直接计算文本相似度得分,简单开箱即用。
from difflib import SequenceMatcher
def text_similarity(a:str,b:str)->float:
return SequenceMatcher(None,a,b).ratio()
t1 = clean_news_text("大模型产业正在快速发展")
t2 = clean_news_text("快讯:大模型产业正在快速发展!")
score = text_similarity(t1,t2)
print(f"相似度得分:{score:.2f}")
if score >=0.85:
print("判定重复新闻")
优点:简单,无需第三方库;缺点:数据量大的时候复杂度是O(n²),上万条新闻就会很慢,适合小批量处理。
五、数据库场景下新闻去重实战
爬虫入库的时候,我们通常不希望内存保存全部指纹,而是把指纹存到MySQL。流程如下:
- 新闻清洗标题、正文
- 生成simhash指纹、md5标题指纹
- 入库前查询数据库,比对指纹,判断是否重复;重复则跳过保存。
建表参考:
CREATE TABLE news(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(500),
content TEXT,
source VARCHAR(100),
publish_time DATETIME,
title_md5 CHAR(32),
simhash_fp BIGINT UNSIGNED,
INDEX idx_title_md5(title_md5)
);
业务逻辑伪代码:
# 拿到爬虫新闻
raw_news = {...}
clean_title = clean_news_text(raw_news["title"])
md5_val = get_md5(clean_title)
fp = simhash_by_jieba(clean_title)
# 查询数据库是否存在重复
# 优先匹配title_md5;如果没有,再做simhash汉明距离比对
注意:MySQL直接大量计算汉明距离性能很差,百万级新闻建议使用分桶策略,或者使用ES向量检索辅助去重。
六、不同方案选型对比
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 标题MD5哈希 | 标题完全一致 | 速度极快 | 标题微调失效,无法识别转载改写新闻 |
| difflib相似度 | 小数据集,几千条以内 | 简单,无需第三方库 | 大数据量性能差 |
| SimHash | 新闻转载、文本局部改动 | 工业界新闻去重标准,抗改写 | 需要调参,海量数据需要分桶优化 |
新闻数据去重分两个层级:精准去重(MD5)和模糊去重(SimHash)。
预处理清洗是所有方案的基础,很多人去重效果差,根源就是没有做文本清洗,特殊符号干扰指纹。如果数据量达到百万级别,内存方案已经扛不住,就需要结合数据库分桶策略,或者接入Elasticsearch向量检索做大规模新闻去重。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8