urllib2.urlopen()真的会获取页面吗?
我在想,当我使用urllib2.urlopen()的时候,它只是读取了头部信息,还是说它实际上把整个网页都拿回来了呢?
在IE中,HTML页面到底是在urlopen调用的时候就获取了,还是在read()调用的时候获取的呢?
handle = urllib2.urlopen(url)
html = handle.read()
我之所以问这个,是因为我有这样的工作流程……
- 我有一个网址列表(其中一些是短网址服务)
- 我只想在之前没有见过这个网址的情况下才读取网页
- 我需要调用urlopen()并使用geturl()来获取这个链接最终指向的页面(在302重定向之后),这样我就知道我是否已经抓取过这个页面了。
- 如果我已经解析过那个页面,我不想再花时间去获取HTML内容。
谢谢!
6 个回答
在本地网络服务器上测试时,urllib2.urlopen(url)
会发送一个HTTP请求,而 .read()
则不会。
urllib2
这个库总是使用HTTP的GET
(或者POST
)方法,所以它每次都会获取整个网页的内容。如果你想用HTTP的HEAD
方法(这个方法只获取网页的头部信息,足够用来跟踪重定向!),你只需要创建一个自己的类,继承urllib2.Request
,然后重写一个简单的方法:
class MyRequest(urllib2.Request):
def get_method(self):
return "HEAD"
接着,把你初始化好的MyRequest
实例传给urllib2.urlopen
就可以了。
我刚用wireshark做了个测试。当我调用urllib2.urlopen('url-for-a-700mbyte-file')时,最开始只获取到了响应的头部和一些数据包的内容。直到我调用read(),大部分的内容才通过网络传过来。这和我查看httplib模块的源代码时看到的情况一致。
所以,回答最初的问题,urlopen()并不是一次性把整个内容都从网络上拿过来。它只获取了头部和通常情况下的一部分内容。剩下的内容是在你调用read()时获取的。
部分内容的获取是正常的,因为:
除非你一个字节一个字节地读取HTTP响应,否则无法确切知道头部会有多长,因此也无法知道在内容开始之前需要读取多少字节。
HTTP客户端无法控制服务器在每个TCP帧中打包了多少字节作为响应。
实际上,由于通常会和头部一起获取一些内容,你可能会发现小的内容(比如小的HTML页面)在调用urlopen()时会被完全获取。