news 2026/10/20 9:09:02

中文参数文本里的数值与单位归一化:抽取成可比字段

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
中文参数文本里的数值与单位归一化:抽取成可比字段

技术资料里最常见的一个困境是:同一项参数在不同页面写成不同样子。"厚度 3mm""厚度 3 毫米""板厚≤3.0mm""加工精度 0.05—0.1 毫米",人一眼就知道在说同一件事,程序却比不出来。想做参数一致性校验、范围校验或者结构化入库,第一步绕不开归一化。

下面这套实现处理四类现实问题:中文与英文单位混写、全角数字与千分位、比较符号(不大于、不小于、约、区间)、以及一段文本里连写多个数量。目标不是做一个通用解析器,而是把抽取结果落成能直接比较的字段:量纲、基准值、下限、上限、符号、原文。

单位表与基准量纲

先把单位映射到同一量纲下的基准单位。这里刻意把量纲显式列出,因为跨量纲比较是这类代码最容易出的错——把"3 升"与"3 千克"当成同一项参数,比对结果看起来正常,实际全是错的。

DIMENSIONS = { "长度": {"mm": 1.0, "毫米": 1.0, "cm": 10.0, "厘米": 10.0, "m": 1000.0, "米": 1000.0, "km": 1000000.0, "公里": 1000000.0}, "质量": {"g": 1.0, "克": 1.0, "kg": 1000.0, "千克": 1000.0, "公斤": 1000.0, "t": 1000000.0, "吨": 1000000.0}, "温度": {"℃": 1.0, "°C": 1.0, "摄氏度": 1.0}, "体积": {"ml": 1.0, "毫升": 1.0, "l": 1000.0, "L": 1000.0, "升": 1000.0}, "比例": {"%": 1.0, "percent": 1.0}, } UNIT_INDEX = {} for dim, table in DIMENSIONS.items(): for unit in table: UNIT_INDEX.setdefault(unit.lower(), (dim, table[unit]))

映射表用小写键索引,查询时把候选单位也转小写,可以省掉 "L/l"、"Mm/MM" 这一类大小写分裂。温度不参与倍率换算,基准系数一律写 1.0,避免后续误把量纲当可乘单位。

数字与符号的解析

中文技术文本里的数字形态比想象中多:全角、半角混用,千分位带逗号,负号有短横与连字符两种。解析函数把这些折叠成浮点数,同时单独返回比较符号。

import re FULL_TO_HALF = str.maketrans("0123456789.-+", "0123456789.-+") NUM_PATTERN = r"[-+]?\d[\d,]*(?:\.\d+)?" OP_ALIASES = {"≤": "<=", "≦": "<=", "<": "<=", "≥": ">=", ">": ">=", "不大于": "<=", "不小于": ">=", "约": "~", "≈": "~", "以内": "<=", "以上": ">="} def parse_number(raw): text = raw.translate(FULL_TO_HALF).replace(",", "") return float(text)

OP_ALIASES这张表需要按行业语料维护。"以内"和"以下"在很多语境里等价,但"以下"在温度语境里含义更模糊,建议先只登记本企业语料里出现过的写法,遇到未知写法保留符号原文,不要靠猜。

抽取:一条正则覆盖四种形态

抽取的目标形态有四种:单值、带符号的单值、闭区间、以及一个短语里的多值。用一条带可选组的正则即可覆盖,剩下的交给后处理。

TOKEN = r"(?:%s)" % NUM_PATTERN RANGE_SEP = r"(?:[-—~~]|至|到)" PATTERN = re.compile( r"(?P<op>[≤≦≥~≈<>]{0,2}|不大于|不小于|约|以内|以上)?" r"\s*(?P<n1>%s)\s*(?P<u1>[a-zA-Z]{1,3}|[\u4e00-\u9fa5]{1,3}|%%)?" r"(?:\s*%s\s*(?P<n2>%s)\s*(?P<u2>[a-zA-Z]{1,3}|[\u4e00-\u9fa5]{1,3}|%%)?)?" % (TOKEN, RANGE_SEP, TOKEN) )

单位组写成"拉丁字母(1 到 3 位)、汉字(1 到 3 位)或百分号",几个限定都是必要的。上限 3 是防止正则把紧随其后的量词或连接字吞进单位里,得到"毫米厚"这种查不到映射的键;百分号写成%%不是笔误,因为这条正则是用 %-格式化拼出来的,模式里的字面量%必须双写,单写会在编译期抛ValueError: unsupported format character;下限 1 更隐蔽——如果把单位组写成可以匹配零个字符,正则会在数字后先接受一个空单位,拉丁单位(mm、kg)整段被漏掉,而中文单位因为能匹配汉字看起来一切正常。查不到映射时按未知单位返回,不要静默返回默认量纲。

后处理:把匹配结果变成可比字段

