python基础教程总结15——4 新闻聚合

NNTP:网络新闻传输协议,Network News Transfer Protocol

目标:  

  从多种不同的来源收集新闻;

  用户可以轻松添加新的新闻来源(甚至是新类型的新闻来源;

  程序可以将编译好的新闻报告分派出多个不同格式的目标;

  程序可以轻松添加新的目标(甚至是新种类的目标)

 

1. 简单的新闻代理程序

1)NNTP类对象:使用NNTP服务器名字实例化;

      newnews方法: 返回给定日期时间之后发布的文章;

    head方法:提供关于文件(主要是主题)的各种信息;  

    body方法:提供文章的正文文本

2)time.localtime([ sec ])   : 将秒数sec转换为time.struct_time类型的对象

   time.strftime(format[, t])  : format -- 格式字符串,   t -- 可选的参数t是一个struct_time对象      返回以可读字符串表示的时间

#newsagent1.py
from nntplib import NNTP
from time import strftime, time, localtime

day=24*60*60
yesterday=localtime(time()-day)
date=strftime('%y%m%d', yesterday)
hour=strftime('%H%M%S', yesterday)

servername='news.foo.bar'  #虚构的服务器名
group='comp.lang.python.announce'
sever=NNTP(servername)

ids=server.newnews(group.date.hour)[1] #提取newnews方法返回元组的第二个参数,即发表文章的ID号

for id in ids:
    head=server.head(id)[3]  #返回信息元组的第四个元素:字符串列表(数据本身)
    for line in head:
        if line.lower().startswitch('subject:'):
            subject= line[9:]
            break

    body=server.body(id)[3]

    print subject
    print '-'*len(subject)
    print '\n'.join(body)

server.quit()

 

2. 改进

from nntplib import NNTP
from time import strftime,time,localtime
from email import message_from_string
from urllib import urlopen
import textwrap
import re

day = 24*60*60

def wrap(string,max=70):
        '''
        将字符串调整为最大行宽
        '''
        return '\n'.join(textwrap.wrap(string)) + '\n'

class NewsAgent:
        '''
        可以从新闻来源获取新闻项目并且发布到新闻目标的对象
        '''
        def __init__(self):
                self.sources = []
                self.destinations = []

        def addSource(self,source):
                self.sources.append(source)

        def addDestination(self,dest):
                self.destinations.append(dest)

        def distribute(self):
               '''
               从所有来源获取所有新闻项目并且发布到所有目标
               '''

                items = []
                for source in self.sources:
                        items.extend(source.getItems())
                for dest in self.destinations:
                        dest.receiveItems(items)

class NewsItem:
        '''
        包括标题和主题文本的简单新闻项目
         '''
        def __init__(self,title,body):
                self.title = title
                self.body = body

class NNTPSource:
        '''
        从NNTP组中获取新闻项目的新闻来源
        '''
        def __init__(self,servername,group,window):
                self.servername = servername
                self.group = group
                self.window = window

        def getItems(self):
                start = localtime(time() - self.window*day)
                date = strftime('%y%m%d',start)
                hour = strftime('%H%M%S',start)

                server = NNTP(self.servername)

                ids = server.newnews(self.group,date,hour)[1]

                for id in ids:
                        lines = server.article(id)[3]
                        message = message_from_string('\n'.join(lines))

                        title = message['subject']
                        body = message.get_payload()
                        if message.is_multipart():
                                body = body[0]

                        yield NewsItem(title,body)

                server.quit()

class SimpleWebSource:
        '''
          使用正则表达式从网页中提取新闻项目的新闻来源
        '''

        def __init__(self,url,titlePattern,bodyPattern):
                self.url = url
                self.titlePattern = re.compile(titlePattern)
                self.bodyPattern = re.compile(bodyPattern)

        def getItems(self):
                text = urlopen(self.url).read()
                titles = self.titlePattern.findall(text)
                bodies = self.bodyPattern.findall(text)
                for title.body in zip(titles,bodies):
                        yield NewsItem(title,wrap(body))

class PlainDestination:
        '''
        将所有的新闻项目格式化为纯文本的新闻目录类
        '''

        def receiveItems(self,items):
                for item in items:
                        print item.title
                        print '-'*len(item.title)
                        print item.body

class HTMLDestination:
        '''
        将所有的新闻项目格式化为HTML的目标类
        '''
        def __init__(self,filename):
                self.filename = filename

        def receiveItems(self,items):
                out = open(self.filename,'w')
                print >> out,'''
                <html>
                <head>
                 <title>Today's News</title>
                </head>
                <body>
                <h1>Today's News</hi>
                '''

                print >> out, '<ul>'
                id = 0
                for item in items:
                        id += 1
                        print >> out, '<li><a href="#">%s</a></li>' % (id,item.title)
                print >> out, '</ul>'

                id = 0
                for item in items:
                        id += 1
                        print >> out, '<h2><a name="%i">%s</a></h2>' % (id,item.title)
                        print >> out, '<pre>%s</pre>' % item.body

                print >> out, '''
                </body>
                </html>
                '''
def runDefaultSetup():
       '''
        来源和目标的默认位置,可以修改
       '''

        agent = NewsAgent()

       '''
        从BBS新闻站获取新闻的SimpleWebSource
       '''
        bbc_url = 'http://news.bbc.co.uk/text_only.stm'
        bbc_title = r'(?s)a href="[^"]*">\s*<b>\s*(.*?)\s*</b>'
        bbc_body = r'(?s)</a>\s*<br/>\s*(.*?)\s*<'
        bbc = SimpleWebSource(bbc_url, bbc_title, bbc_body)

        agent.addSource(bbc)

        '''
        从comp.lang.python.announce获取新闻的NNTPSource
        '''
        clpa_server = 'news2.neva.ru'
        clpa_group = 'alt.sex.telephone'
        clpa_window = 1
        clpa = NNTPSource(clpa_server,clpa_group,clpa_window)

        agent.addSource(clpa)
         
       '''
        增加纯文本目标和HTML目标
       '''
        agent.addDestination(PlainDestination())
        agent.addDestination(HTMLDestination('news.html'))
      
        '''
         发布新闻项目
        '''
        agent.distribute()
if __name__ == '__main__':
        runDefaultSetup()            

  这个程序,首先从整体上进行分析,重点部分在于NewsAgent,它的作用是存储新闻来源,存储目标地址,然后在分别调用来源服务器(NNTPSource以及SimpleWebSource)以及写新闻的类(PlainDestination和HTMLDestination)。所以从这里也看的出,NNTPSource是专门用来获取新闻服务器上的信息的,SimpleWebSource是获取一个url上的数据的。而PlainDestination和HTMLDestination的作用很明显,前者是用来输出获取到的内容到终端的,后者是写数据到html文件中的。

有了这些分析,然后在来看主程序中的内容,主程序就是来给NewsAgent添加信息源和输出目的地址的。

 

posted @ 2015-07-28 15:26  zxqstrong  阅读(1131)  评论(0编辑  收藏  举报