python结巴分词代码_python结巴分词SEO的应用详解

本帖最后由 为人生而奋斗 于 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 格式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值