set()去重会丢失顺序是因为其无序特性,应改用dict.fromkeys()保持插入顺序;清洗需标准化字符串并处理HTML实体;字段级去重优于全文哈希,关键字段组合生成指纹更可靠。

用 set() 去重时为什么丢失了顺序?
直接套 list(set(data)) 看似省事,但 Python 的 set 无序,原始抓取顺序(比如按时间、热度、分页顺序)会彻底打乱。尤其当后续要保留“第一条是最新”这类业务逻辑时,这等于埋雷。
更稳妥的做法是用 dict.fromkeys() 保持插入顺序(Python 3.7+ 保证有序):
cleaned = list(dict.fromkeys(raw_list))
注意:仅适用于元素可哈希(str、int、tuple),含 dict 或 list 的嵌套结构会报 TypeError;此时得转成 JSON 字符串再去重,但要注意浮点精度、键顺序等干扰项。
清洗 HTML 标签和空白字符的常见翻车点
很多人用 re.sub(r']+>', '', text) 简单粗暴删标签,结果遇到 <script> 里藏的 JS、<style> 里的 CSS,或者未闭合标签(如 <br)时,正则直接失效甚至误删正文。
立即学习“Python免费学习笔记(深入)”;
推荐用 BeautifulSoup 配合 get_text(),但要注意三点:
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
-
strip=True参数必须显式传,否则首尾空格残留 - 多个连续换行或空格会被压缩成单个空格,若需保留段落结构,改用
get_text(separator=' ', strip=False)后再手动re.sub(r'\s+', ' ', ...) - 遇到
、—等 HTML 实体,要加html.unescape()解码,否则清洗后还留着&符号
去重前先标准化再比对,否则 '北京' 和 ' 北京 ' 被当成两条
爬虫数据里常见空格、全角/半角符号混用、大小写不一致、URL 中 http 和 https 混存等问题。直接比对字符串等于白忙活。
建议统一走标准化管道:
def normalize(s):
if not isinstance(s, str): return s
s = html.unescape(s.strip())
s = re.sub(r'[^\w\s\u4e00-\u9fff]', '', s) # 保留中文、字母、数字、空格
s = re.sub(r'\s+', ' ', s)
return s.lower()之后再用 dict.fromkeys([normalize(x) for x in raw_list]),但注意:标准化后若需回溯原始值,得用元组 (normalized, original) 存储,不能丢原始数据。
面对重复 ID 但内容微调的数据,该用字段级去重还是全文哈希?
电商商品页抓取常出现 ID 相同但价格/库存变动的情况,此时按 ID 去重会丢变更;而按全文哈希又可能因广告位、时间戳等噪声字段导致相同内容被判定为不同。
务实做法是提取业务关键字段做组合哈希:
- 只取
title、price、sku_id(不含update_time、view_count) - 拼接后用
hashlib.md5(...encode()).hexdigest()[:8]生成简短指纹 - 用
collections.defaultdict(list)按指纹分组,再人工或规则判断是否真重复(比如价格差超 10% 就保留两条)
别依赖单一维度,真实数据永远在边界上——ID 可能填错,文本可能有错别字,哈希碰撞虽小但不是零。留痕比自动裁决更重要。

















