Python基础教程书籍案例:新闻采集(新闻聚合)【上】

这个练习项目来自《Python基础教程(第2版)》,案例原名为“新闻聚合”。

项目分为两个阶段:

  • 第一阶段:通过与NNTP服务器进行交互获取新闻源。
  • 第二阶段:获取不同的新闻源编译为新闻报告并输出不同格式的目标。

这一篇教程,我们先完成第一阶段的目标。

NNTP是“Network News Transfer Protocol”的简称,中文名为“网络新闻传输协议”。

通过这种协议不是很常见,通过它可以传输网络新闻邮件。

NNTP服务器上,往往会存在多个新闻组(或者叫讨论组)。

我们需要从NNTP服务器获取到24小时内,某一个新闻组的新闻邮件,并进行解析,获取到新闻标题以及对应的内容。

这里我们访问的NNTP服务器地址为:http://web.aioe.org,新闻组名称为:comp.lang.python。

为了实现第一阶段目标,我们先进行一次试验。

通过Python内置的nntplib模块与NNTP服务器进行交互,访问目标新闻组。

示例代码:

from nntplib import NNTP

server = NNTP('web.aioe.org')  # 实例化NNTP服务器连接对象
result = server.group('comp.lang.python')  # 连接服务器中的新闻组
print(result)  # 显示输出连接信息
server.quit()  # 关闭连接

运行上方代码,如果正确连接到了指定的新闻组,会显示输出以“211”开头的返回信息。

例如:(‘211 8977 192702 201741 comp.lang.python’, 8977, 192702, 201741, ‘comp.lang.python’)

否则,会给出异常提示。

在完成了这个试验,确定能够正常连接新闻组之后,我们进一步完成项目目标。

1、导入需要使用的模块

除了nntplib模块之外,因为我们要获取近24小时的新闻源,所以还需要datetime模块,帮助我们处理获取新闻的时间。

示例代码:

from nntplib import NNTP
from datetime import date, timedelta

2、创建服务器连接对象、新闻组名称以及新闻时间

示例代码:

server = NNTP('web.aioe.org')  # 实例化NNTP服务器连接对象
yesterday = date.today() - timedelta(days=1)  # 当前时间减去时间间隔
group = 'comp.lang.python'  # 新闻组名称

3、创建生成新闻id的生成器

创建新闻id的生成器是为了能够只获取一个新闻标题与内容。

因为获取内容过多的话,会耗费太多时间。

def get_id():  # 创建新闻id生成器
    ids = server.newnews(group, yesterday)[1]  # 获取近24小时新闻内容中的所有新闻id
    for id in ids:  # 遍历所有新闻id
        yield id  # 生成1个新闻id

在上方代码中,通过newnews()方法能够获取最新一段时间内的所有新闻的数量和id,它是一个元组,类似:(数量描述,[id1,id2,…])。

所以,我们需要获取到返回值中id列表部分,并进行循环遍历,从而生成每一个新闻id。

4、获取一个新闻内容并显示输出

大家可以通过下方代码的注释,理解整个实现过程。

示例代码:

ids = get_id()  # 创建新闻id生成器对象
id = next(ids)  # 获取第1个新闻id
head_data = server.head(id)[1][2]  # 获取新闻的头部内容
body_data = server.body(id)[1][2]  # 获取新闻的主体内容
title = ''  # 创建标题
body = ''  # 创建主体
for line in head_data:  # 遍历头部内容
    if line.decode().lower().startswith('subject:'):  # 如果发现标题特征(“subject:”开头)
        title = line[9:].decode()  # 去除特征文字保存标题内容
for line in body_data:  # 遍历主体内容
    if line.decode().endswith('='):  # 如果行内容以“=”结尾
        line = line[:-1]  # 去除“=”
    if line.decode().endswith('=20'):  # 如果行内容以“=20”结尾
        line = line[:-3] + b'\n'  # 去除“=20”后添加换行符
    body += line.decode()  # 将每行内容组织为新的主体内容

print(title)  # 显示输出标题内容
print('-' * len(title))  # 显示输出和标题字符数量同等的“-”符号
print(body)  # 显示输出主题内容
server.quit()  # 退出与服务器的连接

注意,因为获取到的新闻内容中,字符串都是bytes类型,所以需要进行解码,才能够进行字符串的相关操作。

通过以上步骤,我们就实现了第一阶段的目标。

    原文作者:NicePython
    原文地址: https://zhuanlan.zhihu.com/p/60570402
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