Python基础教程:构建新闻聚合器(Usenet/RSS)实战解析

花开有时
花开有时
发布时间:2026-10-13| 1人浏览过
原创

本文基于《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新闻聚合器项目的完整解析,希望对读者的学习有所启发,也欢迎大家继续支持本站内容。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。