拿到匹配片段之后,分三步收尾:判定量纲、换算到基准单位、按符号决定值落在下限还是上限。区间与单值走同一套出口,比对逻辑就不需要分支。

def to_field(match): op = (match.group("op") or "").strip() op = OP_ALIASES.get(op, op) v1 = parse_number(match.group("n1")) unit = (match.group("u1") or match.group("u2") or "").strip() info = UNIT_INDEX.get(unit.lower()) if not info: return {"raw": match.group(0), "dimension": None, "value": v1, "unit": unit, "op": op, "note": "unit-unknown"} dim, factor = info low, high = v1 * factor, v1 * factor if match.group("n2"): high = parse_number(match.group("n2")) * factor return {"raw": match.group(0), "dimension": dim, "low": low, "high": high, "op": op, "unit": unit}

百分比和温度这两类要单独打标记。百分比的基准值直接用原数即可,但"3"和"3%"在文本里外观接近,抽取时如果没有取到%,建议返回unit-unknown而不是默认按单值处理。

三条实测出来的经验

· 多值连写要单独处理。"长 3 米、宽 1.2 米"用一条正则整体匹配会把"长"当成单位的一部分。做法是按分隔符(顿号、逗号、分号)先切短语,再对每个短语单独抽值。

· 抽取结果保留原文。字段里带raw,出现争议时能立刻定位是哪一句文本被解析错了;只存数值的话,排错成本会成倍上升。

· 单位表按版本落盘。这张表一旦改动,历史抽取结果就不可比。把它连同版本号一起写成配置,比写在代码里更容易复核。

按这套实现,在一批约 400 页的工业品参数文本上跑,抽取召回接近全量,误报集中在未知单位那一类,逐条补进映射表即可收敛。

(本文由一支长期做工业文本结构化与数据质量检测的技术团队整理,欢迎同行交流指正。)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 9:08:59

16位串行DAC驱动开发:SPI时序、寄存器配置与工程避坑指南

简介&#xff1a;面向嵌入式开发者的tpc116s8设备驱动完整工程包&#xff0c;适用于需要将该控制器接入STM32F10x平台的场景。压缩包共126个文件&#xff0c;大小2.36MB&#xff0c;以C源码&#xff08;30个.c&#xff09;与头文件&#xff08;33个.h&#xff09;为主体&#x…

作者头像 李华
网站建设 2026/10/20 9:08:45

Selenium Web自动化实战:模拟用户、元素定位与避坑指南

做Web自动化&#xff0c;不管你是写测试脚本还是搞数据采集&#xff0c;Selenium都是绕不开的那套工具。但很多人写了几百行代码&#xff0c;最后发现脚本不是今天跑不通&#xff0c;就是明天元素定位失败&#xff0c;甚至明明模拟了“点击”&#xff0c;平台还是识别出你是机器…

作者头像 李华
网站建设 2026/10/20 9:08:27

Selenium自动化如何规避网站检测?从指纹隐藏到行为模拟完整指南

用Python写Selenium自动化的人&#xff0c;几乎都会在某个时间点遇到同一个尴尬&#xff1a;本机调试时一切正常&#xff0c;脚本一旦部署出去&#xff0c;或者连续跑上几十次&#xff0c;目标网站就开始给你脸色看。轻则多出几道滑块验证码&#xff0c;重则直接把会话标记为异…

作者头像 李华
网站建设 2026/10/20 9:08:07

端到端测试编排框架tester-army实战:从跑通到跑稳的工程化指南

1. 端到端测试与 tester-army 的定位拆解1.1 为什么端到端测试总让人又爱又恨端到端测试这个词&#xff0c;做过交付的人都懂。它站在整个系统的入口&#xff0c;模拟真实用户从点击到落库的完整链路&#xff0c;一旦跑通&#xff0c;心里那块石头才算落地。可它也是 CI 流水线…

作者头像 李华
网站建设 2026/10/20 9:07:30

2026年API测试工具横评:Postman、Apifox、JMeter怎么选?

做完整套API测试工具横评&#xff0c;已经是两周前的事了&#xff0c;结果一直压在手头没整理。起因是我所在的项目组要做接口自动化体系改造&#xff0c;团队里Postman、Apifox、Apipost、JMeter都用得有人&#xff0c;经常出现同一个接口在四个工具里跑来跑去、断言逻辑各写一…

作者头像 李华
网站建设 2026/10/20 9:06:40

基于Spring Boot与若依的物联网平台V2实战:MQTT接入与设备管理

1. 项目概述与整体设计思路1.1 这个项目到底解决什么问题这两年做物联网平台的后端研发&#xff0c;最典型的场景就是&#xff1a;设备接入、指令下发、状态上报、数据可视化。如果你用Spring Boot自己从零写一套&#xff0c;设备管理、用户权限、菜单配置、操作日志、代码生成…

作者头像 李华