21.16. nntplib - NNTP协议客户端

源代码: Lib / nntplib.py

此模块定义实现网络新闻传输协议的客户端侧的NNTP类。它可以用于实现新闻阅读器或海报,或自动新闻处理器。It is compatible with RFC 3977 as well as the older RFC 977 and RFC 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对象,表示与在主机主机上运行的NNTP服务器的连接,在端口端口处侦听。可以为套接字连接指定可选的超时如果提供了可选的用户密码 t>,或/.netrc和可选标志usenetrc 为真,AUTHINFO USERAUTHINFO PASS / t8>命令用于标识和验证服务器的用户。如果可选标志readermode为真,则在执行认证之前发送模式 读取器 如果要连接到本地计算机上的NNTP服务器并打算调用读取程序特定的命令(例如group),有时需要使用读取模式。如果遇到意外的NNTPPermanentError,您可能需要设置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对象,表示与在主机主机上运行的NNTP服务器的加密连接,在端口端口处侦听。NNTP_SSL对象具有与NNTP对象相同的方法。如果省略端口,则使用端口563(NNTPS)。ssl_context也是可选的,并且是SSLContext对象。有关最佳做法,请参阅Security considerations所有其他参数的行为与NNTP相同。

注意,对于如下所述的STARTTLS, RFC 4642不建议使用SSL-on-563。但是,一些服务器只支持前者。

版本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 Objects

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

21.16.1.1. Attributes

NNTP.nntp_version

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

版本3.2中的新功能。

NNTP.nntp_implementation

描述NNTP服务器的软件名称和版本的字符串,或None(如果服务器未通知)。

版本3.2中的新功能。

21.16.1.2. Methods

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

许多以下方法采用可选的仅关键字参数文件当提供文件参数时,它必须是为二进制写入打开的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命令。如果用户密码为无,usenetrc为true,则将使用~/.netrc

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

版本3.2中的新功能。

NNTP.starttls(ssl_context=None)

发送STARTTLS命令。这将启用NNTP连接上的加密。ssl_context参数是可选的,应为ssl.SSLContext对象。有关最佳做法,请参阅Security considerations

请注意,在传输验证信息后,可能无法进行验证,如果可能,在NNTP对象初始化期间,默认会进行验证。有关抑制此行为的信息,请参见NNTP.login()

版本3.2中的新功能。

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

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

发送NEWGROUPS命令。date参数应为datetime.datedatetime.datetime对象。返回一对(响应, 组)其中是表示自给定日期如果提供文件,则将为空。

>>> 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是组名或'*'日期newgroups()返回一对(响应, 文章)其中文章是邮件ID列表。

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

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

发送LISTLIST ACTIVE命令。返回一个(响应, 列表)其中列表是表示所有可用组NNTP服务器,可选择匹配模式字符串group_pattern每个元组具有(组, 最后, 第一, 标志)其中是组名称,最后第一个是最后和第一个商品编号,而这些值之一:

  • y:允许来自同伴的本地帖子和文章。
  • m:群组已审核,所有过帐都必须通过审核。
  • n:不允许发布本地内容,仅允许来自同行的文章。
  • j:来自对等体的文章将替换为垃圾组。
  • x:没有本地发布,并且来自对等端的文章被忽略。
  • =foo.bar:文章被归档在foo.bar组中。

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

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

在版本3.2中更改: group_pattern已添加。

NNTP.descriptions(grouppattern)

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

>>> 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命令,其中名称是组名称。选择组作为当前组(如果存在)。返回元组(响应, 计数, 第一, 最后, t5>其中计数是组中的(估计)物品数量,第一是组中的第一个物品编号,t8>是组中的最后一个商品编号,name是组名称。

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

在旧服务器上发送OVER命令或XOVER命令。message_spec can be either a string representing a message id, or a (first, last) tuple of numbers indicating a range of articles in the current group, or a (first, None) tuple indicating a range of articles starting from first to the last article in the current group, or None to select the current article in the current group.

返回一对(响应, 概述)概述(article_number, 概述)元组的列表,由message_spec 每个概述是具有相同数量项目的字典,但此数字取决于服务器。这些项目是消息头(键是较小包头的名称)或元数据项(键是元数据名称前加":")。NNTP规范保证以下项目存在:

  • subjectfromdatemessage-idreferences
  • :bytes元数据:整个原始文章中的字节数(包括标题和正文)
  • :lines metadata:文章正文中的行数

每个项目的值为字符串,如果不存在,则为None

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

>>> _, _, 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?= <[email protected]>'
>>> nntplib.decode_header(over['from'])
'"Martin v. Löwis" <[email protected]>'

版本3.2中的新功能。

NNTP.help(*, file=None)

发送HELP命令。返回一对(响应, 列表)其中列表是帮助字符串列表。

NNTP.stat(message_spec=None)

Send a STAT command, where message_spec is either a message id (enclosed in '<' and '>') or an article number in the current group. 如果省略message_specNone,则会考虑当前组中的当前文章。返回三次(回应, 号码, id)其中号码 number和id是消息ID。

>>> _, _, first, last, _ = s.group('gmane.comp.python.devel')
>>> resp, number, message_id = s.stat(first)
>>> number, message_id
(9099, '<[email protected]>')
NNTP.next()

发送NEXT命令。返回stat()

NNTP.last()

发送LAST命令。返回stat()

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

发送ARTICLE命令,其中message_spec的含义与stat()相同。返回元组(响应, 信息)其中infonamedtuple属性message_id(按此顺序)。number是组中的文章编号(如果信息不可用,则为0),message_id消息ID为字符串,包括包括头部和主体的原始消息的行的列表(不终止换行符)。

>>> resp, info = s.article('<[email protected]>')
>>> info.number
0
>>> info.message_id
'<[email protected]>'
>>> len(info.lines)
65
>>> info.lines[0]
b'Path: main.gmane.org!not-for-mail'
>>> info.lines[1]
b'From: Neal Norwitz <[email protected]>'
>>> 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命令。返回的(或写入到文件)的将仅包含消息头,而不包含正文。

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

article()相同,但发送BODY命令。返回的(或写入到文件)的将仅包含消息正文,而不包含头。

NNTP.post(data)

使用POST命令发布文章。数据参数是为二进制读取打开的file object它应该代表一个格式正确的新闻文章,包括所需的标题。post()方法自动转义以.并附加终止线。

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

NNTP.ihave(message_id, data)

发送IHAVE命令。message_id is the id of the message to send to the server (enclosed in '<' and '>'). 数据参数和返回值与post()相同。

NNTP.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',其中第一最后数字进行搜索。返回一对(响应, 列表),其中列表(id, text),其中id是文章编号(字符串),该文章的请求标题的文本。如果提供了文件参数,则XHDR命令的输出存储在文件中。如果文件是字符串,那么该方法将打开具有该名称的文件,写入该文件,然后关闭它。如果文件file object,则它将开始调用write()来存储命令输出的行。如果提供文件,则返回的列表是空列表。

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

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

NNTP.xpath(id)

Return a pair (resp, path), where path is the directory path to the article with message ID id. 大多数情况下,NNTP服务器管理员未启用此扩展。

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

21.16.2. Utility functions

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

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'