通过webpy实现一个简单的相关关键词API接口

前两天的时间比较忙,没有时间做分享,所以今天给大家分享一个福利吧。如果你是做SEO的,那么这个可能对你的工作有所帮助。

前些日子有个基友找我做一个web的API接口,主要的功能如下:

  • 有自己的一个关键词词库
  • 通过http请求一个关键词,然后返回跟这个关键词最相关的N个结果
  • 就是想这两个简单的功能,因为功能太简单,因此就没有必要用到复杂的框架(Django, flask)这些,所以就用了一个最基本的webpy实现。

    效果展示
    1.默认首页
    默认首页
    2.关键词搜索结果页(词库有点不纯洁)
    关键词搜索结果页

    实现过程
    首先需要安装webpy以及Levenshtein,安装方法也很简单:

    pip install web.py python-levenshtein

    如果安装下载速度比较慢的,那么可以使用豆瓣源进行安装。对于MacOS和Linux用户可能需要root权限,这个自行添加就好。

    先说一下实现思路
    整个API的核心就是通过一个关键词来查找跟他相关的关键词,那么就需要到一个关键词相似度的算法来计算。由于一个词库的关键词数量可能存在很多的关键词(几万,几十万等)那么对于算法的效率要求就比较高了。这也是我没有用余弦相似度算法的原因,因为那个算法需要用到jieba分词,如果每次都对几十万的词进行分词是会崩溃的。所以这里我用了一个效率比较高,准确度还算可以的编辑距离算法,这个算法是别人优化过的,直接拿来用就好,经测试词库6W多的词基本是瞬时响应。

    具体代码实现细节
    先来实现根据一个关键词,返回N个相似的关键词

    import Levenshtein
    
    def match_key(key, num, library):
        """获取固定数量的相关关键词
        key: 要获取的关键词
        num: 要获取相关词的数量
        library: 关键词词库
        return: 由/分割的字符串组成的N个关键词
        """
        simi_dict_list = {lib_key: Levenshtein.jaro(key, lib_key) for lib_key in library}
        simi_list = sorted(simi_dict_list.iteritems(), key=lambda x: x[1], reverse=True)
        return "/".join([w[0] for w in simi_list[:num]])
    

    解释一下代码:函数需要传递三个参数(要查询的关键词,要返回的关键词数量,要查询的关键词库)第一句是将关键词与通过levenshtein.jaro方法计算出来的相似度组成一个字典。然后通过sorted方法,以相似度值进行逆序排序,得到的是一个元组组成的list,最后根据参数num来设置返回多少个关键词,并通过join方法以/区分每个关键词,组成字符串返回。

    web请求部分代码实现

    import web
    
    urls = (
        '/', 'Index',
    )
    # 关键词词库 每行一个关键词
    ciku = [w.strip() for w in open("ciku.txt")]
    
    class Index:
        def GET(self):
            web.header('Content-Type','text/html; charset=utf-8')
            key = web.input(s=None)
            num = web.input(n=None)
            if key.s is not None:
                word = key.s.encode("utf-8")
                number = int(num.n) if num.n else 3
                return match_key(word, number, ciku)
            else:
                return "欢迎使用关键词自动匹配系统!"
    

    简单解释一下代码:
    变量urls里面就是配置路由的,每行一个路由,前面表示请求路径/(首页),后面是实现这个请求的类名Index。接下来就是导入关键词的词库,每行一个关键词,文本要是utf-8编码,墙裂要求python编程过程中一直用这个编码。
    后面就是实现Index这个类,因为这里我们都是get请求,所以就之定义了GET方法。接着先定义响应头的编码(不然中文响应可能会返回乱码),然后通过web.input(key=default)方法获取GET请求参数,其中key就是参数名, default就是参数默认值,我这里设置为None。通过这种方法分别获取关键词和返回数量。
    接下来判断是否获取到关键词,如果获取不到,那么说明没有写对参数名或者是请求首页,这时直接返回一段话就好了。如果获取到了那么就先将关键词进行编码为utf-8的,因为获取到的是Unicode编码。然后判断是否有提供返回数量的参数,如果没有就直接默认是返回3个相关词。接下来就是直接将参数传入到之前计算相关度的函数match_key,然后返回。

    启动服务部分代码
    因为比较简单,所以全部放在了一个文件里面,运行服务代码如下:

    if __name__ == '__main__':
        app = web.application(urls, globals())
        app.run()
    

    这部分的代码就没啥好解析的了,if __name__ == ‘__main__’就是只有运行当前的文件才会执行下面的代码。接着就创建一个webpy的应用实例,把路由配置和全局变量传进去,最后启动应用。

    运行代码
    在当前代码文件夹下使用如下命令,假设文件名是index.py:

    $python index.py 8000
    

    就会看到输出http://0.0.0.0:8000/,然后再浏览器打开就看到文章前面的展示效果啦。
    完整代码地址: https://github.com/brookxs/webpywebpy
    学习地址:http://webpy.org/docs/0.3/tutorial.zh-cn
    微信公众号:布鲁的python

    发表评论

    电子邮件地址不会被公开。