当前位置: 首页 > news >正文

文本中地理位置提取方法—正则和NLP模型

这里写目录标题

    • 一、提取地址列后12个字
    • 二、正则表达式删除不需要的文本
    • 三、保留关键字并删除之后的字
    • 四、相似度计算,查重
    • 五、去重

大量的文本中识别数据,要充分考虑效率和准确率。本文的方案是通过正则和NLP门址模型联合识别的方案。
首先利用现有粗略地址将包含有地址和事由的长文本缩短到短文本,在用正则匹配出地址,然后通过匹配出地址的长度和其他规则发现没有正确识别的地址。对于这部分地址通过MGeo模型高精度实现文本中地址识别地址,然后对识别后的地址做各行间的相似度计算,对于相似的字符串,把出现次数少的替换成出现次数多的。
通过MGeo模型高精度实现文本中地址识别

一、提取地址列后12个字

数据有个粗略地址和详细描述两列,通过提取地址列后12个字,一方面可以去除地址内容之前的数据,减少正则匹配,另一方面为Mgeo nlp模型处理做了截断提高精度和效率。

import pandas as pd# 文件路径
path = r"D:\data\rs\结果v6.xlsx"
path1 = r"D:\data\rs\结果v620.xlsx"# 要提取的字符数
N = 20# 读取数据并处理空值
df = pd.read_excel(path)
df['工单内容'] = df['工单内容'].fillna('').astype(str)# 定义提取函数
def extract_content(row, n):try:address = row['案发地址']content = row['工单内容']if not isinstance(address, str) or not isinstance(content, str):return ''start = content.find(address)if start == -1:return ''start += len(address)return content[start:start+n]except Exception as e:print(f"Error processing row {row.name}: {e}")return ''# 使用 lambda 把参数 n 传进去
df['提取内容'] = df.apply(lambda x: extract_content(x, N), axis=1)# 保存结果
df.to_excel(path1, index=False)

二、正则表达式删除不需要的文本

