11.5. 设置 User-Agent

改进 HTTP Web 服务客户端的第一步是使用 User-Agent 正确标识自己。为此,您需要超越基本的 urllib 并深入了解 urllib2

示例 11.4. 介绍 urllib2

>>> import httplib
>>> httplib.HTTPConnection.debuglevel = 1                             1
>>> import urllib2
>>> request = urllib2.Request('http://diveintomark.org/xml/atom.xml') 2
>>> opener = urllib2.build_opener()                                   3
>>> feeddata = opener.open(request).read()                            4
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: Python-urllib/2.1
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Wed, 14 Apr 2004 23:23:12 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
header: ETag: "e8284-68e0-4de30f80"
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
1 如果您仍然打开了上一节示例中的 Python IDE,则可以跳过此步骤,但这会启用 HTTP 调试,以便您可以查看实际通过网络发送的内容以及返回的内容。
2 使用 urllib2 获取 HTTP 资源是一个三步过程,原因很快就会清楚。第一步是创建一个 Request 对象,该对象获取您最终要检索的资源的 URL。请注意,此步骤实际上还没有检索任何内容。
3 第二步是构建一个 URL 打开器。这可以使用任意数量的处理程序,这些处理程序控制如何处理响应。但是,您也可以构建一个没有任何自定义处理程序的打开器,这就是您在这里所做的。本章稍后,当您探索重定向时,您将看到如何定义和使用自定义处理程序。
4 最后一步是告诉打开器使用您创建的 Request 对象打开 URL。从打印的所有调试信息中可以看出,此步骤实际上检索了资源并将返回的数据存储在 feeddata 中。

示例 11.5. 使用 Request 添加标头

>>> request                                                1
<urllib2.Request instance at 0x00250AA8>
>>> request.get_full_url()
http://diveintomark.org/xml/atom.xml
>>> request.add_header('User-Agent',
...     'OpenAnything/1.0 +https://diveintopythonbook.pythonlang.cn/')    2
>>> feeddata = opener.open(request).read()                 3
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: OpenAnything/1.0 +https://diveintopythonbook.pythonlang.cn/   4
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Wed, 14 Apr 2004 23:45:17 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
header: ETag: "e8284-68e0-4de30f80"
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
1 您将继续上一个示例;您已经使用要访问的 URL 创建了一个 Request 对象。
2 使用 Request 对象上的 add_header 方法,您可以向请求添加任意 HTTP 标头。第一个参数是标头,第二个参数是您为该标头提供的值。惯例规定 User-Agent 应采用以下特定格式:应用程序名称,后跟斜杠,再后跟版本号。其余部分是自由格式,您会在实际应用中看到很多变体,但其中某个地方应该包含您的应用程序的 URL。服务器通常会将 User-Agent 与请求的其他详细信息一起记录下来,并且包含应用程序的 URL 允许查看访问日志的服务器管理员在出现问题时与您联系。
3 您之前创建的 opener 对象也可以重复使用,它将再次检索相同的 Feed,但使用您自定义的 User-Agent 标头。
4 在这里,您发送了自定义的 User-Agent,以代替 Python 默认发送的通用 User-Agent。如果仔细观察,您会注意到您定义了一个 User-Agent 标头,但实际上发送了一个 User-agent 标头。看到区别了吗?urllib2 更改了大小写,因此只有第一个字母大写。但这并不重要;HTTP 规定标头字段名称完全不区分大小写。