问题背景
某些数据因为要对外提供,所以对敏感信息要脱敏,电话号码、身份证等信息有规则可以匹配,但是姓名就比较难,特别是在一个长文本中提取姓名然后做到精准脱敏,就有点难度,不过现在大模型发展比较快,利用大模型来姓名提取就比较好用。
通过咨询市面上的大模型如何选择可以使用的姓名提取模型,并进行使用和比对,敲定了一个落地方案,就是使用RaNER(Robust Named Entity Recognition)模型,这是达摩院专为中文优化的命名实体识别框架,在准确率、鲁棒性和部署便捷性方面均表现突出,特别适合中文姓名识别场景。
现在介绍一下该模型的安装测试,供大家参考使用。
RaNER模型使用流程
我已经在本机电脑安装了Conda环境,所以测试环境就用Conda简单方便。
创建环境
conda创建虚拟环境
conda create -n chinese-ner python=3.9
conda activate chinese-ner
安装核心依赖
pip install modelscope transformers torch numpy
代码需要使用到依赖,安装一下
pip install addict==2.4.0
pip install datasets==2.21.0
pip install Pillow
pip install simplejson
pip install sortedcontainers
测试代码
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
# 初始化RaNER模型管道
ner_pipeline = pipeline(
task=Tasks.named_entity_recognition,
model='damo/nlp_raner_named-entity-recognition_chinese-base-news'
)
# 测试示例
text = "马云在杭州阿里巴巴总部宣布,公司将在上海设立新的研发中心,并与北京大学展开合作。"
result = ner_pipeline(input=text)
# 提取姓名实体
person_entities = [entity for entity in result['output'] if entity['type'] == 'PER']
print("识别到的姓名:", [entity['span'] for entity in person_entities])
返回结果
识别到的姓名: ['马云']
因为部分数据文本中存在HTML标签,所以还需要去除HTML标签,需要加入处理文本的函数。
安装beautifulsoup4来处理标签
pip install beautifulsoup4
测试代码
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from bs4 import BeautifulSoup
import re
# ==========================================
# 1. 初始化 NER 模型
# ==========================================
print("正在加载模型,请稍候...")
ner_pipeline = pipeline(
task=Tasks.named_entity_recognition,
model='damo/nlp_raner_named-entity-recognition_chinese-base-news'
)
# ==========================================
# 2. 定义 HTML 清洗函数
# ==========================================
def clean_html(html_text):
"""
使用 BeautifulSoup 去除 HTML 标签,并规范化空白字符
"""
# 使用 'html.parser' 解析器
soup = BeautifulSoup(html_text, 'html.parser')
# 获取文本内容
text = soup.get_text(separator=' ')
# 简单的后处理:去除多余的空行和空格
# \s+ 匹配所有空白字符(空格、换行、制表符),替换为单个空格
text = re.sub(r'\s+', ' ', text).strip()
return text
# ==========================================
# 3. 定义长文本分段函数
# ==========================================
def split_text(text, max_length=500):
"""
将长文本按句子分割,避免超过模型限制 (512)
"""
# 按中文句号、感叹号、问号分割,保留分隔符
sentences = re.split(r'(?<=[。!?])', text)
chunks = []
current_chunk = ""
for sentence in sentences:
if len(current_chunk) + len(sentence) <= max_length:
current_chunk += sentence
else:
if current_chunk:
chunks.append(current_chunk)
current_chunk = sentence
if current_chunk:
chunks.append(current_chunk)
return chunks
# ==========================================
# 4. 你的原始 HTML 数据
# ==========================================
text = """
<div style="font-family: 宋体;">
<h2>中标通知书</h2>
<p>项目编号:ZJ-2026-TEST</p>
<p>项目名称:非常智慧的改造工程</p>
<hr>
<table border="1" style="border-collapse: collapse; width: 100%;">
<thead>
<tr>
<th>中标单位</th>
<th>项目经理</th>
<th>中标金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>浙江大聪明有限公司</td>
<td>章天</td>
<td>1250.00万元</td>
</tr>
</tbody>
</table>
<p>
特此通知。
<br>
招标人代表:<b>李大牛</b>
<br>
技术顾问:<b>陈三明</b>
</p>
</div>
"""
# 1. 先清洗数据
cleaned_text = clean_html(text)
# 2. 再将清洗后的文本传入模型
result = ner_pipeline(input=cleaned_text)
# 提取姓名实体
person_entities = [entity for entity in result['output'] if entity['type'] == 'PER']
print("识别到的姓名:", [entity['span'] for entity in person_entities])
返回结果
识别到的姓名: ['章天 ', '李大牛', '陈三明']
传统方法 vs RaNER 对比
你可以直接加入这段,提升文章深度:
- Jieba 分词:依赖词典,无法理解上下文,复姓、生僻名、昵称容易漏识,误报率高,不适合脱敏。
- 正则表达式:只能匹配固定规则姓名,无法处理真实文本中的复杂情况,长文本基本不可用。
- 大模型:基于深度学习,具备上下文理解能力,鲁棒性强,支持生僻姓名、复姓、长文本、HTML 文本,识别精度高,是企业级脱敏的最优选择。
总结
在中文长文本的姓名提取与脱敏场景中,传统基于规则、词典的方法(如正则、Jieba 词性标注)存在明显短板:漏识别、误识别、无法处理复杂文本、不支持 HTML 格式、难以适应真实业务数据。这些问题会直接导致脱敏不彻底,带来数据安全风险。
通过实测对比,达摩院的 RaNER 模型 在中文命名实体识别任务中表现出显著优势:识别精度高、鲁棒性强、支持长文本推理、兼容 HTML 等非结构化数据、部署简单、运行稳定。它能够在复杂业务文档、公告、合同、报告等真实场景中,精准提取人名实体,为后续的敏感信息脱敏提供可靠支撑。
本文提供的 Conda 环境部署、HTML 清洗、长文本分段等完整方案,已经可以直接应用于实际业务,实现开箱即用、低成本、高可靠的中文姓名提取服务。