zoukankan      html  css  js  c++  java
  • python结巴分词SEO的应用详解

     结巴分词在SEO中可以应用于分析/提取文章关键词、关键词归类、标题重写、文章伪原创等等方面,用处非常多。
         具体结巴分词项目:https://github.com/fxsjy/jieba
        安装方法:
       以mac系统为例(因为自己用mac系统):
       在终端输入:
       

    [Asm] 纯文本查看 复制代码
    1
    pip3 install jieba -i http://pypi.douban.com/simple --trusted-host pypi.douban.com



        <ignore_js_op>

       这样就安装完成,然后就可以用coderunner软件开始写python3使用了

       常用方法使用示例
    1. 分词常用方法

    jieba.cut 方法接受三个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型

    jieba.cut_for_search 方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用 于搜索引擎构建倒排索引的分词,粒度比较细 待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串, 可能无法预料地错误解码成 UTF-8

    jieba.Tokenizer(dictionary=DEFAULT_DICT)  新建自定义分词器,可用于同时使用不同词典。 jieba.dt 为默认分词器,所有全局分词相关函数都是该分词器的映射。(一般使用默认的就可以了)

       代码测试:
       

    [Asm] 纯文本查看 复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python3# -*- coding: utf-8 -*-
    import jieba
    ret1 = jieba.cut('我来到北京清华大学', cut_all=True)
    ret2 = jieba.cut('我来到北京清华大学', cut_all=False)
    ret3 = jieba.cut_for_search('我来到北京清华大学')
    print('/'.join(ret1))
    print('/'.join(ret2))
    print('/'.join(ret3))



        <ignore_js_op>   

       开始应用:
    分类海量关键词(用于专题页、tag标签等)

    假如我们用之前的关键词挖掘工具挖掘出了一堆关键词,看起来不仅杂乱无章,并且还要花大量的时间来进行过滤和归类。那么,就教大家用结巴分词来对关键词进行归类,几千个关键词1秒完成,几万关键词1分钟也能搞定。最后可以得到下图两种结果。这个可以用来干嘛呢?我们在做SEO的时候是不是可以根据分类将同一类的词做成专题页或者tag标签的聚合页?
       

    第一种:json格式

    第二种:Excel 格式

       提取文章关键词
    假如我们需要了解一篇文章内,关于该行业的关键词的表现如何(文章中包含了多少关键词,TF_IDF值是多 少,或者是TextRank的值是多少)等,我们都需要对文章进行分词处理,但是由于每个行业都有自己的专业 名词,所以仅仅使用python默认的词典的话那么就很难获取到准确的数据,数据得出来也不是我们想要的。 这个时候一般的做法就是添加自己的行业关键词字典,让结巴分词更准确。

    主要步骤:

    找到行业的相关关键词,保存到TXT文件里面
    将所有的词都设置为相同的自定义词性,比如kws
    在程序中导入自定义词典
    使用TF-IDF算法提取文章的关键词,在词性过滤参数里面添加自定义词性,打印结果分析行业词的情 况。
    该方法在实际用得比较少,主要就分析一下竞争对手内容中关键词的部署情况,实际的参考意义对于SEO来说 不是很大。



    二、关键词归类|标题重写|文章伪原创
    通过余弦相似度算法计算两个字符串之间的相关度,来对关键词进行归类、重写标题、文章伪原创等功能, 让你目瞪口呆。以下案例使用的母词文件均为txt文件,两种格式:一种内容是纯关键词的txt,每行一个关键词就好;另一种是关键词加指数的txt,关键词和指数之前用tab键分隔,一行一对关键词。

      余弦相似度算法实现

       

    [Asm] 纯文本查看 复制代码
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # -*- coding: utf-8 -*-from jieba import posseg
    import math
    import time
    def simicos(str1, str2):
        # 对两个要计算的字符串进行分词, 使用隐马尔科夫模型(也可不用)
        # 由于不同的分词算法, 所以分出来的结果可能不一样
        # 也会导致相似度会有所误差, 但是一般影响不大
        cut_str1 = [w for w, t in posseg.lcut(str1) if 'n' in t or 'v' in t]
        cut_str2 = [w for w, t in posseg.lcut(str2) if 'n' in t or 'v' in t]
        # 列出所有词
        all_words = set(cut_str1 + cut_str2)
        # 计算词频
        freq_str1 = [cut_str1.count(x) for x in all_words]
        freq_str2 = [cut_str2.count(x) for x in all_words]
        # 计算相似度
        sum_all = sum(map(lambda z, y: z * y, freq_str1, freq_str2))
        sqrt_str1 = math.sqrt(sum(x ** 2 for x in freq_str1))
        sqrt_str2 = math.sqrt(sum(x ** 2 for x in freq_str2))
        return sum_all / (sqrt_str1 * sqrt_str2)
    if __name__ == '__main__':
        case1 = "SEO"
        case2 = "SEO培训网"
        start = time.time()
        similarity = simicos(case1, case2)
        end = time.time()
        print()
        print("耗时: %.3fs" % (end - start))
        print("相似度: %.3f" % similarity)


       <ignore_js_op>
    结果:

      

    [Asm] 纯文本查看 复制代码
    1
    耗时: 0.751s相似度: 0.707



    相似度在0.707,说明“SEO” 和“SEO培训网”这两个词相似度还是很高的。



    2.关键词自动归类实现

    实现思路:

    将所有待分类的关键词放入到一个TXT文件中,程序将所有关键词读取到列表里面

    将第一个词作为母词分别与其它词进行相似度计算,相似度大于0.3的就认为与该词同类。将对他 们放到一个新的列表中,并从原来的关键词列表中删除。

    直到该词与列表中所有的词计算完毕,然后接着重复以上的操作,直到所有的词分类完毕。

      算法缺陷:由于需要多次进行循环计算,因此时间复杂度比较高。不利于大批量的关键词快速归类, 而且如果关键词越驳杂,那么得到的分类就越多。
    具体实现代码:
       

    [Asm] 纯文本查看 复制代码
    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    012
    013
    014
    015
    016
    017
    018
    019
    020
    021
    022
    023
    024
    025
    026
    027
    028
    029
    030
    031
    032
    033
    034
    035
    036
    037
    038
    039
    040
    041
    042
    043
    044
    045
    046
    047
    048
    049
    050
    051
    052
    053
    054
    055
    056
    057
    058
    059
    060
    061
    062
    063
    064
    065
    066
    067
    068
    069
    070
    071
    072
    073
    074
    075
    076
    077
    078
    079
    080
    081
    082
    083
    084
    085
    086
    087
    088
    089
    090
    091
    092
    093
    094
    095
    096
    097
    098
    099
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    # -*- coding: utf-8 -*-from jieba import posseg
    import math
    import json
    import time
    # 结果保存字典
    result = {}
    # Cache 缓存
    cache = {}
    def simicos(str1, str2):
        """
        字符串余弦相似度算法实现, 添加缓存存储,减少分词带来的时间消耗
        提高计算效率
        :param str1: 要比较的字符串1
        :param str2: 要比较的字符串2
        :return: 相似度值0.0-1.0
        """
        global cache
        if cache.get(str1):  # 或者用key in cache 方法也可以
            cut_str1 = cache[str1]
        else:
            cut_str1 = [w for w, t in posseg.cut(str1) if 'n' in t or 'v' in t]
            cache[str1] = cut_str1
        if cache.get(str2):
            cut_str2 = cache[str2]
        else:
            cut_str2 = [w for w, t in posseg.cut(str2) if 'n' in t or 'v' in t]
            cache[str2] = cut_str2
        all_words = set(cut_str1 + cut_str2)
        freq_str1 = [cut_str1.count(x) for x in all_words]
        freq_str2 = [cut_str2.count(x) for x in all_words]
        sum_all = sum(map(lambda z, y: z * y, freq_str1, freq_str2))
        sqrt_str1 = math.sqrt(sum(x ** 2 for x in freq_str1))
        sqrt_str2 = math.sqrt(sum(x ** 2 for x in freq_str2))
        try:
            return sum_all / (sqrt_str1 * sqrt_str2)
        except ZeroDivisionError:
            return 0.0
    def calculate(keyword_list):
        """
        使用递归的方式进行计算和分类
        优点:代码简单,容易理解
        缺点:python默认最大的递归深度为1000,超过之后就会出错
        :param keyword_list: 要分类的关键词列表
        :return: None
        """
        filter_word = []
        # 获取第一个词作为母词
        muci = keyword_list.pop(0)
        # 用该词作为分类
        result[muci] = []
        print(len(keyword_list))
        while keyword_list:
            # 提取列表中的下一个词
            kw = keyword_list.pop(0)
            simi = simicos(muci, kw)
            if simi >= 0.3:
                result[muci].append(kw)
            else:
                filter_word.append(kw)
        # 如果列表中还有词,就递归计算
        if filter_word:
            calculate(filter_word)
    def classify(keyword_list):
        """
        使用while循环的方法计算和分类
        :param keyword_list: 要分类的关键词队列
        :return: None
        """
        muci = keyword_list.pop(0)  # 第一个词
        result[muci] = {"total": 0, "list": []}
        last = keyword_list[-1]  # 最后一个词
        total_classify = 0
        remain = len(keyword_list)
        while keyword_list:
            # 提取列表中的下一个词
            kw = keyword_list.pop(0)
            simi = simicos(muci, kw)
            if simi >= 0.3:
                result[muci]["list"].append(kw)
                result[muci]["total"] += 1
                remain -= 1
            else:
                keyword_list.append(kw)
            if kw == last and keyword_list:  # 如果已经是最后一个了
                total_classify += 1
                print("Has been classified %d, remain %d" % (total_classify, remain))
                muci = keyword_list.pop(0)
                remain -= 1
                result[muci] = {"total": 0, "list": []}
                if keyword_list:
                    last = keyword_list[-1]
                else:
                    break
    def result_filter(result_dict, bigthan=10):
        """
        结果过滤筛选函数
        由于使用该方法会等到很多的分类,有些分类是没有关键词的或者只有少数的相关词
        那么对于这些分类就可能不需要了,我们就直接把他们过滤掉就好了
        :param result_dict: 要筛选的分类结果
        :param bigthan: 相关词数量大于等于该数的分类将保存
        :return: 过滤后的结果
        """
        retfilter = {}
        for item, values in result_dict.items():
            if values["total"] > bigthan:
                retfilter[item] = values
        return retfilter
    if __name__ == "__main__":
        t_start = time.time()
        print("start....")
        keywords = [key.strip() for key in open("baidumobilekey.txt", encoding='utf-8')]
        classify(keywords)
        filtered = result_filter(result)
        # 结果保存在json中
        f = open("result3.json", "w", encoding='utf-8')
        f.write(json.dumps(filtered, ensure_ascii=False))
        f.close()
        print("done, consume %.3f" % (time.time() - t_start))



    结果:



    结果保存为json文件
    因为上面的算法都是通过纯python写的,因此算法的速度是比较慢的,经测试,几万的关键词可能都需要十几分 钟,因此的话不适宜用来分类大量的关键词,同时如果要求的相似度越高,那么得出来的分类就越多。因此也不是 很好的一种解决办法。


    还有一种就是使用编辑距离的算法,这个算法有别人用c语言写好的,而且不用分词,因此速度上比上面的算法会快很多,但是分类效果没那么好。一些不相关的词也可能会被分类到同一个分类下。

      使用Levenshtein模块分类

    代码实现: 需要安装Levenshtein模块,安装方法 pip install python-Levenshtein
      

    [Asm] 纯文本查看 复制代码
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    # -*- coding: utf-8 -*-import json
    import time
    import Levenshtein
    result = {}
    def classify(keyword_list):
        """
        使用while循环的方法计算和分类
        :param keyword_list: 要分类的关键词队列
        :return: None
        """
        muci = keyword_list.pop(0)  # 第一个词
        result[muci] = {"total": 0, "list": []}
        last = keyword_list[-1]  # 最后一个词
        total_classify = 0
        remain = len(keyword_list)
        while keyword_list:
            # 提取列表中的下一个词
            kw = keyword_list.pop(0)
            simi = Levenshtein.jaro_winkler(kw, muci)
            if simi >= 0.8:
                result[muci]["list"].append(kw)
                result[muci]["total"] += 1
                remain -= 1
            else:
                keyword_list.append(kw)
            if kw == last and keyword_list:  # 如果已经是最后一个了
                total_classify += 1
                print("Has been classified %d, remain %d" % (total_classify, remain))
                muci = keyword_list.pop(0)
                remain -= 1
                result[muci] = {"total": 0, "list": []}
                if keyword_list:
                    last = keyword_list[-1]
                else:
                    break
    def result_filter(result_dict, bigthan=10):
        """
        结果过滤筛选函数
        由于使用该方法会等到很多的分类,有些分类是没有关键词的或者只有少数的相关词
        那么对于这些分类就可能不需要了,我们就直接把他们过滤掉就好了
        :param result_dict: 要筛选的分类结果
        :param bigthan: 相关词数量大于等于该数的分类将保存
        :return: 过滤后的结果
        """
        retfilter = {}
        for item, values in result_dict.items():
            if values["total"] > bigthan:
                retfilter[item] = values
        return retfilter
    if __name__ == "__main__":
        t_start = time.time()
        print("start....")
        keywords = [key.strip() for key in open("baidumobilekey.txt", encoding='utf-8')]
        # keywords = [key.strip() for key in open("004.txt", encoding='utf-8')]
        # calculate(keywords)
        classify(keywords)
        filtered = result_filter(result)
        # 结果保存在json中
        f = open("result4.json", "w", encoding='utf-8')
        f.write(json.dumps(filtered, ensure_ascii=False))
        f.close()
        print("done, consume %.3f" % (time.time() - t_start))



      得到的结果也是一个json文件。

      结巴分词关键词分类

    以上的算法速度是快了,但是的话效果也不是很好,而且分类也比较多。

    这里还有一种比较折中的办法,那就是通过结巴将所有的关键词进行分词,然后根据TF-IDF算法,提取出里面前N 个名词或动词作为分类。然后根据包含的方式将所有的关键词归类。

    该方法可以快速的将大量的关键词归类,但是会有一部分的关键词是获取不到归类的。至于选择哪种方式,由自己决定。

    具体代码:
       

    [Asm] 纯文本查看 复制代码
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    # -*- coding: utf-8 -*-"""
    python结巴关键词分类脚本,算法二
    1. 通过TF_IDF算法提取出前N个词性的词作为分类
    2. 遍历整个关键词列表,假如关键词中包含分类名,则将词放入到分类中
    3. 如果都没有,则将词放入到其它分类
    """
    import codecs
    import csv
    import time
    from jieba import analyse
    result = {}
    def init(group):
        for g in group:
            result[g] = {"total": 0, "keys": []}
        result["其它"] = {"total": 0, "keys": []}
    def classsify(kw_list, group):
        index = 0
        total = len(kw_list)
        while index < total:
            flag = 0
            for g in group:
                if g in kw_list[index][0]:
                    flag = 1
                    result[g]["total"] += int(keyword_list[index][1])
                    result[g]["keys"].append(kw_list[index])
            if not flag:
                result["其它"]["total"] += int(keyword_list[index][1])
                result["其它"]["keys"].append(kw_list[index])
            index += 1
    def write_to_file(group):
        savefile = open("result.csv", "w", encoding='utf-8')
        csvwriter = csv.writer(savefile)
        fields = []
        group.append("其它")
        for g in group:
            fields.append(g)
            fields.append(result[g]["total"])
        csvwriter.writerow(fields)
        maxline = max(len(item["keys"]) for item in result.values())
        cols = len(fields)
        for row in range(maxline):
            rowfield = ["" for _ in range(cols)]
            gix = 0
            kwitem = []
            for col in range(cols):
                if result.get(group[gix])["keys"]:
                    if col % 2 == 0:
                        kwitem = result.get(group[gix])["keys"].pop(0)
                    rowfield[col] = kwitem[0]
                    if col % 2 == 1:
                        gix += 1
                        rowfield[col] = kwitem[1]
            csvwriter.writerow(rowfield)
        savefile.close()
    if __name__ == "__main__":
        print("start.....")
        t_start = time.time()
        keyword_list = [k.strip().split(' ') for k in open("003.txt", encoding='utf-8')]
        groups = analyse.extract_tags(" ".join(item[0] for item in keyword_list),
                                      topK=20, allowPOS=('ns', 'n', 'vn', 'v', 'nr'))
        groups = [g for g in groups]
        init(groups)
        classsify(keyword_list, groups)
        write_to_file(groups)
        print("done, consume %.3f" % (time.time() - t_start))



    结果:每一列为一个类别,例如第一列是“考研”这个类别的所有词语分类。


    结果存为Excel 格式

    转载自:https://www.52pojie.cn/thread-1038075-1-1.html

  • 相关阅读:
    2012年6月30号PMP考试总结
    安装了VS2010 sp1 后再安装ASP.NET MVC 3.0的问题(Final Result: Installation failed with error code: (0x80070643), "安装时发生严重错误 " (Ela)
    黄光裕方面独家点评国美中报:领先优势即将丧失
    Asp.net 模板页(MasterPage)里的 js脚本路径
    Windows 7 Sp1 x64 无法安装英文语言包(已解决)
    The issue of vertical lines throughing the Report footer or the whole page in Crystal report 11
    Windows Server 2008 R2 with Service Pack 1
    垃圾农业银行网银https://www.95599.cn/PersonalBank/startUpHtmlSessionAction.ebf
    如何填写PMP审计表单,Audit注意事项
    被日军飞机炸毁的上海南火车站铁轨上拍摄了一个父母刚被炸死、正在铁轨上深哀啼号的婴儿
  • 原文地址:https://www.cnblogs.com/ginowang42/p/12001226.html
Copyright © 2011-2022 走看看