由于采集省市区镇数据需要对地名进行拼音转换, 由于第三方高准确度接口对 IP 进行了限制, 处理大量数据变得异常缓慢.
使用了一个折中的办法, 省市区 3 级 (3 千 +) 用高准确度接口 (几乎没有拼错的地名), 镇级(4 万 +) 用本地 HanLP 提供的接口(大部分多音字还算是能拼正确).
GitHub 源码:
另外我提供了一个临时测试服务器, 国内的但域名备案掉了走的海外线路, 仅供测试, 随时可能关闭. 测试: http://pinyin-test.haozgz.com/pinyin?txt = 重庆着陆 OK, 重力看着没有异常.
https://github.com/hankcs/HanLP 是一个优秀的开源自然语言处理工具, 提供了颇为准确的拼音转换功能. 开始本想使用更为顺手的 Node.JS 来处理, 但测试了 GitHub 上排第一的 hotoo/pinyin 库, 就是开了分词, 对多音字支持也不太理想. 最后决定使用 HanLPPython 版 https://github.com/hankcs/pyhanlp 来进行转换, 但是这个库对地名的支持还是有限, 都字地名很多转换成 dou 囧, 不过在同类型里面算是最好的.
新手第一次正经写 Python 代码, 刚开始电脑上以前装的 Python 2.7.x, 就按 Python2 写了一个服务, 发现字符串编码需要转来转去, 够折腾的, 但好歹功能没问题. 后面因为这个编码问题, 越想越觉得不舒服, 一个优秀的语言哪有这么折腾的, 就改成了 3.6.x(Miniconda 里面 3.7.x 环境 SSL 有问题, pip 用不了, 不愿折腾了). 最终结果就是仅支持 Python3, 没有了奇异的代码.
http.server 的简单上手
创建服务
网上有很多例子, 也都非常简单, 这个玩意也很容易上手. 几行代码就能创建一个 HTTP 服务功能.
- from http.server import HTTPServer, BaseHTTPRequestHandler
- class HttpHandler(BaseHTTPRequestHandler):
- def do_GET(self):
- #服务功能实现
- def do_POST(self):
- #服务功能实现
- httpd = HTTPServer(('127.0.0.1', 9527), HttpHandler)
- httpd.serve_forever()
和 Node.JS 的 http 模块写出来的服务一样简洁. 只监听 127.0.0.1 省的配置防火墙, 只让本机访问.
接收请求参数
一个 web API 不仅仅有 path, 还要有 query string x-www-form-urlencoded 请求参数支持. urllib.parse.parse_qs 能轻松解析出请求数据.
- class HttpHandler(BaseHTTPRequestHandler):
- def do_GET(self):
- path,args=urllib.parse.splitquery(self.path)
- self._response(path, args)
- def do_POST(self):
- args = self.rfile.read(int(self.headers['content-length'])).decode("utf-8")
- self._response(self.path, args)
- def _response(self, path, args):
- if args:
- args=urllib.parse.parse_qs(args).items()
- args=dict([(k,v[0]) for k,v in args])
- else:
- args={}
- # 轻松就解析出了请求参数对象
执行实际业务逻辑
有了 path 和 args, 就直接可以上业务逻辑了. 具体这个请求是要处理什么功能, 根据 path 来判断一下即可, 功能需要的参数从 args 里面取.
整个拼音服务完整代码
- from pyhanlp import *
- import traceback
- import JSON
- import urllib
- from http.server import HTTPServer, BaseHTTPRequestHandler
- class HttpHandler(BaseHTTPRequestHandler):
- def _response(self, path, args):
- code=200
- rtv={'c':0,'m':'','v':''}
- try:
- if args:
- args=urllib.parse.parse_qs(args).items()
- args=dict([(k,v[0]) for k,v in args])
- else:
- args={}
- # ****************************************
- # *************** 页面开始 *****************
- # ****************************************
- # ==>
- if path=="/":
- rtv["v"]="服务器已准备好"
- # ==>
- elif path=="/pinyin":
- txt=args.get("txt","")
- pinyin_list = HanLP.convertToPinyinList(txt)
- list=[]
- Pinyin=JClass("com.hankcs.hanlp.dictionary.py.Pinyin")
- for i in range(pinyin_list.size()):
- pinyin=pinyin_list[i]
- if pinyin==Pinyin.none5:
- list.append('F'+txt[i])
- else:
- list.append(pinyin.getPinyinWithoutTone())
- rtv["v"]=list
- # ****************************************
- # **************** 页面结束 ****************
- # ****************************************
- else:
- code=404
- rtv["c"]=404
- rtv["m"]="路径"+path+"不存在"
- except Exception as e:
- rtv["c"]=1
- rtv["m"]='服务器错误:'+str(e)+"\n"+traceback.format_exc()
- try:
- rtv=JSON.dumps(rtv,ensure_ascii=False)
- except Exception as e:
- rtv={'c':2,'m':'服务器返回数据错误:'+str(e)+"\n"+traceback.format_exc(),'v':''}
- rtv=JSON.dumps(rtv,ensure_ascii=False)
- self.send_response(code)
- self.send_header('Content-type', 'text/json; charset=utf-8')
- self.send_header('Access-Control-Allow-Origin', '*')
- self.end_headers()
- self.wfile.write(rtv.encode())
- def do_GET(self):
- path,args=urllib.parse.splitquery(self.path)
- self._response(path, args)
- def do_POST(self):
- args = self.rfile.read(int(self.headers['content-length'])).decode("utf-8")
- self._response(self.path, args)
- httpd = HTTPServer(('127.0.0.1', 9527), HttpHandler)
- httpd.serve_forever()
HanLP 的安装
由于 HanLP 是一个 java 库, 因此使用了 pyhanlp 这个 Python 包, 底层还是用 jpype1 来调用 HanLP 的 java 接口. Windows 上还是根据 wiki 来完成的安装, 这库给予了蛮实用的安装方法.
本方法只在 Windows 7 环境下运行过, 其他环境自测.
:: 安装一个有效的版本
> conda create -n python364 python=3.6.4
:: 切换版本
> activate python364
:: 安装 jpype1
> conda install -c conda-forge jpype1
:: 安装 pyhanlp
> pip install pyhanlp
:: 执行一遍, 会提示要下载哪些东西
> hanlp
:: 环境都搞定后就可以运行服务了
> python server.py
[1] 安装 Miniconda
conda 版本随意, https://conda.io/miniconda.html
[2] 安装 pyhanlp
参考: https://github.com/hankcs/pyhanlp/wiki/Windows
这个库是 java 库, 需要有 java 环境, 如果没有装过, 需要先安装 java: 下载 JDK
测试发现 python3.7.1 Windows 下 ssl 有问题无法安装, conda 切换成 python 3.6.4 测试安装正常
安装好后运行一下 hanlp 命令, 会提示下载, 看第 3 步
如果出现 XXX.dll 什么的问题, 可能是 C++ 运行库缺失, 安装微软常用运行库合集应该能够解决, 我在 Windows Server 2012 上使用时出现此问题, 装上就 OJBK 了.
[3] 下载字典和 jar
参考半自动配置: .
字典和 jar 存放目录一般在 Miniconda3[\envs\py36]\Lib\site-packages\pyhanlp\static .
jar 直接下载最新 releases .
字典最好直接 clone 仓库 / data 目录最新版本(用 SVN 下载速度快很多, 无需 model 数据), 一样的在存储目录内放一个 data 文件夹, releases 对 bug 处理稍微滞后一点.
另外需要修改 hanlp.properties, 给 root 赋值为当前目录完整路径.
SVN: https://github.com/hankcs/HanLP/trunk/data
[4] 运行
python server.py
[5] 浏览器访问
http://127.0.0.1:9527/pinyin?txt = 要拼的文字
比如: 拼音. m 返回结果 {c:0,m:"",v:["pin","yin","F.","Fm"]},c=0 时代表正常, 其他代表出错, m 为错误原因, 拼音如果是字母符号会用 F 打头.
最后
GitHub 源码: .
如果这个库有帮助到您, 请 Star 一下.
来源: https://www.cnblogs.com/xiangyuecn/p/10612688.html