记录读《Programming Collective Intelligence》一书。
本文记录第三章的第一部分:获取数据
第三章描述了群组的建立,首先获取测试数据;而后根据不同的聚类方法行成群组,并展示。
需要的python语言基础
字典
定义: 字典是Python 语言中唯一的映射类型。映射类型对象里哈希值(键) 和指向的对象(值)是一对多的关系
初始化及赋值:
>>> dict1 = {} #空字典
>>> dict2 = {'name': 'earth', 'port': 80}
访问字典中的值:
(1) 遍历整个字典
>>>> for key in dict2.keys():
... print 'key=%s, value=%s' % (key, dict2[key])
...
key=name, value=earth
key=port, value=80
(2) 获取某个键的值
>>> dict2['name']
'earth'
本文中,上述两种方法都采用了,其中对于第一种方法的使用有所差异:遍历字典的每个元素,而非字典元素的键;对于第二种方法,采用动态发现的
单词作为键进行索引,例如 dict2[word]
内建方法:
keys()方法,返回一个列表,包含字典中所有的键
values()方法,返回一个列表,包含字典中所有的值
items(), 返回一个包含所有(键, 值)元组的列表。
以上三个接口都是返回一个列表,在本文中的代码实现中,使用items方法,遍历词典的每个元素。
字符串
原始字符串操作符
r/R
在转义字符(\n \t等)前增加字母 r,使得转义字符的转义功能失效,恢复其最原始的字符功能。
例如:
>>> f = open('C:\windows\temp\readme.txt', 'r')
上述语句为打开某个文件的操作,但是文件的路径中含有 \temp \readme 两个红色部分的转义字符,导致操作失败。此时采用r操作符。
f = open(r'C:\windows\temp\readme.txt', 'r')
如上,在文件路径的字符串前加 r 操作符。
正则表达式
定义:
正则表达式(RE)是一些由字符和特殊符号组成的字符串,它们描述了这些字符和字符的某种重复方式,因此能按某种模式匹配一个有相似特征的字符串的集合、字符串。
涉及到的通配符:
[.........] 匹配字符组中出现的任意一个字符
[^........] 不匹配此字符集中的任意个字符
+ 匹配(+)前面出现的正则表达式一次或者多次 [a-z] +\.com 匹配一个或者多个小写字母
举例: [^A-Z^a-z]+ 表示:不匹配大小写字母表的字符,即非字母的 字符形式。
<[^>]+> 表示: 第一个字符是<, 第二个字符不是>。
常见的函数和方法:
split(pattern,string, max=0) 根据正则表达式pattern 中的分隔符把字符string 分割为一个列表,返回成功匹配的列表,最多分割max 次(默认是分割所有匹配的地方)。
sub(pattern, repl, string, max=0) 把字符串string 中所有匹配正则表达式pattern 的地方替换成字符串repl,如果max 的值没有给出,则对所有匹配的地方进行替换(另外,请参考subn(),它还会返回一个表示替换次数的数值)。
代码实现
代码实现的原理:获取订阅博客中的文字 (本文改造以获取五个CSDN RSS博客为数据源),而后统计每篇RSS订阅中每个单词出现的次数及各个单词是否在某篇RSS订阅中出现,最后设置过滤原则,过滤掉某些单词,并将最终的单词统计按照博客的title写入到文件中,形成每篇RSS订阅中单词出现次数的数据源。
# coding=utf-8
import feedparser
import re
import codecs
def getwordcounts(url):
d=feedparser.parse(url)
wc={}
for e in d.entries:
if 'summary' in e:
summary=e.summary
else:
summary=e.description
#提取一个单词列表
words=getwords(e.title+' '+summary)
for word in words:
wc.setdefault(word,0)
wc[word] += 1
print d.feed.title
#print wc
return d.feed.title,wc
def getwords(html):
#去除所有的html标记
txt=re.compile(r'<[^>]+>').sub('',html)
#利用所有非字母拆分出单词
words=re.compile(r'[^a-z^A-Z]+').split(txt)
#words=re.compile(r'[^\u4E00-\u9FA5]').split(txt)
return [word.lower() for word in words if word!='']
#传入一个包含n个URL的文件
def ParseUrl():
apcounts={}
wordcounts={} #存放"每篇文章" 中"各个单词 出现的 个数"的字典
csdnList=[line for line in file("csdn.txt")]
for url in csdnList:
title,wc=getwordcounts(url)
wordcounts[title]=wc # 字典的索引是 title,值为单词的字典。
for word,count in wc.items(): #对于某个博客的RSS中,其中各个单词及出现的次数
apcounts.setdefault(word,0)
if count>1:
apcounts[word]+=1 #此word在一篇RSS中出现,则+1
#过滤掉一些单词,过滤原则是:单词在所有博客中出现的比率。比如一个单子只在一篇博客中出现,则其比率很小,则过滤掉.这里采用的样本:csdn的五篇RSS。设置系数为0.2~0.7,
#即过滤掉仅在一篇文中出现的词,和在四篇文中都会出现的词
wordlist=[] #list
for w,bc in apcounts.items():
frac=float(bc)/len(csdnList)
if frac>0.2 and frac <0.7 :
wordlist.append(w) #满足条件的单词才会被作为最终的参考数据
return wordlist,wordcounts
#讲数据写入文件中
def SaveWord(wordlist2,wordcounts2):
out=codecs.open('blogdata.txt','w','utf-8')
out.write('Blog')
for word in wordlist2:
out.write('\t%s' % word) # 讲单词先写入到文件中
out.write('\n') #第一行 是单词,即标头是单词
for blog,wc in wordcounts2.items(): #索引是blog标头,键值是单词及数目
out.write('blog') # 这里本来是要输出blog的title,但是由于有中文,输出有问题,待后续处理
for word in wordlist2:
if word in wc:
out.write('\t%d' % wc[word]) #对于每篇博客,如果博客中的单词在过滤后的word list中,则将其数目输出
else: out.write('\t0') #否则输出个数0
out.write('\n') #写完一篇博客的单词数据,换行
if __name__ =='__main__':
wordlist1,wordcounts1=ParseUrl()
SaveWord(wordlist1,wordcounts1)
最终出来的数据,如下:由于是英文,实际上这些数据在建立关联的时候没有效果。
Blog public shuffle from https quot a github order nbsp name out content org arraybuffer class true spark s com case null android the d val long var limit node e
郭霖的专栏 4 0 6 2 0 0 2 10 2 0 0 12 0 0 15 3 0 0 2 0 16 6 0 0 0 2 0 8 0 0
anzhsoft的技术专栏 0 3 2 0 20 0 0 1 0 0 2 0 2 4 0 0 5 1 0 0 0 0 3 0 4 2 3 1 3 0
雷霄骅(leixiaohua1020)的专栏 2 0 0 4 144 11 4 0 11 6 2 6 2 0 3 0 0 31 9 2 13 17 1 4 0 0 0 0 0 8
yxyhack's blog 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0
摇摆少年梦的技术博客 0 2 0 0 0 4 0 4 0 3 1 0 0 2 0 2 4 4 0 1 0 0 3 4 8 0 3 2 3 2
总结
(1) 后续针对python,需要了解下对于汉字的编码问题。目前代码中博客的title暂时写成了'blog' ,并非是真正的,因为有汉字。
(2) 中间的过滤部分才是关键,需要把哪些词过滤掉,这个后续研究下。
(3) 在实际的应用中,应该有个单独训练出来的数据集(单词集或者中文词组集合)去聚合某些文章的吧?后续再了解下相关主题。