nntplib — NNTP 协议客户端 — Python 文档

来自菜鸟教程
Python/docs/3.8/library/nntplib
跳转至:导航、​搜索

nntplib — NNTP 协议客户端

源代码: :source:`Lib/nntplib.py`



该模块定义了类 NNTP,它实现了网络新闻传输协议的客户端。 它可用于实现新闻阅读器或海报,或自动化新闻处理器。 它兼容 RFC 3977 以及旧的 RFC 977 和 RFC 2980[ X121X]。

下面是两个如何使用它的小例子。 要列出有关新闻组的一些统计信息并打印最近 10 篇文章的主题:

>>> s = nntplib.NNTP('news.gmane.io')
>>> resp, count, first, last, name = s.group('gmane.comp.python.committers')
>>> print('Group', name, 'has', count, 'articles, range', first, 'to', last)
Group gmane.comp.python.committers has 1096 articles, range 1 to 1096
>>> resp, overviews = s.over((last - 9, last))
>>> for id, over in overviews:
...     print(id, nntplib.decode_header(over['subject']))
...
1087 Re: Commit privileges for Łukasz Langa
1088 Re: 3.2 alpha 2 freeze
1089 Re: 3.2 alpha 2 freeze
1090 Re: Commit privileges for Łukasz Langa
1091 Re: Commit privileges for Łukasz Langa
1092 Updated ssh key
1093 Re: Updated ssh key
1094 Re: Updated ssh key
1095 Hello fellow committers!
1096 Re: Hello fellow committers!
>>> s.quit()
'205 Bye!'

从二进制文件发布文章(假设文章具有有效标题,并且您有权在特定新闻组上发布):

>>> s = nntplib.NNTP('news.gmane.io')
>>> f = open('article.txt', 'rb')
>>> s.post(f)
'240 Article posted successfully.'
>>> s.quit()
'205 Bye!'

模块本身定义了以下类:

class nntplib.NNTP(host, port=119, user=None, password=None, readermode=None, usenetrc=False[, timeout])

返回一个新的 NNTP 对象,表示与运行在主机 主机 上的 NNTP 服务器的连接,监听端口 端口 。 可以为套接字连接指定可选的 timeout。 如果提供了可选的 user 和 password,或者 /.netrc 中存在合适的凭据并且可选标志 usenetrc 为真,则 [ X171X] 和 AUTHINFO PASS 命令用于向服务器识别和验证用户。 如果可选标志 readermode 为真,则在执行身份验证之前发送 mode reader 命令。 如果您连接到本地机器上的 NNTP 服务器并打算调用特定于阅读器的命令,例如 group,有时需要阅读器模式。 如果您收到意外的 NNTPPermanentErrors,您可能需要设置 readermode。 NNTP 类支持 [X39X]with 语句无条件消耗 OSError 异常并在完成后关闭 NNTP 连接,例如:

>>> from nntplib import NNTP
>>> with NNTP('news.gmane.io') as n:
...     n.group('gmane.comp.python.committers')
... 
('211 1755 1 1755 gmane.comp.python.committers', 1755, 1, 1755, 'gmane.comp.python.committers')
>>>

在 3.2 版更改:usenetrc 现在默认为 False。

在 3.3 版更改:添加了对 with 语句的支持。

class nntplib.NNTP_SSL(host, port=563, user=None, password=None, ssl_context=None, readermode=None, usenetrc=False[, timeout])

返回一个新的 NNTP_SSL 对象,表示与运行在主机 主机 上的 NNTP 服务器的加密连接,监听端口 端口 。 NNTP_SSL 对象与 NNTP 对象具有相同的方法。 如果省略 port,则使用端口 563 (NNTPS)。 ssl_context 也是可选的,是一个 SSLContext 对象。 请阅读 安全注意事项 以获得最佳实践。 所有其他参数的行为与 NNTP 相同。

请注意,根据 RFC 4642,不鼓励 SSL-on-563,支持 STARTTLS,如下所述。 但是,有些服务器只支持前者。

3.2 版中的新功能。

3.4 版更改: 该类现在支持使用 ssl.SSLContext.check_hostname 和 服务器名称指示 进行主机名检查(请参阅 ssl.HAS_SNI )。

