同一台设备的重量有四种写法:抽取数值的单位归一与量纲校验

发布时间:2026/10/28 23:43:28
同一台设备的重量有四种写法:抽取数值的单位归一与量纲校验 公开资料里抓出来的数值写法不一致是常态。同一款设备的整机重量说明书里是「12.5 kg」官网参数栏写「12.5 千克」经销商页面写「12500g」另一篇评测文章写「约 12.5 KG不含包装」。四个字符串两两不相等。把它们直接当成四个候选值丢进比对逻辑结果只有两种要么判成数据冲突报一堆假问题要么取最后一条把冲突掩盖掉。要让这类数值可比得先把它们压成同一个内部表示数值、量纲、规范单位、以及一条这个数带不带限定的标记。下面记录用标准库实现的做法重点不在正则技巧而在失败时怎么留痕。一、词典按量纲分组不按单位字符串平铺第一种实现是把所有单位放进一张表kg → 1、g → 0.001、斤 → 0.5、mm → 1、cm → 10。看起来能用写到第三批资料就会出问题同一批数据里既出现「12.5 kg」又出现「125 mm」如果换算表是平铺的比对时就无法回答这两个数是不是在说同一件事。正确的结构是先分组再换算量纲是桶单位在桶里带一个到基准单位的因子。DIMENSIONS { mass: { 基准: (kg, 1.0), 单位: {kg: 1.0, 千克: 1.0, 公斤: 1.0, g: 0.001, 克: 0.001, 斤: 0.5, 吨: 1000.0}, }, length: { 基准: (mm, 1.0), 单位: {mm: 1.0, 毫米: 1.0, cm: 10.0, 厘米: 10.0, m: 1000.0, 米: 1000.0, 英寸: 25.4, inch: 25.4}, }, power: { 基准: (kW, 1.0), 单位: {W: 0.001, w: 0.001, 瓦: 0.001, kW: 1.0, 千瓦: 1.0, 马力: 0.7355}, }, }单位名要大小写各存一条。资料里KW、Kw、kw都出现过M与m在功率与长度里还各指一种量纲。归一时统一转小写查表比强行规定输入必须符合某种大小写要稳。二、解析先剥限定词再拆数字与单位「约 12.5 KG不含包装」这一条里有三层信息数值 12.5、单位 kg、以及两个限定标记约、条件说明。限定词不能当垃圾丢掉它决定了这条记录能不能用来做等值判断。import re QUALIFIERS {约: approx, 左右: approx, ±: tol, 不含: exclude, 含: include, 以上: lower_bound, 以下: upper_bound, 最大: peak, 额定: rated} ALL_UNITS [u for cfg in DIMENSIONS.values() for u in cfg[单位]] def parse(text): raw (text or ).strip() flags [tag for word, tag in QUALIFIERS.items() if word in raw] m re.search(r-?\d(?:\.\d)?, raw) if not m: return {raw: raw, ok: False, value: None, unit: None, flags: flags} tail raw[m.end():].strip( ,。.;()) low tail.lower() unit max((u for u in ALL_UNITS if u.lower() in low), keylen, default) return {raw: raw, ok: True, value: float(m.group()), unit: unit, flags: flags}取单位这一步用的是「词典里最长匹配」而不是把数字后面的一串字符整段当单位收上来。差别很实际约 12.5 KG不含包装里贪婪收法会把「KG不含包装」一起收进单位字段查表必然落空最长匹配拿到KG剩下的部分只作为限定标记参与后续判断。这也是为什么归一函数要区分两种失败一类是单位不认识词典没覆盖一类是单位认识但量纲不对质量字段里出现M。def normalize(parsed, expected_dim): if not parsed[ok]: return {status: no_number, detail: parsed[raw]} bucket DIMENSIONS[expected_dim][单位] unit parsed[unit].lower() for name, factor in bucket.items(): if name.lower() unit: return {status: ok, value: parsed[value] * factor, unit: DIMENSIONS[expected_dim][基准][0], flags: parsed[flags]} other [d for d, cfg in DIMENSIONS.items() if unit in {u.lower() for u in cfg[单位]}] return {status: wrong_dim if other else unknown_unit, detail: %s 出现在 %s 字段 % (parsed[unit], expected_dim)}wrong_dim与unknown_unit分开是为了让规则扩展有依据。前者说明词典是全的、这一条数据本身有问题应该回原文核对后者说明这批资料的写法超出了当前覆盖应该补词典。两种失败混在一个状态里跑一个月之后谁也不会回头看。四、比对阶段的三个陷阱| 陷阱 | 典型输入 | 后果与对策 || --- | --- | --- || 把近似当相等 | 「约 12.5 kg」与「12.48 kg」 | 带approx标记的候选不参与等值判断只参与范围判断 || 忽略口径差异 | 「12.5 kg不含包装」与「14 kg」 | 条件说明留成字段比对时按同口径配对 || 精度信息丢失 | 「12.5」与「12.500」 | 原字符串留在结构里归一值只用于比较 |第二条最容易漏。设备重量按不含包装写、竞品按含包装写两个数放一起就成了竞品更重的结论。这类错误在数值完全正确的前提下发生事后很难通过抽查发现因为它不是抽取错是配对错。第三条涉及一个取舍归一值用浮点数比对时用绝对差或相对差阈值。直接拿12.5与12.50做字符串相等判断会漏掉真正需要人工确认的口径差异把它们都当成同一个数又会把三位小数精度来自检测报告这条线索抹掉。原字符串留在结构里成本只是多存一列。五、什么时候不该做归一两类场景建议停在抽取层。一是资料本身没有单位比如参数表里只有「12.5」一列单位写在表外的注释段落里——这种要先解决表头与注释的归属关系再谈单位归一。二是同名单位在不同量纲里含义不同比如M在长度与功率语境里指向两个东西这时归一函数会返回wrong_dim正确的做法是回到原文补上下文而不是猜一个。数值可比性这件事规则会随资料写法一直长。真正稳的做法是把失败留痕做扎实哪一条没解析出来、以什么原因没解析出来都能回查。有了这份留痕词典与口径规则才有扩充的依据没有留痕只能在结论出来后回头怀疑所有数据。本文由一支长期做企业内容抽取的技术团队整理欢迎同行交流指正。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询