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添加信息源和输出目的地址的。