exception nntplib.NNTPError
派生自标准异常 Exception,这是由 nntplib 模块引发的所有异常的基类。 此类的实例具有以下属性:
response
服务器的响应(如果可用),作为 str 对象。
exception nntplib.NNTPReplyError
从服务器收到意外回复时引发异常。
exception nntplib.NNTPTemporaryError
收到 400-499 范围内的响应代码时引发异常。
exception nntplib.NNTPPermanentError
收到 500-599 范围内的响应代码时引发异常。
exception nntplib.NNTPProtocolError
当从服务器收到不以 1-5 范围内的数字开头的回复时引发异常。
exception nntplib.NNTPDataError
响应数据中存在错误时引发异常。

NNTP 对象

连接时,NNTP 和 NNTP_SSL 对象支持以下方法和属性。

属性

NNTP.nntp_version

一个整数,表示服务器支持的 NNTP 协议版本。 实际上,对于广告 RFC 3977 合规性的服务器,这应该是 2,而对于其他服务器,这应该是 1。

3.2 版中的新功能。

NNTP.nntp_implementation

描述 NNTP 服务器的软件名称和版本的字符串,如果服务器未通告,则为 None。

3.2 版中的新功能。


方法

在几乎所有方法的返回元组中作为第一项返回的 response 是服务器的响应:一个以三位数代码开头的字符串。 如果服务器的响应指示错误,则该方法会引发上述异常之一。

以下许多方法采用可选的仅关键字参数 file。 当提供 file 参数时,它必须是为二进制写入打开的 file object,或要写入的磁盘文件的名称。 然后该方法会将服务器返回的任何数据(响应行和终止点除外)写入文件; 该方法通常返回的任何行、元组或对象列表都将为空。

3.2 版更改: 以下许多方法已被重新设计和修复,这使得它们与 3.1 版本不兼容。


NNTP.quit()
发送 QUIT 命令并关闭连接。 一旦调用了此方法,就不应调用 NNTP 对象的其他方法。
NNTP.getwelcome()
返回服务器发送的欢迎消息以回复初始连接。 (此消息有时包含可能与用户相关的免责声明或帮助信息。)
NNTP.getcapabilities()

返回服务器通告的 RFC 3977 能力,作为 dict 实例映射能力名称到(可能为空)值列表。 在不理解 CAPABILITIES 命令的旧服务器上,将返回一个空字典。

>>> s = NNTP('news.gmane.io')
>>> 'POST' in s.getcapabilities()
True

3.2 版中的新功能。

NNTP.login(user=None, password=None, usenetrc=True)

使用用户名和密码发送 AUTHINFO 命令。 如果 user 和 password 为 None 且 usenetrc 为真,则将尽可能使用来自 ~/.netrc 的凭据。

除非故意延迟,登录通常在NNTP对象初始化期间进行,不需要单独调用该函数。 要强制延迟验证,在创建对象时不得设置user或password,并且必须将usenetrc设置为False。

3.2 版中的新功能。

NNTP.starttls(context=None)

发送 STARTTLS 命令。 这将在 NNTP 连接上启用加密。 context 参数是可选的,应该是一个 ssl.SSLContext 对象。 请阅读 安全注意事项 以获得最佳实践。

请注意,这可能不会在传输身份验证信息后进行,并且在 NNTP 对象初始化期间,如果可能,默认情况下会进行身份验证。 有关抑制此行为的信息,请参阅 NNTP.login()。

3.2 版中的新功能。

在 3.4 版更改:该方法现在支持使用 ssl.SSLContext.check_hostname 和 Server Name Indication 进行主机名检查(请参阅 ssl.HAS_SNI )。

NNTP.newgroups(date, *, file=None)

发送 NEWGROUPS 命令。 date 参数应该是 datetime.date 或 datetime.datetime 对象。 返回一对 (response, groups),其中 groups 是一个列表,表示自给定 date 以来新的组。 但是,如果提供 file,则 groups 将为空。

>>> from datetime import date, timedelta
>>> resp, groups = s.newgroups(date.today() - timedelta(days=3))
>>> len(groups) 
85
>>> groups[0] 
GroupInfo(group='gmane.network.tor.devel', last='4', first='1', flag='m')
NNTP.newnews(group, date, *, file=None)

发送 NEWNEWS 命令。 这里,group 是组名或 '*',date 与 newgroups() 的含义相同。 返回一对 (response, articles),其中 articles 是消息 ID 列表。

NNTP 服务器管理员经常禁用此命令。

NNTP.list(group_pattern=None, *, file=None)

