自然语言处理包括中文分词、词性标注、关键词抽取、依存句法分析、文本分类接口情感分析、词义相似度计算、实体标识、文本摘要等等,慢慢来吧,看看一步步能到什么程度。本文实现的是关键词提取。
在jiaba中,关键词提取包括了TF-IDF关键词提取、PageRank关键词提取方式,同时还可以自定义语料库、停用词库,在此基础上再进行TF-IDF关键词提取,本文略作尝试。
代码示例
代码语言:javascript复制#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import math
import re
import datetime
import sys
import jieba
import jieba.analyse
import codecs
from collections import Counter
#对文件进行分词处理
def segment(sentence, cut_all=False):
sentence = sentence.replace('n', '').replace('u3000', '').replace('u00A0', '')
sentence = ' '.join(jieba.cut(sentence, cut_all=cut_all))
return re.sub('[a-zA-Z0-9.。::,,))((!!??”“"]', '', sentence).split()
#将文件从gb2312格式转码为utf-8格式
def EncodingtoUTF(filename):
try:
with codecs.open(filename, 'rb', 'mbcs') as f:
text=f.read().encode("utf-8")
with open(filename, 'wb') as e:
e.write(text)
except:
return
# 对指定目录的文件进行分词
class DocumentsSegment(object):
def __init__(self, dirname):
self.dirname = dirname
if not os.path.isdir(dirname):
print(dirname, '- not a directory!')
sys.exit()
def __iter__(self):
for dirfile in os.walk(self.dirname):
for fname in dirfile[2]:
# 对文件进行utf-8转码
EncodingtoUTF(os.path.join(dirfile[0], fname))
text = open(os.path.join(dirfile[0], fname),
'r', encoding='utf-8', errors='ignore').read()
# 对文件进行迭代并进行分词
yield segment(text) # time consuming
class IDFGen():
def __init__(self,inputdir,outputfile):
self.inputdir=inputdir
self.outputfile=outputfile
self.documents=DocumentsSegment(inputdir)
def gen_idf(self):
ignored = {'', ' ', '', '。', ':', ',', ')', '(', '!', '?', '”', '“'} #忽略词
id_freq = {} #词频字典
i = 0
for doc in self.documents:
doc = set(x for x in doc if x not in ignored) #剔除忽略词
for x in doc: #遍历文档
id_freq[x] = id_freq.get(x, 0) 1 #更新词频
if i % 1000 == 0: #每1000篇文章提示进度
print('Documents processed: ', i, ', time: ',
datetime.datetime.now())
i = 1
# 词频排序
sortdata = dict(sorted(id_freq.items(), key=lambda x: x[1]))
# 将词频转换后写入词频语料库
with open(self.outputfile, 'w', encoding='utf-8') as f: #将词频取对数后,写入idf文件
for key, value in sortdata.items():
f.write(key ' ' str(math.log(i / value, 2)) 'n')
# 词频文件加载
class IDFLoader(object):
def __init__(self, idf_path):
self.idf_path = idf_path
self.idf_freq = {} # idf
self.mean_idf = 0.0 # 均值
self.load_idf()
# 加载词频文件
def load_idf(self): # 从文件中载入idf
cnt = 0
with open(self.idf_path, 'r', encoding='utf-8') as f:
for line in f:
try:
word, freq = line.strip().split(' ')
cnt = 1
except Exception as e:
pass
self.idf_freq[word] = float(freq)
print(self.idf_freq)
print('Vocabularies loaded: %d' % cnt)
# 获取idf均值
self.mean_idf = sum(self.idf_freq.values()) / cnt
if __name__ == "__main__":
inputdir = 'C:PythonPycharmlangprocess\train'
idffile = 'C:PythonPycharmlangprocess\udfidf.txt'
stopwordfile= 'C:PythonPycharmlangprocess\stopwords.txt'
filename = 'C:PythonPycharmlangprocess\trainC4-LiteratureC4-Literature02.txt'
str = '''《三国演义》描写了从东汉末年到西晋初年之间近百年的历史风云,以描写战争为主,诉说了东汉末年的群雄割据混战和魏、蜀、吴三国之间的政治和军事斗争,最终司马炎一统三国,建立晋朝的故事。反映了三国时代各类社会斗争与矛盾的转化,并概括了这一时代的历史巨变,塑造了一群叱咤风云的三国英雄人物。全书可大致分为黄巾起义、董卓之乱、群雄逐鹿、三国鼎立、三国归晋五大部分。在广阔的历史舞台上,上演了一幕幕气势磅礴的战争场面。作者罗贯中将兵法三十六计融于字里行间,既有情节,也有兵法韬略。《三国演义》是中国文学史上第一部章回小说,是历史演义小说的开山之作,也是第一部文人长篇小说,中国古典四大名著之一。'''
seg_list = jieba.cut(str) #分词
# 《|三国演义|》|描写|了|从|东汉|末年|到|西晋|初年|之间|近|百年|的|历史风云|,|以|描写|战争|为主|,|诉说|了|东汉|末年|的|群雄割据|混战|和|魏|、|蜀|、|吴三国|之间|的|政治|和|军事|斗争
data = Counter(seg_list) #用Counter函数构造字典
# Counter({',': 12, '的': 10, '了': 6, '、': 6, '。': 6, '三国': 4, '是': 3, '《': 2, '三国演义': 2, '》': 2
# Counter输出的时候有顺序,但其实内部是无顺序的,建议排序一下
top10= data.most_common(10) #通过Counter函数的most_common获取前10名
#[(',', 12), ('的', 10), ('了', 6), ('、', 6), ('。', 6), ('三国', 4), ('是', 3), ('《', 2), ('三国演义', 2), ('》', 2)]
sortdata=sorted(data.items(), key=lambda x: x[1], reverse=True)
# [(',', 12), ('的', 10), ('了', 6), ('、', 6), ('。', 6), ('三国', 4), ('是', 3), ('《', 2), ('三国演义', 2), ('》', 2)
# AttributeError: 'Counter' object has no attribute 'sort'
# 所以只能转换为list再通过list进行排序
items = list(data.items())
items.sort(key=lambda x: x[1], reverse=True)
# [(',', 12), ('的', 10), ('了', 6), ('、', 6), ('。', 6), ('三国', 4), ('是', 3), ('《', 2), ('三国演义', 2), ('》', 2), ('描写', 2), ('东汉', 2),
# ----------------------------------------关键词提取-------------------------------------------
# 基于TF-IDF算法的关键词抽取
# 第一个参数:待提取关键词的文本
# 第二个参数:返回关键词的数量,重要性从高到低排序
# 第三个参数:是否同时返回每个关键词的权重
# 第四个参数:词性过滤,为空表示不过滤,若提供则仅返回包括指定词性的词,默认值为空,即不筛选
keywords = jieba.analyse.extract_tags(str, topK=5, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v'))
# [('三国', 0.5706667621368), ('兵法', 0.3433023063252), ('描写', 0.2863118806472), ('历史风云', 0.256041307266), ('群雄逐鹿', 0.242178363654)]
# 基于 TF-IDF 算法的关键词抽取,使用停用词词典,使用逆向文件频率文本语料库
tfidf = jieba.analyse.TFIDF()
tfidf.set_stop_words('stopwords.txt') # 使用停用词词典
tfidf.set_idf_path('idf.txt') # 使用默认的逆向文件频率(IDF)文本语料库
keywords=tfidf.extract_tags(str,topK=5, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v')) # 再进行
# [('三国', 0.5706667621368), ('兵法', 0.3433023063252), ('描写', 0.2863118806472), ('历史风云', 0.256041307266), ('群雄逐鹿', 0.242178363654)]
# 基于 TextRank 算法的关键词抽取
# 第一个参数:待提取关键词的文本
# 第二个参数:返回关键词的数量,重要性从高到低排序
# 第三个参数:是否同时返回每个关键词的权重
# 第四个参数:词性过滤,为空表示不过滤,若提供则仅返回符合词性要求的关键词,默认过滤词性是('ns', 'n', 'vn', 'v')
keywords = jieba.analyse.textrank(str, topK=5, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v'))
# [('三国', 1.0), ('斗争', 0.7784764171715404), ('兵法', 0.6974027914816684), ('历史', 0.6748143587652791), ('时代', 0.6480813515953463)]
# 利用jieba进行关键字提取时,有两种接口。
# 一个基于TF-IDF算法,一个基于TextRank算法。
# TF-IDF算法,完全基于词频统计来计算词的权重,然后排序,在返回TopK个词作为关键字。
# TextRank相对于TF-IDF,基本思路一致,也是基于统计的思想,只不过其计算词的权重时,还考虑了词的上下文(通过窗口滑动来实现),
# 而且计算词的权重时,也考虑了相关联系词的影响。可以说,TextRank实际上是依据位置与词频来计算词的权重的。
# TF-IDF计算简单,运行性能更好。
# ----------------------------------------自定义预料库后关键词提取-------------------------------------------
#content = open(filename, 'rb').read()
content = open(filename, 'r', encoding='utf-8', errors='ignore').read()
jieba.analyse.set_stop_words(stopwordfile)
keywords = jieba.analyse.extract_tags(content, topK=10) #, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v')) # 再进行
print('未使用自定义预料,输出关键词:',keywords)
# 未使用自定义预料,输出关键词: ['岭南文化', '文化', '爱国主义', '学者', '近代', '研讨会', '侨乡', '传统', '研究', '炎黄']
# 基于原始语料,生成自定义的词频库
myidffile=IDFGen(inputdir,idffile)
myidffile.gen_idf()
jieba.analyse.set_stop_words(stopwordfile)
jieba.analyse.set_idf_path(idffile);
keywords = jieba.analyse.extract_tags(content, topK=10)
print('使用自定义预料后,输出关键词:', keywords)
# 使用自定义预料后,输出关键词: ['岭南文化', '爱国主义', '广东', '侨乡', '岭南', '中原', '与会', '商品经济', '学者', '近代']