本文来源吾爱破解论坛
本帖最后由 为人生而奋斗 于 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)
下载附件 保存到相册
这样就安装完成,然后就可以用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)
下载附件 保存到相册
开始应用:
分类海量关键词(用于专题页、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)
下载附件 保存到相册
结果:
[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 谢谢。
- 上一篇: (tkinter自习作)国内股票期权保证金计算器
- 下一篇: MPV播放直播视频