首页 编程教程正文

python结巴分词SEO的应用详解

piaodoo 编程教程 2020-02-22 22:14:33 1238 0 python教程

本文来源吾爱破解论坛

本帖最后由 为人生而奋斗 于 2019-10-15 16:19 编辑

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

pip3 install jieba -i http://pypi.douban.com/simple --trusted-host pypi.douban.com


   

image.png (138.97 KB, 下载次数: 0)

下载附件  保存到相册

2019-10-15 10:48 上传



   这样就安装完成,然后就可以用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] 纯文本查看 复制代码
#!/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))


   

image.png (402.44 KB, 下载次数: 0)

下载附件  保存到相册

2019-10-15 10:50 上传

  

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

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

第一种:json格式
嗨学网

第二种:Excel 格式

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

主要步骤:

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



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

  余弦相似度算法实现

   [Asm] 纯文本查看 复制代码
# -*- 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)

  

image.png (531.48 KB, 下载次数: 0)

下载附件  保存到相册

2019-10-15 10:53 上传


结果:

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


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



2.关键词自动归类实现

实现思路:

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

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

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

  算法缺陷:由于需要多次进行循环计算,因此时间复杂度比较高。不利于大批量的关键词快速归类, 而且如果关键词越驳杂,那么得到的分类就越多。
具体实现代码:
   [Asm] 纯文本查看 复制代码
# -*- 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] 纯文本查看 复制代码
# -*- 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] 纯文本查看 复制代码
# -*- 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('\t') 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 格式

版权声明:

本站所有资源均为站长或网友整理自互联网或站长购买自互联网,站长无法分辨资源版权出自何处,所以不承担任何版权以及其他问题带来的法律责任,如有侵权或者其他问题请联系站长删除!站长QQ754403226 谢谢。

有关影视版权:本站只供百度云网盘资源,版权均属于影片公司所有,请在下载后24小时删除,切勿用于商业用途。本站所有资源信息均从互联网搜索而来,本站不对显示的内容承担责任,如您认为本站页面信息侵犯了您的权益,请附上版权证明邮件告知【754403226@qq.com】,在收到邮件后72小时内删除。本文链接:https://www.piaodoo.com/7894.html

搜索