发送 LIST 或 LIST ACTIVE 命令。 返回一对 (response, list),其中 list 是表示此 NNTP 服务器可用的所有组的元组列表,可选择匹配模式字符串 group_pattern。 每个元组的形式为 (group, last, first, flag),其中 group 是组名,last 和 first 是最后和第一个文章编号,[ X150X]flag 通常采用以下值之一:

  • y:允许本地发帖和同行文章。

  • m:该群组已审核,所有帖子必须获得批准。

  • n:不允许本地发帖,只能发同行文章。

  • j:来自同行的文章被提交到垃圾组。

  • x:无本地发帖,忽略同行文章。

  • =foo.bar:文章改为在foo.bar组中归档。

如果 flag 有另一个值,那么新闻组的状态应该被认为是未知的。

此命令可以返回非常大的结果,尤其是在未指定 group_pattern 的情况下。 最好离线缓存结果,除非您确实需要刷新它们。

3.2 版更改:添加了 group_pattern。

NNTP.descriptions(grouppattern)

发送 LIST NEWSGROUPS 命令,其中 grouppattern 是 RFC 3977 中指定的通配符字符串(它本质上与 DOS 或 UNIX shell 通配符相同字符串)。 返回一对 (response, descriptions),其中 descriptions 是将组名称映射到文本描述的字典。

>>> resp, descs = s.descriptions('gmane.comp.python.*')
>>> len(descs) 
295
>>> descs.popitem() 
('gmane.comp.python.bio.general', 'BioPython discussion list (Moderated)')
NNTP.description(group)

获取单个组 组 的描述。 如果多个组匹配(如果 'group' 是真正的 Wildmat 字符串),则返回第一个匹配项。 如果没有组匹配,则返回一个空字符串。

这省略了来自服务器的响应代码。 如果需要响应代码,请使用 descriptions()。

NNTP.group(name)
发送 GROUP 命令,其中 name 是组名。 该组被选为当前组(如果存在)。 返回一个元组 (response, count, first, last, name),其中 count 是组中的(估计)文章数,first 是组中的第一个文章编号,last[ X163X]为组中最后一个货号,name为组名。
NNTP.over(message_spec, *, file=None)

在旧服务器上发送 OVER 命令或 XOVER 命令。 message_spec 可以是表示消息 ID 的字符串,也可以是表示当前组中文章范围的 (first, last) 数字元组,或表示范围的 (first, None) 元组文章从first到当前组中的最后一篇,或None选择当前组中的当前文章。

返回一对 (response, overviews)。 overviews 是一个 (article_number, overview) 元组列表,每个 message_spec 选择的文章对应一个。 每个 overview 都是一个字典,项目数相同,但这个数字取决于服务器。 这些项目要么是消息标题(关键是小写的标题名称),要么是元数据项目(关键是元数据名称加上 ":")。 NNTP 规范保证以下项目存在:

  • subject、from、date、message-id 和 references 标头

  • :bytes 元数据:整个原始文章的字节数(包括标题和正文)

  • :lines 元数据:文章正文的行数

每个项目的值要么是一个字符串,要么是 None(如果不存在)。

当标头值可能包含非 ASCII 字符时,建议对标头值使用 decode_header() 函数:

>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, overviews = s.over((last, last))
>>> art_num, over = overviews[0]
>>> art_num
117216
>>> list(over.keys())
['xref', 'from', ':lines', ':bytes', 'references', 'date', 'message-id', 'subject']
>>> over['from']
'=?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?= <martin@v.loewis.de>'
>>> nntplib.decode_header(over['from'])
'"Martin v. Löwis" <martin@v.loewis.de>'

3.2 版中的新功能。

NNTP.help(*, file=None)
发送 HELP 命令。 返回一对 (response, list),其中 list 是帮助字符串列表。
NNTP.stat(message_spec=None)

发送 STAT 命令,其中 message_spec 是消息 ID(包含在 '<' 和 '>' 中)或当前组中的文章编号。 如果省略 message_spec 或 None,则考虑当前组中的当前文章。 返回一个三元组 (response, number, id),其中 number 是文章编号,id 是消息 ID。

>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, number, message_id = s.stat(first)
>>> number, message_id
(9099, '<20030112190404.GE29873@epoch.metaslash.com>')
NNTP.next()
发送 NEXT 命令。 返回 stat()。
NNTP.last()
发送 LAST 命令。 返回 stat()。
NNTP.article(message_spec=None, *, file=None)

