Python基础教程:构建新闻聚合器(Usenet/RSS)实战解析
本文基于《Python基础教程》项目四,深入解析新闻聚合器的构建逻辑。通过NewsAgent类整合NNTPSource与SimpleWebSource数据源,结合PlainDestination与HTMLDestination输出格式,实现从Usenet新闻组或URL抓取信息并保存为纯文本或HTML文件的功能。文章详细拆解了分层架构设计,涵盖数据获取、聚合分发及持久化存储的核心代码逻辑,帮助读者理解类似现代RSS订阅器的底层工作原理。
《Python基础教程》中的第四个实战项目聚焦于新闻聚合应用。这类应用在当下已较为少见,甚至鲜有人直接使用,其技术背景通常被称为Usenet(新闻组)。该程序的核心功能是从指定的数据源(此处特指Usenet新闻组)采集信息,并将采集到的内容保存至指定的目标文件中。在存储格式上,程序支持两种模式:纯文本文件和HTML文件。从功能定位来看,该程序的作用类似于当今广泛使用的博客订阅工具或RSS阅读器。
接下来展示具体代码实现,随后对代码结构进行逐一剖析:
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:
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:
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="#" rel="external nofollow" >%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()
bbc_url = 'http://news.bbc.co.uk/text_only.stm'
bbc_title = r'(?s)a href="[^" rel="external nofollow" ]*">\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)
clpa_server = 'news2.neva.ru'
clpa_group = 'alt.sex.telephone'
clpa_window = 1
clpa = NNTPSource(clpa_server,clpa_group,clpa_window)
agent.addSource(clpa)
agent.addDestination(PlainDestination())
agent.addDestination(HTMLDestination('news.html'))
agent.distribute()
if __name__ == '__main__':
runDefaultSetup()
从整体架构来看,程序的核心组件是NewsAgent类。该类负责管理新闻来源列表以及数据存储目标地址。在运行过程中,NewsAgent会分别调用负责获取数据的源类(NNTPSource和SimpleWebSource)以及负责写入数据的目的地类(PlainDestination和HTMLDestination)。由此可以看出架构的分工:NNTPSource专门用于从新闻服务器获取数据,而SimpleWebSource则用于抓取指定URL的数据。PlainDestination的作用是将获取到的内容输出到终端屏幕,而HTMLDestination则负责将数据写入HTML文件中。
基于上述组件分析,主程序的逻辑相对直观,其主要职责是为NewsAgent实例添加具体的信息源对象以及配置输出目的地的地址。
尽管程序逻辑简单,但其设计体现了清晰的分层架构思想。
以上即为本文关于Python新闻聚合器项目的完整解析,希望对读者的学习有所启发,也欢迎大家继续支持本站内容。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













