urllib2.urlopen()真的会获取页面吗?

2 投票
6 回答
4607 浏览
提问于 2025-04-15 23:45

我在想,当我使用urllib2.urlopen()的时候,它只是读取了头部信息,还是说它实际上把整个网页都拿回来了呢?

在IE中,HTML页面到底是在urlopen调用的时候就获取了,还是在read()调用的时候获取的呢?

handle = urllib2.urlopen(url)
html = handle.read()

我之所以问这个,是因为我有这样的工作流程……

  • 我有一个网址列表(其中一些是短网址服务)
  • 我只想在之前没有见过这个网址的情况下才读取网页
  • 我需要调用urlopen()并使用geturl()来获取这个链接最终指向的页面(在302重定向之后),这样我就知道我是否已经抓取过这个页面了。
  • 如果我已经解析过那个页面,我不想再花时间去获取HTML内容。

谢谢!

6 个回答

1

在本地网络服务器上测试时,urllib2.urlopen(url) 会发送一个HTTP请求,而 .read() 则不会。

3

urllib2这个库总是使用HTTP的GET(或者POST)方法,所以它每次都会获取整个网页的内容。如果你想用HTTP的HEAD方法(这个方法只获取网页的头部信息,足够用来跟踪重定向!),你只需要创建一个自己的类,继承urllib2.Request,然后重写一个简单的方法:

class MyRequest(urllib2.Request):

    def get_method(self):
        return "HEAD"

接着,把你初始化好的MyRequest实例传给urllib2.urlopen就可以了。

6

我刚用wireshark做了个测试。当我调用urllib2.urlopen('url-for-a-700mbyte-file')时,最开始只获取到了响应的头部和一些数据包的内容。直到我调用read(),大部分的内容才通过网络传过来。这和我查看httplib模块的源代码时看到的情况一致。

所以,回答最初的问题,urlopen()并不是一次性把整个内容都从网络上拿过来。它只获取了头部和通常情况下的一部分内容。剩下的内容是在你调用read()时获取的。

部分内容的获取是正常的,因为:

  1. 除非你一个字节一个字节地读取HTTP响应,否则无法确切知道头部会有多长,因此也无法知道在内容开始之前需要读取多少字节。

  2. HTTP客户端无法控制服务器在每个TCP帧中打包了多少字节作为响应。

实际上,由于通常会和头部一起获取一些内容,你可能会发现小的内容(比如小的HTML页面)在调用urlopen()时会被完全获取。

撰写回答