发送 ARTICLE 命令,其中 message_spec 与 stat() 的含义相同。 返回一个元组 (response, info),其中 info 是一个 namedtuple,具有三个属性 number、message_id 和 lines[ X142X](按此顺序)。 number 是群中的文章编号(如果信息不可用则为 0),message_id 为字符串的消息 ID,以及 lines 列表包含原始消息的行(不终止换行符),包括标题和正文。

>>> resp, info = s.article('<20030112190404.GE29873@epoch.metaslash.com>')
>>> info.number
0
>>> info.message_id
'<20030112190404.GE29873@epoch.metaslash.com>'
>>> len(info.lines)
65
>>> info.lines[0]
b'Path: main.gmane.org!not-for-mail'
>>> info.lines[1]
b'From: Neal Norwitz <neal@metaslash.com>'
>>> info.lines[-3:]
[b'There is a patch for 2.3 as well as 2.2.', b'', b'Neal']
NNTP.head(message_spec=None, *, file=None)
与 article() 相同,但发送 HEAD 命令。 返回(或写入 file)的 lines 将仅包含消息标题,而不包含正文。
NNTP.body(message_spec=None, *, file=None)
与 article() 相同,但发送 BODY 命令。 返回(或写入 file)的 lines 将仅包含邮件正文,而不包含标题。
NNTP.post(data)

使用 POST 命令发表文章。 data 参数是为二进制读取而打开的 文件对象 ,或任何可迭代的字节对象(代表要发布的文章的原始行)。 它应该代表一篇格式良好的新闻文章,包括所需的标题。 post() 方法自动转义以 . 开头的行并附加终止行。

如果该方法成功,则返回服务器的响应。 如果服务器拒绝发布,则会引发 NNTPReplyError。

NNTP.ihave(message_id, data)
发送 IHAVE 命令。 message_id 是要发送到服务器的消息的 id(包含在 '<' 和 '>' 中)。 data 参数和返回值与 post() 相同。
NNTP.date()
返回一对 (response, date)。 date 是一个 datetime 对象,包含服务器的当前日期和时间。
NNTP.slave()
发送 SLAVE 命令。 返回服务器的 响应 。
NNTP.set_debuglevel(level)
设置实例的调试级别。 这控制打印的调试输出量。 默认值 0 不产生调试输出。 1 的值会产生适量的调试输出,通常每个请求或响应只有一行。 2 或更高的值会产生最大数量的调试输出,记录连接上发送和接收的每一行(包括消息文本)。

以下是 RFC 2980 中定义的可选 NNTP 扩展。 其中一些已被 RFC 3977 中的新命令取代。

NNTP.xhdr(hdr, str, *, file=None)
发送 XHDR 命令。 hdr 参数是标题关键字,例如 'subject'。 str 参数的格式应为 'first-last',其中 first 和 last 是要搜索的第一个和最后一个文章编号。 返回一对 (response, list),其中 list 是对 (id, text) 的列表,其中 id 是商品编号(作为字符串)和 ]text 是该文章请求标题的文本。 如果提供 file 参数,则 XHDR 命令的输出存储在文件中。 如果 file 是一个字符串,那么该方法将打开一个具有该名称的文件,写入然后关闭它。 如果 file 是一个 file object,那么它将开始调用 write() 来存储命令输出的行。 如果提供了 file,则返回的 list 是一个空列表。
NNTP.xover(start, end, *, file=None)
发送 XOVER 命令。 start 和 end 是界定要选择的文章范围的文章编号。 返回值与 over() 相同。 建议改用 over(),因为它会自动使用较新的 OVER 命令(如果可用)。
NNTP.xpath(id)

返回一对(resp, path),其中path是消息ID为id的文章的目录路径。 大多数情况下,NNTP 服务器管理员不会启用此扩展。

自 3.3 版起已弃用:未主动使用 XPATH 扩展。


实用功能

该模块还定义了以下实用程序函数:

nntplib.decode_header(header_str)

解码标头值,取消转义任何转义的非 ASCII 字符。 header_str 必须是一个 str 对象。 返回未转义的值。 建议使用此函数以人类可读的形式显示一些标题:

>>> decode_header("Some subject")
'Some subject'
>>> decode_header("=?ISO-8859-15?Q?D=E9buter_en_Python?=")
'Débuter en Python'
>>> decode_header("Re: =?UTF-8?B?cHJvYmzDqG1lIGRlIG1hdHJpY2U=?=")
'Re: problème de matrice'