0
点赞
收藏
分享

微信扫一扫

发现群组(一)建立RSS数据集


        记录读《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 操作符。



       正则表达式

          定义:        

特殊符号组成的字符串,它们描述了这些字符和字符的某种重复方式,因此能按某种模式匹配一个有相似特征的字符串的集合、字符串。

         涉及到的通配符:

          [.........]     匹配字符组中出现的任意一个字符

          [^........]      不匹配此字符集中的任意个字符

          +               匹配(+)前面出现的正则表达式一次或者多次                     [a-z] +\.com  匹配一个或者多个小写字母


举例: [^A-Z^a-z]+   表示:不匹配大小写字母表的字符,即非字母的 字符形式。

         <[^>]+> 表示: 第一个字符是<, 第二个字符不是>。

         常见的函数和方法:

        compile(pattern,flags=0) 对正则表达式模式pattern 进行编译,flags 是可选标志符,并返回一个regex 对象

        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) 在实际的应用中,应该有个单独训练出来的数据集(单词集或者中文词组集合)去聚合某些文章的吧?后续再了解下相关主题。

举报

相关推荐

0 条评论