• 使用Python的http.server实现一个简易的Web Api对外提供HanLP拼音转换服务


    由于采集省市区镇数据需要对地名进行拼音转换,由于第三方高准确度接口对IP进行了限制,处理大量数据变得异常缓慢。

    使用了一个折中的办法,省市区 3级(3千+)用高准确度接口(几乎没有拼错的地名),镇级(4万+)用本地HanLP提供的接口(大部分多音字还算是能拼正确)。

    Github源码:https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov/tree/master/assets/pinyin-python-server

    另外我提供了一个临时测试服务器,国内的但域名备案掉了走的海外线路,仅供测试,随时可能关闭。测试:http://pinyin-test.haozgz.com/pinyin?txt=重庆着陆OK,重力看着没有异常

    HanLP是一个优秀的开源自然语言处理工具,提供了颇为准确的拼音转换功能。开始本想使用更为顺手的nodejs来处理,但测试了Github上排第一的hotoo/pinyin库,就是开了分词,对多音字支持也不太理想。最后决定使用HanLPPython版来进行转换,但是这个库对地名的支持还是有限,字地名很多转换成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()
    

    nodejshttp模块写出来的服务一样简洁。只监听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={}
            # 轻松就解析出了请求参数对象
    

    执行实际业务逻辑

    有了pathargs,就直接可以上业务逻辑了。具体这个请求是要处理什么功能,根据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)+"
    "+traceback.format_exc()
                
            try:
                rtv=json.dumps(rtv,ensure_ascii=False)
            except Exception as e:
                rtv={'c':2,'m':'服务器返回数据错误:'+str(e)+"
    "+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来调用HanLPjava接口。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 windowsssl有问题无法安装,conda切换成python 3.6.4测试安装正常

    安装好后运行一下hanlp命令,会提示下载,看第3步

    如果出现XXX.dll什么的问题,可能是C++运行库缺失,安装微软常用运行库合集应该能够解决,我在Windows Server 2012上使用时出现此问题,装上就OJBK了。

    【3】下载字典和jar

    参考半自动配置: https://github.com/hankcs/pyhanlp/wiki/手动配置

    字典和jar存放目录一般在Miniconda3[envspy36]Libsite-packagespyhanlpstatic

    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源码:https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov/tree/master/assets/pinyin-python-server

    如果这个库有帮助到您,请 Star 一下。

  • 相关阅读:
    .VC中的Attach和Detach
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
    用API OleLoadPicture通过IStream来加载JPG、GIF格式的图片
    .OnNcHitTest
    线性规划与网络流24题索引
    线性规划与网络流24题 17运输问题
    网络流24题 21最长k可重区间集问题
    网络流16数字梯形问题
    网络流24题 20深海机器人问题
    网络流24题 19负载平衡问题
  • 原文地址:https://www.cnblogs.com/xiangyuecn/p/10612688.html
Copyright © 2020-2023  润新知