Python urllib2.urlopen()是否实际获取页面?

Python urllib2.urlopen()是否实际获取页面?,python,urllib2,Python,Urllib2,当我使用urllib2.urlopen()时,我正在压缩。它是只读取标题还是实际返回整个网页 IE HTML页面实际上是通过urlopen调用还是read()调用获取的 我要求的原因是这个工作流 我有一个url列表(其中一些带有短url服务) 我只想阅读网页,如果我没有看到该网址之前 我需要调用urlopen()并使用geturl()获取链接指向的最后一个页面(在302重定向之后),这样我就知道我是否已经对它进行了爬网 如果我已经解析了html页面,我不想承担获取html的开销 谢谢 通过查

当我使用urllib2.urlopen()时,我正在压缩。它是只读取标题还是实际返回整个网页

IE HTML页面实际上是通过urlopen调用还是read()调用获取的

我要求的原因是这个工作流

  • 我有一个url列表(其中一些带有短url服务)
  • 我只想阅读网页,如果我没有看到该网址之前
  • 我需要调用urlopen()并使用geturl()获取链接指向的最后一个页面(在302重定向之后),这样我就知道我是否已经对它进行了爬网
  • 如果我已经解析了html页面,我不想承担获取html的开销

谢谢

通过查看页面,我非常确定它可以获得页面的内容。返回的对象包含页面。

使用本地web服务器测试时,
urlib2.urlopen(url)
发出HTTP请求,而
.read()
没有。

urlib2
始终使用HTTP方法
GET
(或
POST
),因此不可避免地会获取整个页面。要改为使用HTTP方法
HEAD
(它只获取头——这足以遵循重定向!),我认为您只需要使用自己的类对
urlib2.Request
进行子类化,并覆盖一个简短的方法:

class MyRequest(urllib2.Request):

    def get_method(self):
        return "HEAD"

并将一个适当初始化的
MyRequest
实例传递给
urllib2.urlopen
,如果您使用,它会智能地发送给您。如果您自己的解决方案已经做得很好,那么就没有必要推出它。

我刚刚用wireshark运行了一个测试。当我调用urllib2.urlopen('url-for-a-700mbyte-file')时,只立即检索到body的头和几个数据包。直到我调用read()时,身体的大部分才通过网络到达。这与我通过阅读httplib模块的源代码所看到的一致

因此,为了回答最初的问题,urlopen()不会通过网络获取整个主体。它获取头文件,通常还有一些正文。调用read()时,将获取正文的其余部分

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

  • 除非您一次读取一个http响应一个字节,否则无法确切知道传入头的长度,因此无法知道在主体启动之前要读取多少字节

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


  • 实际上,由于一些正文通常与标题一起获取,您可能会发现小正文(例如,小html页面)完全是通过urlopen()调用获取的。

    您可以选择使用以下内容读取响应的一部分:

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

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

    对于其他人,您能告诉我们您使用的是什么刮取库吗?实际上,使用Python2.6进行测试表明,在urlopen()调用中,只有一小部分主体通过网络检索。其余部分等待read()被调用。@Forest,HTTP的
    GET
    动词被定义为检索整个页面;可能你没有看到的部分是阻塞了操作系统和网络硬件缓冲区(顺便说一句,这是一件非常糟糕的事情)。我相信问题不是关于HTTP方法,而是关于在urllib2实现的不同阶段网络上发生了什么。查看我的答案了解详细信息。我打赌尚未检索到的正文数据包正在阻塞操作系统或硬件缓冲区(包括服务器和客户端之间的任何位置,可能在路由器上,中间是c)。。。几乎不是一件好事:-(.Alex,我很感谢你的关注,但是没有任何东西会被阻塞。HTTP运行在TCP之上,它实现了流量控制。但是在使用
    urlib2.urlopen
    时获取什么的关注,
    request
    模块有用吗?如果你真的想知道页面
    requests.head的大小(url,headers={'Accept-Encoding':'identity'})。可以使用headers.get('content-length',None)
    。考虑在http中支持范围!
    urllib2.Request(url, None, requestHeaders).read(CHUNKSIZE)