解决Uibot解析地址字符串中省市区的问题
python中有cpca库, 可以匹配省市区并返回. 但这个库有些老, 好多年不更新, 像深圳龙华区这些近几年升级为区的都没有. 所以需要结合正则实现.
python还有另外一个geopy库也可以实现, 但是这个库需要实时通过API读取, 还总是timeout, 所以放弃这个方案.
UiBot本来支持python扩展来解决, 但是不知为何Uibot自带的python对cpca支持有问题, 始终报错, 所以放弃, 改为Uibot调用系统命令读取打印输出的方式曲线救国.
python代码都是GPT4 Turbo写的, 自己做了小修改.
Uibot测试:
PyTools('parse_address', '广东省深圳市龙华区深圳北站')
Uibot函数:
// 由于通过uibot的python调用存在问题(import cpca始终报错), 所以通过命令行调用
// python路径直接写在tools.bat中, 使用系统where python给出的路径, 避免uibot调用错误的python版本. 此时在系统中使用Pip安装的库可以直接在这儿使用
// tools.bat直接调用执行tools.py. 具体函数在tools.py中实现
// 以Json字符串形式返回
Function PyTools(func, params)
// params支持单字符串的单参数或者数组形式的多参数
Dim Ret
If type('params') = 'string'
Ret = Sys.Command(@res"tools.bat "+func+" "+params)
else
Dim cmd = @res"tools.bat "+func
For Each p In params
cmd = cmd + " " + p
Next
Ret = Sys.Command(@res"tools.bat "+func+cmd)
End if
return JSON.Parse(Ret)
End Function
系统命令 tools.bat
和python脚本tools.py
, 放在uibot项目的res目录下. 如果不放心调用哪个版本的python,可以积极在python前面加路径.
@echo off
python.exe D:\folder\to\project\res\tools.py %1 %2 %3 %4 %5 %6 %7 %8 %9
@echo on
tool.py部分. 大多数是gpt4写的
# tools.py
import sys,re,json
import cpca
def parse_address(address):
a = ""
a1 = parse_address1(address)
a2 = parse_address2(address)
# 策略: 长度相同优选a1方法, 否则选a2
if len(a2) <= len(a1):
a = a1
else:
a = a2
# return f"{a[0]}|{a[1]}|{a[2]}"
return json.dumps(a, ensure_ascii=False)
# 采用cpca获取省市区. 好处: 不写省市区这几个字都能识别. 问题: 可能有数据库过期问题(龙华区无法识别)
def parse_address1(address):
# 使用 cpca 库解析地址并返回 DataFrame
df = cpca.transform([address])
location = df.iloc[0] # 提取第一行数据,即我们需要的地址解析结果
# 返回省市区字符串,用 "|" 分隔
# return f"{location['省']}|{location['市']}|{location['区']}"
return list(filter(None,[location['省'], location['市'], location['区']]))
# 采用正则表达式获取省市区. 好处: 不需要更新数据库. 问题: 必须有省市区这几个字.
def parse_address2(address):
# 更新省/直辖市的匹配模式以处理没有“市”字的直辖市情况
pattern = re.compile(
r'(?P<province>[^省]+省|[^自治区]+自治区|北京|天津|上海|重庆)?'
r'(?P<city>[^市]+市|[^自治州]+自治州|[^地区]+地区|[^盟]+盟)?'
r'(?P<district>[^县]+县|[^区]+区|[^旗]+旗|[^自治县]+自治县|[^林区]+林区|[^特别行政区]+特别行政区)?'
)
match = pattern.search(address)
if not match:
return "无法提取地址信息"
province, city, district = match.group('province', 'city', 'district')
# 北京、天津、上海和重庆作为直辖市,如果匹配到省份但没有匹配到市,将省份的名字赋给城市
if province in ['北京', '天津', '上海', '重庆'] and not city:
city = province
city = city + '市'
# 如果没有匹配到,则用空字符串代替
province = province if province else ''
city = city if city else ''
district = district if district else ''
# 以"|"连接非空字符串
# result = '|'.join(filter(None, [province, city, district]))
return list(filter(None,[province, city, district]))
def test_parse_address():
print(parse_address('广东省深圳市龙华区深圳北站'))
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: python tools.py parse_address 'Your Address String Here'")
sys.exit(1)
if sys.argv[1] == "parse_address":
input_address = sys.argv[2]
result = parse_address(input_address)
print(result)
elif sys.argv[1] == "test_parse_address":
test_parse_address()
else:
print('["没有正确的函数名"]')