下面用一段python代码来作示例:
服务器不会为你发送压缩数据,除非你告诉服务器你可以处理压缩数据。
例 11.14. 告诉服务器你想获得压缩数据
>>> import urllib2, httplib
>>> httplib.HTTPConnection.debuglevel = 1
>>> request = urllib2.Request('http://diveintomark.org/xml/atom.xml')
>>> request.add_header('Accept-encoding', 'gzip')
>>> opener = urllib2.build_opener()
>>> f = opener.open(request)
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: Python-urllib/2.1
Accept-encoding: gzip
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Thu, 15 Apr 2004 22:24:39 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Last-Modified: Thu, 15 Apr 2004 19:45:21 GMT
header: ETag: "e842a-3e53-55d97640"
header: Accept-Ranges: bytes
header: Vary: Accept-Encoding
header: Content-Encoding: gzip
header: Content-Length: 6289
header: Connection: close
header: Content-Type: application/atom+xml
例 11.15. 解压缩数据
>>> compresseddata = f.read()
>>> len(compresseddata)
6289
>>> import StringIO
>>> compressedstream = StringIO.StringIO(compresseddata)
>>> import gzip
>>> gzipper = gzip.GzipFile(fileobj=compressedstream)
>>> data = gzipper.read()
>>> print data
<-- rest of feed omitted for brevity -->
>>> len(data)
15955
继续上面的例子,f 是一个从 URL 开启器返回的类文件对象。使用它的 read() 方法将正常地获得非压缩数据,但是因为这个数据已经被 gzip 压缩过,所以这只是获得你想要的最终数据的第一步。 | |
好吧,只是先得有点儿凌乱的步骤。Python 有一个 gzip 模块,它能读取 (当然也能写入) 磁盘上的 gzip 压缩文件。但是磁盘上还没有文件,只在内存里有一个 gzip 压缩缓冲区,并且你不想仅仅为了解压缩而写出一个临时文件。那么怎么做来从内存数据 (compresseddata) 创建类文件对象呢?这需要使用 StringIO 模块。你首次看到 StringIO 模块是在上一章,但现在你会发现它的另一种用法。 | |
现在你可以创建 GzipFile 的一个实例,并且告诉它其中的 “文件” 是一个类文件对象 compressedstream。 | |
这是做所有工作的一行:从 GzipFile 中 “读取” 将会解压缩数据。感到奇妙吗?是的,它确实解压缩了数据。gzipper 是一个类文件对象,它代表一个 gzip 压缩文件。尽管这个 “文件” 并非一个磁盘上的真实文件;但 gzipper 还是从你用 StringIO 包装了压缩数据的类文件对象中 “读取” 数据,而它仅仅是内存中的变量 compresseddata。压缩的数据来自哪呢?最初你从远程 HTTP 服务器下载它,通过从用 urllib2.build_opener 创建的类文件对象中 “读取”。令人吃惊吧,这就是所有的步骤。链条上的每一步都完全不知道上一步在造假。 | |
看看吧,实际的数据 (实际为 15955 bytes)。 |
No comments:
Post a Comment