发现群组(一)建立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 操作符。

       正则表达式

          定义:        

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

         涉及到的通配符:

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

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

          +               匹配(+)前面出现的正则表达式一次或者多次                     [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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

proware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值