Skip to main content

21.16. nntplib — NNTP协议客户端

源代码: Lib/nntplib.py


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

这里有两个小例子,说明如何使用它。列出一些关于新闻组的统计数据,并打印最后10篇文章的主题:

>>> s = nntplib.NNTP('news.gmane.org')
>>> 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.org')
>>> 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 对象,表示到在主机 host 上运行的NNTP服务器的连接,在端口 port 侦听。可以为套接字连接指定可选的 timeout。如果提供了可选的 userpassword,或者如果在 /.netrc 中存在合适的凭证,并且可选标志 usenetrc 为真,则 AUTHINFO USERAUTHINFO PASS 命令用于向服务器标识和认证用户。如果可选标志 readermode 为真,则在执行认证之前发送 mode reader 命令。如果要连接到本地计算机上的NNTP服务器并打算调用特定于读取程序的命令(如 group),则有时需要使用阅读器模式。如果您遇到意外的 NNTPPermanentError s,您可能需要设置 readermodeNNTP 类支持 with 语句无条件地使用 OSError 异常并在完成后关闭NNTP连接,例如:

>>> from nntplib import NNTP
>>> with NNTP('news.gmane.org') 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 对象,表示到在主机 host 上运行的NNTP服务器的加密连接,在端口 port 侦听。 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

在响应数据中存在一些错误时引发异常。

21.16.1. NNTP对象

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

21.16.1.1. 属性

NNTP.nntp_version

表示服务器支持的NNTP协议版本的整数。在实践中,这应该是服务器广告 RFC 3977 合规性和 1 为其他人的 2

3.2 新版功能.

NNTP.nntp_implementation

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

3.2 新版功能.

21.16.1.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.org')
>>> 'POST' in s.getcapabilities()
True

3.2 新版功能.

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

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

除非故意延迟,否则登录通常在 NNTP 对象初始化期间执行,并且单独调用此函数不是必需的。要强制认证被延迟,在创建对象时不能设置 userpassword,并且必须将 usenetrc 设置为False。

3.2 新版功能.

NNTP.starttls(ssl_context=None)

发送 STARTTLS 命令。这将启用NNTP连接上的加密。 ssl_context 参数是可选的,应为 ssl.SSLContext 对象。请阅读 安全注意事项 的最佳做法。

注意,这可能不会在认证信息被发送之后完成,并且如果可能,在 NNTP 对象初始化期间默认地发生认证。有关抑制此行为的信息,请参阅 NNTP.login()

3.2 新版功能.

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

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

发送 NEWGROUPS 命令。 date 参数应为 datetime.datedatetime.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)

发送 LISTLIST ACTIVE 命令。返回一对 (response, list),其中 list 是表示从此NNTP服务器可用的所有组的元组的列表,可选地匹配模式字符串 group_pattern。每个元组具有 (group, last, first, flag) 的形式,其中 group 是组名,lastfirst 是最后和第一个文章编号,flag 通常取这些值之一:

  • y:允许来自同行的本地帖子和文章。

  • m:小组已审核,所有帖子都必须批准。

  • n:不允许当地发布,只有同行的文章。

  • j:来自对等体的文章被替换为垃圾组。

  • x:没有本地发布,同行的文章被忽略。

  • =foo.bar:相反,在 foo.bar 组中提交文章。

如果 flag 具有另一个值,则新闻组的状态应被视为未知。

此命令可以返回非常大的结果,特别是如果没有指定 group_pattern。最好是离线缓存结果,除非你真的需要刷新它们。

在 3.2 版更改: 加入 group_pattern

NNTP.descriptions(grouppattern)

发送 LIST NEWSGROUPS 命令,其中 grouppatternRFC 3977 中指定的wildmat字符串(本质上与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 的描述。如果多个组匹配(如果’group’是一个真正的wildmat字符串),返回第一个匹配。如果没有匹配,返回一个空字符串。

这会从服务器中删除响应代码。如果需要响应代码,请使用 descriptions()

NNTP.group(name)

发送 GROUP 命令,其中 name 是组名称。选择组作为当前组(如果存在)。返回一个元组 (response, count, first, last, name),其中 count 是组中的(估计)文章数,first 是组中的第一个文章编号,last 是组中的最后一个文章编号,name 是组名称。

NNTP.over(message_spec, *, file=None)

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

返回一对 (response, overviews)overviews(article_number, overview) 元组的列表,message_spec 选择的每个文章一个。每个 overview 是一个具有相同数量项目的字典,但这个数字取决于服务器。这些项目是消息头(键是较小包头的名称)或元数据项(键是元数据名称的前缀与 ":")。 NNTP规范保证存在以下项目:

  • subjectfromdatemessage-idreferences 报头

  • :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 是消息标识(包含在 '<''>' 中)或当前组中的文章编号。如果省略 message_specNone,则考虑当前组中的当前项目。返回三 (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 是具有三个属性 numbermessage_idlines (以此顺序)的 namedtuplenumber 是组中的文章编号(如果信息不可用,则为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 参数是为二进制读取打开的 file object,或任何可迭代的字节对象(表示要发布的文章的原始行)。它应该代表一个格式正确的新闻文章,包括所需的标题。 post() 方法自动转义以 . 开头的行并附加终止行。

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

NNTP.ihave(message_id, data)

发送 IHAVE 命令。 message_id 是要发送到服务器的消息的ID(包含在 '<''>' 中)。 data 参数和返回值与 post() 的相同。

NNTP.date()

返回一对 (response, date)date 是包含服务器的当前日期和时间的 datetime 对象。

NNTP.slave()

发送 SLAVE 命令。返回服务器的 response

NNTP.set_debuglevel(level)

设置实例的调试级别。这控制打印的调试输出量。默认值 0 不产生调试输出。 1 的值产生中等量的调试输出,通常每个请求或响应都有一行。 2 或更高的值产生最大量的调试输出,记录在连接上发送和接收的每行(包括消息文本)。

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

NNTP.xhdr(hdr, str, *, file=None)

发送 XHDR 命令。 hdr 参数是报头关键字,例如 'subject'str 参数应该具有 'first-last' 的形式,其中 firstlast 是要搜索的第一个和最后一个商品编号。返回一对 (response, list),其中 list 是对 (id, text) 的列表,其中 id 是项目编号(作为字符串),text 是该文章的请求标题的文本。如果提供了 file 参数,则 XHDR 命令的输出存储在文件中。如果 file 是字符串,那么该方法将打开一个具有该名称的文件,写入该文件,然后关闭它。如果 filefile object,那么它将开始调用 write() 来存储命令输出的行。如果提供了 file,则返回的 list 是空列表。

NNTP.xover(start, end, *, file=None)

发送 XOVER 命令。 startend 是定义要选择的文章范围的文章号。返回值与 over() 相同。建议使用 over(),因为它会自动使用较新的 OVER 命令(如果可用)。

NNTP.xpath(id)

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

3.3 版后已移除: XPATH扩展名未被主动使用。

21.16.2. 效用函数

该模块还定义了以下效用函数:

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'