一、基本信息
1.1 功能目录
:::success 🎯 从业以来,处理过的小场景,大部分来自GitHub的大神,结合自己的理解和项目需求进行修改,争取不做gitclone 工程师,涉及内容包括但不限于: 中英文敏感词、暴恐词表、繁简体转换、英文模拟中文发音、😍🤪 :::
二、项目简记
2.1 敏感词检测
2.2 车牌抽取
基于规则抽取车牌号实体 https://github.com/PyUnit/pyunit-plate
2.3 时间抽取
用于句子中时间词的抽取和转换, 主要基于Time_NLP做了部分优化 https://github.com/xiaoxiong74/Time-Extractor
一般处理文本,例如新闻,对于包含多个时间,需要有一定的策略判断。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
from flask.globals import g
import time
from timing.TimeNormalizer import TimeNormalizer # 引入包
tn = TimeNormalizer()
TARGET_REGULAR = "[u'报'|u'报道']"
'''利用标点符号,将文章进行短句切分处理'''
def seg_short_content(content):
return [sentence for sentence in re.split(r'[,,??!!。;;\n\r\t ]', content) if sentence]
'''选择最早的规范的时间'''
def selectEarliestTime(tu_arr):
res = []
# restime = tu_arr[0].time.format("YYYY-MM-DD HH:mm")
# timegap = time.time()-tu_arr[0].time.timestamp
for tu in tu_arr[1:]:
# print("deng,", tu.time.format("YYYY-MM-DD HH:mm"))
if tu.time.timestamp == 0:
continue
if not re.findall("\d+", tu.exp_time): # 去掉早上、目前等模糊时间
continue
rtime = sorted(res, key=lambda tu: tu.time.format("YYYY-MM-DD HH:mm"))
# print("sort for ealiest time: ", rtime)
for rt in rtime:
if rt.norm_tunit[3] != -1: #如果时间有小时,那么就提前
rtime.lappend(rt)
if not rtime:
return selectIntegralTime(tu_arr)
return rtime[0].time.format("YYYY-MM-DD HH:mm")
'''选择描述最为完整的时间'''
def selectIntegralTime(tu_arr):
res = []
best_count = 0
for tu in tu_arr:
if tu.time.timestamp != 0:
tmp_count = 0
for i in range(0, 6): # 年、月、日、时、分、秒
if tu.norm_tunit[i] != -1:
tmp_count += 1
if tmp_count > best_count:
res = [tu.time.format("YYYY-MM-DD HH:mm")]
best_count = tmp_count
elif tmp_count == best_count:
res.append(tu.time.format("YYYY-MM-DD HH:mm"))
if not res:
return tu_arr[0].time.format("YYYY-MM-DD HH:mm")
rtime = sorted(res) # 填充的槽值相同,则选择最早的时间
return rtime[0]
'''选择离主干句子最近的时间'''
def selectNearestTime(tu_arr, text, titles):
if not titles:
return tu_arr[0].time.format("YYYY-MM-DD HH:mm")
rt = ""
best_dist = len(text)
s_title = text.find(titles[0][0])
t_title = s_title + len(titles[0][0])
print(titles[0][0], s_title, t_title)
for tu in tu_arr:
if tu.time.timestamp == 0:
continue
s_time = text.find(tu.exp_time)
t_time = s_time + len(tu.exp_time)
if s_time >= s_title and t_time <= t_title:
return tu.time.format("YYYY-MM-DD HH:mm")
if not re.findall("\d+", tu.exp_time) or tu.norm_tunit[3] == -1: # 需要明确是几时
continue
if s_time >= t_title:
tmp = abs(s_time - t_title)
if t_time <= s_title:
tmp = abs(s_time - t_title)
if tmp < best_dist:
best_dist = tmp
print(tu.exp_time, s_time, t_time, best_dist)
rt = tu.time.format("YYYY-MM-DD HH:mm")
print(rt, best_dist)
if not rt:
rt = tu_arr[0].time.format("YYYY-MM-DD HH:mm")
return rt
'''正则去掉报道时间'''
def delReportTime(text):
rtime = []
subsents = seg_short_content(text)
if subsents:
if re.findall(TARGET_REGULAR + "+$", "".join(subsents[0])) != []:
rtime = tn.parse(target=subsents[0])
if rtime:
subsents.pop(0)
if not rtime and len(subsents) > 1:
if re.findall(TARGET_REGULAR + "+$", "".join(subsents[1])) != []:
rtime = tn.parse(target=subsents[0] + "," + subsents[1])
if rtime:
subsents.pop(1)
subsents.pop(0)
try:
text = ",".join(subsents)
if rtime:
rt = tn.parse(target=text, timeBase=rtime[-1].time.format('YYYY-MM-DD HH:mm:ss'))
if not rt:
rt = rtime
else:
rt = tn.parse(target=text)
except:
print("Error:时间格式不符合规范!")
rt = []
return rt
'''根据标题选择时间'''
def getTimewithTitle(text, titles):
res = tn.parse(target=text)
if len(res) == 0:
rtime = ""
elif len(res) == 1:
rtime = res[0].time.format("YYYY-MM-DD HH:mm")
else:
rtime = selectNearestTime(res, text, titles) # 选择离标题最近的时间
return rtime
def getTime4resp(text):
text = text.replace(" ", ",") # [2021/2/2 22:30] 替换时间的空格
# text=re.sub("[a-zA-Z]+://[^\s]*[.com|.cn|.html]","",text)
res = tn.parse(target=text) # 不去报道时间
# res = delReportTime(text) # 去掉报道时间
if len(res) == 0:
rtime = ""
elif len(res) == 1:
rtime = res[0].time.format("YYYY-MM-DD HH:mm")
else:
# rtime = selectIntegralTime(res) # 选择最完整的时间
rtime = selectEarliestTime(res) # 选择最早的符合规范的时间
return rtime
2.4 地址抽取
PyUnit-Address https://github.com/PyUnit/pyunit-address
pip install pyunit-address
2.5 标题抽取/摘要生成/文章缩减
TextRank算法可以用来从文本中提取关键词和摘要(重要的句子)。TextRank4ZH是针对中文文本的TextRank算法的python算法实现。https://github.com/letiantian/TextRank4ZH
2.6 中文纠错
包含n-gram以及双向lstm语言模型 https://github.com/zedom1/error-detection
pycorrector https://github.com/shibing624/pycorrector
中文文本纠错任务,常见错误类型包括:
- 谐音字词,如 配副眼睛-配副眼镜
- 混淆音字词,如 流浪织女-牛郎织女
- 字词顺序颠倒,如 伍迪艾伦-艾伦伍迪
- 字词补全,如 爱有天意-假如爱有天意
- 形似字错误,如 高梁-高粱
- 中文拼音全拼,如 xingfu-幸福
- 中文拼音缩写,如 sz-深圳
-
2.7 繁简转换
python https://github.com/Tim9Liu9/py_change_code
SimpleChinese2 https://github.com/chenmingxiang110/SimpleChinese2 文字预处理
- 繁体简体转换
- 拼音文字转换
- 姓名生成
三、工具记录
3.1 paddleNLP
https://github.com/PaddlePaddle/PaddleNLP
PaddleNLP是飞桨自然语言处理开发库,具备易用的文本领域API,多场景的应用示例、和高性能分布式训练三大特点,旨在提升开发者在文本领域的开发效率,并提供丰富的NLP应用示例。
以python 作为镜像,安装PaddleNLP 的docker 镜像将近1.8G。
在命名实体识别方面,该工具非常好。 ```python from paddlenlp import Taskflow
中文分词
seg = Taskflow(“word_segmentation”) seg(“第十四届全运会在西安举办”)
[‘第十四届’, ‘全运会’, ‘在’, ‘西安’, ‘举办’]
词性标注
tag = Taskflow(“pos_tagging”) tag(“第十四届全运会在西安举办”)
[(‘第十四届’, ‘m’), (‘全运会’, ‘nz’), (‘在’, ‘p’), (‘西安’, ‘LOC’), (‘举办’, ‘v’)]
命名实体识别
ner = Taskflow(“ner”) ner(“《孤女》是2010年九州出版社出版的小说,作者是余兼羽”)
[(‘《’, ‘w’), (‘孤女’, ‘作品类实体’), (‘》’, ‘w’), (‘是’, ‘肯定词’), (‘2010年’, ‘时间类’), (‘九州出版社’, ‘组织机构类’), (‘出版’, ‘场景事件’), (‘的’, ‘助词’), (‘小说’, ‘作品类概念’), (‘,’, ‘w’), (‘作者’, ‘人物类概念’), (‘是’, ‘肯定词’), (‘余兼羽’, ‘人物类实体’)]
句法分析
ddp = Taskflow(“dependency_parsing”) ddp(“9月9日上午纳达尔在亚瑟·阿什球场击败俄罗斯球员梅德韦杰夫”)
[{‘word’: [‘9月9日’, ‘上午’, ‘纳达尔’, ‘在’, ‘亚瑟·阿什球场’, ‘击败’, ‘俄罗斯’, ‘球员’, ‘梅德韦杰夫’], ‘head’: [2, 6, 6, 5, 6, 0, 8, 9, 6], ‘deprel’: [‘ATT’, ‘ADV’, ‘SBV’, ‘MT’, ‘ADV’, ‘HED’, ‘ATT’, ‘ATT’, ‘VOB’]}]
情感分析
senta = Taskflow(“sentiment_analysis”) senta(“这个产品用起来真的很流畅,我非常喜欢”)
[{‘text’: ‘这个产品用起来真的很流畅,我非常喜欢’, ‘label’: ‘positive’, ‘score’: 0.9938690066337585}]
<a name="eJwA0"></a>
## 3.3 synonyms
[https://github.com/chatopera/Synonyms](https://github.com/chatopera/Synonyms)<br />提取关键词
```python
import synonyms
print("人脸: ", synonyms.nearby("人脸"))
print("识别: ", synonyms.nearby("识别"))
print("NOT_EXIST: ", synonyms.nearby("NOT_EXIST"))
synonyms.nearby(人脸, 10) = (
["图片", "图像", "通过观察", "数字图像", "几何图形", "脸部", "图象", "放大镜", "面孔", "Mii"],
[0.597284, 0.580373, 0.568486, 0.535674, 0.531835, 0.530
095, 0.525344, 0.524009, 0.523101, 0.516046])
句子相似度,领域数据亲测效果不佳
sen1 = "发生历史性变革"
sen2 = "发生历史性变革"
r = synonyms.compare(sen1, sen2, seg=True)
旗帜引领方向 vs 道路决定命运: 0.429
旗帜引领方向 vs 旗帜指引道路: 0.93
发生历史性变革 vs 发生历史性变革: 1.0
打印近义词 ```python synonyms.display(“飞机”) ‘飞机’近义词:
- 飞机:1.0
- 直升机:0.8423391
- 客机:0.8393003
- 滑翔机:0.7872388
- 军用飞机:0.7832081
- 水上飞机:0.77857226
- 运输机:0.7724742
- 航机:0.7664748
- 航空器:0.76592904
- 民航机:0.74209654
获得词向量,该向量为 numpy 的 array,当该词语是未登录词时,抛出 KeyError 异常。
```python
>>> synonyms.v("飞机")
array([-2.412167 , 2.2628384 , -7.0214124 , 3.9381874 , 0.8219283 ,
-3.2809453 , 3.8747153 , -5.217062 , -2.2786229 , -1.2572327 ],
dtype=float32)
中文分词
synonyms.seg("中文近义词工具包")
>>>(['中文', '近义词', '工具包'], ['nz', 'n', 'n'])
提取关键词
keywords = synonyms.keywords("9月15日以来,台积电、高通、三星等华为的重要合作伙伴,只要没有美国的相关许可证,都无法供应芯片给华为,而中芯国际等国产芯片企业,也因采用美国技术,而无法供货给华为。目前华为部分型号的手机产品出现货少的现象,若该形势持续下去,华为手机业务将遭受重创。")
英文状态下,输入
:::success
之后按下回车键,可以输入绿色的提示区块~
输入
:::danger
之后按下回车键。可输入红色的提示区块,其他可以点击了解更多
:::danger 💪
:::