关于python:urllib2.urlopen()实际上是否获取页面?

Does urllib2.urlopen() actually fetch the page?

我在使用urllib2.urlopen()时只是为了读取头文件,还是实际带回整个网页?

IE是否真的在urlopen调用或read()调用上获取HTML页面?

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

我问的原因是这个工作流程......

  • 我有一个网址列表(其中一些有短网址服务)
  • 如果我之前没有看过该网址,我只想阅读该网页
  • 我需要调用urlopen()并使用geturl()来获取链接所在的最终页面(在302重定向之后),所以我知道我是否已经抓取它了。
  • 如果我已经解析了那个页面,我不想承担必须抓取html的开销。

谢谢!


我刚用wireshark进行测试。当我调用urllib2.urlopen('url-for-a-700mbyte-file')时,只会立即检索标题和一些正文包。直到我打电话给read(),大部分身体都来到了网络。这与我通过阅读httplib模块的源代码看到的相符。

因此,为了回答原始问题,urlopen()不会通过网络获取整个主体。它取出标题,通常是一些正文。当你调用read()时,将获取正文的其余部分。

部分正文提取是预期的,因为:

  • 除非您一次读取一个字节的http响应,否则无法准确知道传入标头的长度,因此无法知道在正文开始之前要读取多少字节。

  • http客户端无法控制服务器捆绑到响应的每个tcp帧中的字节数。

  • 实际上,由于一些主体通常与标题一起被提取,您可能会发现在urlopen()调用中完全获取了小主体(例如小的html页面)。


    urllib2始终使用HTTP方法GET(或POST),因此不可避免地会获得整页。要使用HTTP方法HEAD(只获取标题 - 足以跟随重定向!),我认为您只需要使用自己的类继承urllib2.Request并覆盖一个简短方法:

    1
    2
    3
    4
    class MyRequest(urllib2.Request):

        def get_method(self):
            return"HEAD"

    并将适当初始化的MyRequest实例传递给urllib2.urlopen


    使用本地Web服务器进行测试时,urllib2.urlopen(url)会触发HTTP请求,而.read()则不会。


    您可以选择阅读部分响应,例如...

    1
    urllib2.Request(url, None, requestHeaders).read(CHUNKSIZE)

    这只是从服务器读取CHUNKSIZE字节,我刚检查过。


    另外,如果您使用Scrapy,它会智能地为您完成HEAD。如果已经在其他地方做得很好,那么推出自己的解决方案毫无意义。


    从查看文档和源代码我很确定它获取页面的内容。返回的对象包含页面。