python结巴分词SEO的应用详解
结巴分词在SEO中可以应用于分析/提取文章关键词、关键词归类、标题重写、文章伪原创等等方面,用处非常多。
具体结巴分词项目:https://github.com/fxsjy/jieba
安装方法:
以mac系统为例(因为自己用mac系统):
在终端输入:
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 为默认分词器,所有全局分词相关函数都是该分词器的映射。(一般使用默认的就可以了)
代码测试:
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键分隔,一行一对关键词。
余弦相似度算法实现
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>
结果:
1
|
耗时: 0.751s相似度: 0.707 |
相似度在0.707,说明“SEO” 和“SEO培训网”这两个词相似度还是很高的。
2.关键词自动归类实现
实现思路:
将所有待分类的关键词放入到一个TXT文件中,程序将所有关键词读取到列表里面
将第一个词作为母词分别与其它词进行相似度计算,相似度大于0.3的就认为与该词同类。将对他 们放到一个新的列表中,并从原来的关键词列表中删除。
直到该词与列表中所有的词计算完毕,然后接着重复以上的操作,直到所有的词分类完毕。
算法缺陷:由于需要多次进行循环计算,因此时间复杂度比较高。不利于大批量的关键词快速归类, 而且如果关键词越驳杂,那么得到的分类就越多。
具体实现代码:
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
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 个名词或动词作为分类。然后根据包含的方式将所有的关键词归类。
该方法可以快速的将大量的关键词归类,但是会有一部分的关键词是获取不到归类的。至于选择哪种方式,由自己决定。
具体代码:
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( '\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 格式
转载自:https://www.52pojie.cn/thread-1038075-1-1.html
python结巴分词SEO的应用详解的更多相关文章
- Python学习一:序列基础详解
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7858473.html 邮箱:moyi@moyib ...
- Python学习二:词典基础详解
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...
- python 3.x 爬虫基础---Urllib详解
python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 前言 爬虫也了解了一段时间了希望在半个月的时间内 ...
- python中argparse模块用法实例详解
python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...
- HanLP分词命名实体提取详解
HanLP分词命名实体提取详解 分享一篇大神的关于hanlp分词命名实体提取的经验文章,文章中分享的内容略有一段时间(使用的hanlp版本比较老),最新一版的hanlp已经出来了,也可以去看看新版 ...
- python selenium 三种等待方式详解[转]
python selenium 三种等待方式详解 引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...
- python设计模式之迭代器与生成器详解(五)
前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...
- **Python中的深拷贝和浅拷贝详解
Python中的深拷贝和浅拷贝详解 这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容. 要说清楚Python中的深浅拷贝,需要 ...
- python+requests接口自动化测试框架实例详解
python+requests接口自动化测试框架实例详解 转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实 ...
随机推荐
- Spring cloud stream【消息分组】
上篇文章我们简单的介绍了stream的使用,发现使用还是蛮方便的,但是在上个案例中,如果有多个消息接收者,那么消息生产者发送的消息会被多个消费者都接收到,这种情况在某些实际场景下是有很大问题的,比 ...
- 关于“Error: listen EADDRINUSE: address already in use 127.0.0.1:3000”
运行vue项目的时候报 Error: listen EADDRINUSE: address already 这个错,表示3000端口号被占用. 解决方法: 1.打开cmd,执行 netstat -n ...
- python - django 解决 templates 模板语言语法冲突
# 在使用某个框架时发现语法与Django的模板语法冲突了,于是找到解决方案: {% verbatim %} // 被 verbatim 包裹起来的地方是不会被 django 渲染的 {% endve ...
- Xamarin.Forms之页面及导航
参考链接: Xamarin. Forms 页面 Xamarin.Forms 导航 Xamarin.Forms 第04局:页面 Xamarin.Forms页面代表跨平台的移动应用程序屏幕. 下文描述的所 ...
- [Android] Android studio gradle 插件的版本号和 gradle 的版本号 的对应关系
[Android] Android studio gradle 插件的版本号和 gradle 的版本号 的对应关系 本博客地址: wukong1688 本文原文地址:https://www.cnblo ...
- LINUX下的gdb调试方法
首先对目标文件进行编译 例如: gcc test.c -o test 这时会生成一个文件test,然后我们就可以对test进行调试了 示例: gdb test 好了以后是设定断点 示例: break ...
- PAT刷题 (Java语言)
1001. A+B Format (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Calculate ...
- 下拉选择的blur和click事件冲突了
当写个下拉选择框时我们希望当input失去焦点时,下拉框消失,或者当选择下拉框中的内容的同时将内容填入input并且使下拉框消失. 这时候我们会想到blur和click,单独使用的时候是没有问题的,但 ...
- 自建 ca 及使用 ca 颁发证书
创建CA: 一.安装openssl [root@localhost ~]# yum install -y openssl 二.创建CA的相关文件及目录 mkdir /opt/root_ca & ...
- shell脚本获取传入参数的个数
ts.sh #!/bin/bash echo $# 输出 [root@redhat6 ~]# ./ts.sh para1 [root@redhat6 ~]# ./ts.sh para1 para2 [ ...