删除 匹配目标词 + 后续内容
1、数字 及之后的去掉(目的是去掉xx楼)
2、”*“ 及之后的去掉(目的是去掉xx楼)
3、把A-Z字母及之后的去掉(目的是去掉xx小区A区)
4、“村的住户”、“的村民”字符串及之后去掉(后面肯定不是地址)
5、“(无门牌号”及之后的去掉
6、“,”及后面的去掉
7、“的住户”和“住户”和“的业主”及之后面去掉
8、“回迁楼”、"民房"及后面的去掉
9、"最"及后面的去掉(应为后面是最东边之类的)
10、”号楼“及后面的去掉
11、删除 “(”及其后的内容
12、 删除 “的”及其后的内容
13、 删除 “附近”及其后的内容
14、删除 三期 关键字及之后的 其中三 可以替换为任意的汉字数字(注意:由于这条规则是要匹配 期 前面的一个变量,非常容易错,使用贪婪匹配会将前面联系的汉字都匹配进去,使用非贪婪只能匹配到 期 一个字)

 text = re.sub(r'([一二三四五六七八九十十一十二十三十四十五十六十七十八十九二十])期', '小区', text)

15 . 删除 “村民、居民、人”及其后的内容

三、保留关键字并删除之后的字

保留关键字”小区“并删除之后的内容

四、正则逻辑优化

  1. 优先保留“小区”并删除之后的,(防止被后续规则误删)

  2. 处理特定结构(村的村民、住户,回迁楼等)

  3. 处理期数(三期),将 三期替换为小区(不能删除之后的,因为口语中可能将小区用xx期表示)

  4. 符号处理(*,逗号,括号)

  5. 处理电话、安装、供暖等关键词

  6. 处理住户、业主、村民、民房等

  7. 处理最、的、附近等

  8. 处理数字、字母

调整原则:
减少误删除,先处理最确定的原则,缩小文本长度,减少后面规则匹配上的概率,避免误删除

  1. 优先保留小区信息 (防止被后续规则误删)

具体模式优先:越具体的匹配规则越先执行

格式清理前置:符号类清理早于文字内容清理

保留操作最后:关键保留操作放在处理链末端

通用模式置后:宽泛的.*模式放在处理链后部

#
import pandas as pd
import re# 文件路径
path = r"D:\data\rs\结果v620.xlsx"
output_path = r"D:\data\rs\结果v620_地址清洗_v3.xlsx"# 读取数据
df = pd.read_excel(path)# 复制原始列用于处理
df['提取地址'] = df['提取内容'].astype(str).copy()def clean_address(text):text = str(text)# 0.清理期数描述(三期、四期等),这个容易错,因为是向前匹配容易把之前联系的小区名匹配进去并替换掉text = re.sub(r'([一二三四五六七八九十十一十二十三十四十五十六十七十八十九二十])期', '小区', text)# 0 。保留小区  (防止被后续规则误删)text = re.sub(r'小区.*', '小区', text)# 1. 特定结构清理(村、回迁楼等)text = re.sub(r'的村民.*', '', text)text = re.sub(r'(无门牌号.*', '', text)text = re.sub(r'回迁楼.*', '', text)# 3. 特殊符号清理(*,逗号,括号)text = re.sub(r'\*.*', '', text)text = re.sub(r',.*', '', text)text = re.sub(r'(.*', '', text)# 4. 业务相关关键词清理(安装、供暖、电话等)text = re.sub(r'安装.*', '', text)text = re.sub(r'供暖.*', '', text)  text = re.sub(r'做.*', '', text)text = re.sub(r'电话.*', '', text)text = re.sub(r'租.*', '', text)text = re.sub(r'名称.*', '', text)  # 5. 清理住户/业主/居民描述text = re.sub(r'(的住户|住户|的业主).*', '', text)text = re.sub(r'村民.*', '', text)text = re.sub(r'居民.*', '', text)text = re.sub(r'人.*', '', text)text = re.sub(r'附近.*', '', text)text = re.sub(r'民房.*', '', text)# 6. 通用描述清理(最、的)text = re.sub(r'最.*', '', text)text = re.sub(r'的.*', '', text)  # 注意这个模式较宽泛,放在后面# 7. 基础元素清理(数字、字母)text = re.sub(r'\d+.*', '', text)text = re.sub(r'[A-Za-z].*', '', text)return text.strip()# 应用清理函数
df['提取地址'] = df['提取地址'].apply(clean_address)# 保存结果
df.to_excel(output_path, index=False)print("地址清洗完成,已保存至:", output_path)

优化补充:

1、对村村 替换为村 将 小区小区(xx小区三期替换来的) 替换为 小区

四、相似度计算,查重

不适用编辑距离,太慢。利用行政区分组减少对比空间,然后用近似算法降低计算量。
通过MinHash+LSH技术高效检测地址相似性。首先清洗地址文本并提取字符级N-Gram特征,每个地址转换为MinHash签名。按行政区划建立局部敏感哈希(LSH)索引,将相似度超过阈值的地址映射到相同哈希桶。通过多进程并行处理各行政区,对每个地址查询LSH获得候选集,排除自身后生成相似地址组。最终输出结构化的"行政区-原地址-相似地址列表"结果,实现大规模地址数据的快速相似聚类。

#
import pandas as pd
import re
from datasketch import MinHash, MinHashLSH
import multiprocessing as mp# --------------------------------------
# 配置参数
# --------------------------------------
INPUT_PATH = r"D:\data\rs\合并结果12.xlsx"
ADDR_COLUMN = '具体地址'    # 要处理的详细地址列
REGION_COLUMN = '案发地址'  # 行政区划列
OUTPUT_PATH = r"D:\data\rs\d.xlsx"
N_GRAM = 3                # N-Gram长度
THRESHOLD = 0.7           # 相似度阈值
NUM_PERM = 128            # MinHash精度参数# --------------------------------------
# 预处理函数
# --------------------------------------
def preprocess(text):"""地址标准化"""text = re.sub(r'[^\w\u4e00-\u9fff]', '', text)  # 去除非中文字符return text.strip()def generate_ngrams(text, n=3):"""生成字符级N-Gram"""return [text[i:i+n] for i in range(len(text)-n+1)]# --------------------------------------
# 核心处理函数(每个行政区独立处理)
# --------------------------------------
def process_region(region_data):"""处理单个行政区的地址相似性"""region_name, addresses = region_datalsh = MinHashLSH(threshold=THRESHOLD, num_perm=NUM_PERM)address_dict = {}minhash_dict = {}  # 存储MinHash对象results = []# 构建当前行政区的LSH索引for idx, addr in enumerate(addresses):processed = preprocess(addr)ngrams = generate_ngrams(processed, N_GRAM)mh = MinHash(num_perm=NUM_PERM)for gram in ngrams:mh.update(gram.encode('utf-8'))lsh.insert(idx, mh)address_dict[idx] = addrminhash_dict[idx] = mh  # 保存MinHash对象# 查询相似对(使用正确的MinHash对象)for idx in address_dict:mh = minhash_dict[idx]candidates = lsh.query(mh)candidates = [c for c in candidates if c != idx]if candidates:original = address_dict[idx]similars = list(set(address_dict[c] for c in candidates))results.append((region_name, original, ', '.join(similars)))return results# --------------------------------------
# 主流程
# --------------------------------------
if __name__ == '__main__':# 读取数据并按行政区划分组df = pd.read_excel(INPUT_PATH)df[ADDR_COLUMN] = df[ADDR_COLUMN].astype(str)grouped = df.groupby(REGION_COLUMN)[ADDR_COLUMN].unique()# 多进程并行处理每个行政区with mp.Pool(mp.cpu_count()) as pool:all_results = pool.map(process_region, grouped.items())# 整合结果final_data = []for region_results in all_results:final_data.extend(region_results)# 保存结果result_df = pd.DataFrame(final_data, columns=['行政区', '原地址', '相似地址列表'])result_df.to_excel(OUTPUT_PATH, index=False)print(f"处理完成!发现相似组: {len(final_data):,}")

五、去重

要求生成一张新表,
d表是上一部生产的相似地址清单表。合并结果12表是地址源表。

1、读取"D:\data\rs\后处理\合并结果12.xlsx" ,统计具体地址列每个内容重复的个数
2、读取"D:\data\rs\后处理\d.xlsx" 里面有原地址和相似地址列表
3、对"D:\data\rs\后处理\d.xlsx" 每一行,读取”相似地址列表“列形成成一个列表,对列表中的每个元素 与"D:\data\rs\后处理\d.xlsx" 原地址列的内容进行比较,比较的原则为 “D:\data\rs\后处理\合并结果12.xlsx"的这两个元素的重复个数
4、在"D:\data\rs\后处理\合并结果12.xlsx"中将重复个数少的替换成多的。
5、遍历"D:\data\rs\后处理\d.xlsx” 每一行,并在"D:\data\rs\后处理\合并结果12.xlsx"完成替换后形成新表

数据量大使用polars库来进行

import polars as pldef process_data():# 读取原始数据并统计频次original_df = pl.read_excel(r"D:\data\rs\后处理\合并结果12.xlsx")count_df = original_df.group_by("具体地址").agg(pl.len().alias("出现次数"))# 读取相似地址表similar_df = pl.read_excel(r"D:\data\rs\后处理\d.xlsx").with_columns(pl.col("相似地址列表").str.split(", "))# 创建地址频次字典count_dict = dict(zip(count_df["具体地址"], count_df["出现次数"]))# 生成替换规则replacement_rules = {}for row in similar_df.iter_rows(named=True):# 获取当前组所有地址group_addresses = [row["原地址"]] + row["相似地址列表"]# 排除不存在的地址valid_addresses = [addr for addr in group_addresses if addr in count_dict]if not valid_addresses:continue# 找出频次最高的地址max_count = max(count_dict[addr] for addr in valid_addresses)candidates = [addr for addr in valid_addresses if count_dict[addr] == max_count]target = candidates[0]  # 频次相同取第一个# 生成替换规则for addr in group_addresses:if addr == target or addr not in count_dict:continue# 保留最大频次规则current_rule = replacement_rules.get(addr, addr)current_count = count_dict.get(current_rule, 0)if count_dict[target] > current_count:replacement_rules[addr] = target# 应用替换规则new_df = original_df.with_columns(pl.col("具体地址").replace(replacement_rules, default=pl.col("具体地址")))# 保存结果new_df.write_excel(r"D:\data\rs\后处理\合并结果_标准化.xlsx")print("处理完成,生成标准化地址表")if __name__ == "__main__":process_data()

相关文章:

  • 吴恩达深度学习作业 RNN模型——字母级语言模型
  • Web 应用服务器:功能、类型与核心作用全解析
  • 写了个脚本将pdf转markdown
  • 题解传送门
  • 2025年- H18-Lc126-54.螺旋矩阵(矩阵)---java版
  • 【c++】【STL】priority_queue详解
  • Git 完整教程:初学者分步指南
  • python数据分析(八):Pandas 文本数据处理
  • 安卓游戏APK文件解密与编辑的完整攻略
  • 【Bootstrap V4系列】 学习入门教程之 组件-警告框(Alert)
  • 测试——用例篇
  • linux下抓包工具--tcpdump介绍
  • Kotlin Flow流
  • VulnHub-DC-2靶机
  • 父子组件双向绑定
  • 【单片机数码管实现第一位开始走0~9,1s后第二位再开始亮】2022-5-2
  • C++将整数换成分数 2024年信息素养大赛复赛 C++小学/初中组 算法创意实践挑战赛 真题详细解析
  • React useCallback函数
  • Oracle-ACL配置
  • “淘宝闪购”提前4天全量,意味着什么?
  • “矿茅”国际化才刚开始?紫金矿业拟分拆境外黄金矿山资产于港交所上市
  • 天启年间故宫“三殿”重修与晚明财政
  • 韩国前国务总理韩德洙正式宣布参加总统选举
  • 印巴局势紧张或爆发军事冲突,印度空军能“一雪前耻”吗?
  • 泽连斯基:美乌矿产协议将提交乌拉达批准
  • 摩根大通任命杜峯为亚太区副主席,加码中国市场业务布局