使用python做tf-idf算法实践

引入

信息内容安全课杨老师讲了一个tf-idf算法,用于提取一篇文档的关键词。觉得蛮好玩又正好练习python,所以就试着写了一下,特此记录,各位看官请轻拍板砖。

tf-idf 算法及其原理

偷个懒,直接贴维基百科的解释:

这里写图片描述

至于原理,同样贴图(没错,我就这么懒了怎么样吧。。→_→) :

tf-idf原理

如果看维基还是了解不清楚的话,推荐阮一峰大神的博客,这个也是我们的老师上课讲的东西。

至于其中的数学原理,从维基的原理就很容易看出来,基础还是“贝叶斯定理”,另外一点就是idf的值这里使用到了熵的概念。推荐这篇博客的介绍 : TF-IDF模型的概率解释

(少壮不努力, 老大学数学。。。囧rz)

实践准备

操作系统 : ubuntu16.04
python版本 :python3.5.2
引入的python组件 :

  • jieba – 用于中文分词,jieba分词组件组件介绍, 可以通过sudo pip3 install jieba3k 直接安装
  • numpy, 科学计算库,通过sudo pip3 install numpy 安装
  • scipy, 科学计算库 + 1,, 通过 sudo pip3 install scipy 安装
  • scikit-learn, 数据挖掘库, 可以通过 sudo pip3 install scikit-learn 安装

语料库准备, 努努书坊-鲁迅-伪自由书 。当然是用爬虫爬喽~

爬虫爬取语料库

如果对爬虫理解有问题可参考本人之前的博客 —— 第一个爬虫:爬去古诗中带‘月’的诗句 。爬去的方法并没有很大的改进 (太弱只能写基础的。。。orz)

三步走 :

  1. 分析之前给出的鲁迅-伪自由书, 获得《伪自由书》中所有文章的链接,并存入一个list ;
  2. for循环遍历链接list, 从新的url获得《伪自由书》中的文章 ;
  3. 将获得的文章存入一个文件夹。

附上代码

#!usr/bin/python3
#coding=utf-8

import re
import os
from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

def geturl(url):
	try :
		html = urlopen(url)
	except HTTPError as e :
		return None
	try :
		bsObj = BeautifulSoup(html, 'lxml')
	except AttributeError as e :
		return None
	return bsObj

def getArticle(url, f) :
	articlePage = geturl(url)
	article = articlePage.findAll('p')
	for paragraph in article :
		print (paragraph.get_text(), file = f)

start = "http://www.kanunu8.com/book/4433/"

page = geturl(start)
tr = page.findAll('tr', {'bgcolor' : '#ffffff'})
links = (re.findall(r'<td><a href="(.*?)">(.*?)</a></td>', str(tr)))

if not os.path.isdir('article') :
	os.mkdir('article')

for link in links :
	with open('./article/' + link[1] + '.txt', 'wt+') as f :
		f.write(link[1])
		getArticle(start + link[0], f)
	print ('---< ' , link[1], ' > get ---')
	

这个爬虫只是在之前的基础上加了一点新功能,将爬去结果都放在了一个文件夹下,使用到了 os 模块的 os.path.isdir(str) 函数和 os.mkdir(str) 函数。 前者用于检查 str 这个文件夹是否存在,后者用于创建一个名为 str 的文件夹 。

爬去的结果如下:
这里写图片描述

然后是爬取结果的一部分 :
爬取结果2

tf-idf算法实现

仍然是三步走 :

  1. 使用jieba给所有的文章分词;
  2. 使用sklearn(即 scikit-learn模块) 中的CountVectorizer()类TfidfTransformer()类 完成对词语的词频分析并获得每篇文章对应的词语的idf值, 可参考[python] 使用scikit-learn工具计算文本TF-IDF值这篇文章的第三部分
  3. 设定关键字个数,取出每篇文章中tf-idf值最大的值作为对应文章的关键词

先附上代码,然后作说明 :

#coding: utf-8

import os
import jieba
import jieba.posseg as pseg
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer

path = './article/'
titlelist, wordslist = [], []
for fileName in os.listdir(path) :
	titlelist.append(''.join(fileName[:-4].split()))
	with open(path + fileName) as f :
		text = f.read()
		text = ''.join(text.split())
		seg_list = jieba.cut(text)
		wordslist.append(' '.join(seg_list))

vec = CountVectorizer()
wordFrequence = vec.fit_transform(wordslist)
words = vec.get_feature_names()

trans = TfidfTransformer()
tfidf = trans.fit_transform(wordFrequence)
wordsWeight = tfidf.toarray()

n = int(input('输入关键字的个数 : '))
while(n > 5 or n < 0) :
	n = int(input('输入数字应大于零并且小于等于5 : '))

for (title, weight) in zip(titlelist, wordsWeight) :
	print (title, ' : ')
	weightlist = weight.tolist()
	for i in range(n) :
		loc = weightlist.index(max(weightlist))
		print('\t#' + str(i + 1) + ':', words[loc])
		del weightlist[loc]
	print()

input('any key to continue...')

对于初学者(比如我)其中可能会不太懂点:

  • os.listpath(path) 函数 返回一个list, 存的是path 文件夹的子目录中文件或文件夹的名字 ;
  • ''.join(text.split()) 将所有文章中的回车、空格删除 ;
  • 对于这一段 :
   vec = CountVectorizer()
   wordFrequence = vec.fit_transform(wordslist)
   words = vec.get_feature_names()
   
   trans = TfidfTransformer()
   tfidf = trans.fit_transform(wordFrequence)
   wordsWeight = tfidf.toarray()
   
   ```
看过给出[链接](http://blog.csdn.net/eastmount/article/details/50323063)**第三部分**也就能很好地理解了,不再解释;
- `zip()` 用于要同时遍历两个或多个 list ,将 list 打包,使用迭代器迭代获取 list 中的值。
- `for i in range(n)` 中,每次取出当前处理文档的最大tf-idf值的索引 loc , 然后在获得的词语列表words 中取出对应的词语,取出一个删除一个,即 `del` 的作用,然后继续取词知道取满 n 个为止。

# 最终结果展示
![结果展示](http://img.blog.csdn.net/20170327195357101?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQXJyb3dMTEw=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

以上です~
   












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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值