Python urllib2 与保持活动状态

Posted

技术标签:

【中文标题】Python urllib2 与保持活动状态【英文标题】:Python urllib2 with keep alive 【发布时间】:2009-06-24 09:50:43 【问题描述】:

如何使用 Python 的 urllib2 发出“保持活动”HTTP 请求?

【问题讨论】:

【参考方案1】:

使用urlgrabber 库。这包括支持 HTTP 1.1 和 keepalive 的 urllib2 的 HTTP 处理程序:

>>> import urllib2
>>> from urlgrabber.keepalive import HTTPHandler
>>> keepalive_handler = HTTPHandler()
>>> opener = urllib2.build_opener(keepalive_handler)
>>> urllib2.install_opener(opener)
>>> 
>>> fo = urllib2.urlopen('http://www.python.org')

注意:您应该使用 urlgrabber 版本 3.9.0 或更早版本,因为 keepalive 模块已在版本 3.9.1 中删除

Python 3 的 keepalive 模块有一个 port。

【讨论】:

第二行好像应该是from urlgrabber.keepalive import HTTPHandler A quick port of it I made to python 3.希望能帮助到别人。 感谢@PiPeep - 我在回答中添加了指向您的端口的链接。 该库在标头方面存在一些问题,并且缺少 cookie 支持。您可以通过从 urllib2 和 httplib 复制来修复它,但我建议尝试另一个库。 @speedplane,我相信确实如此,但是,您应该使用更积极维护的github.com/wikier/keepalive,而不是使用该粘贴链接。我已经更新了帖子。编辑应该在经过同行评审后可见。【参考方案2】:

试试urllib3,它有以下特点:

对多个请求(HTTPConnectionPool 和 HTTPSConnectionPool)重复使用相同的套接字连接(带有可选的客户端证书验证)。 文件过帐 (encode_multipart_formdata)。 内置重定向和重试(可选)。 支持 gzip 和 deflate 解码。 线程安全和健全安全。 小型且易于理解的代码库非常适合扩展和构建。如需更全面的解决方案,请查看 Requests。

或者更全面的解决方案 - Requests - 支持来自 version 0.8.0 的 keep-alive(通过在内部使用 urllib3)并具有以下 features:

极其简单的 HEAD、GET、POST、PUT、PATCH、DELETE 请求。 Gevent 支持异步请求。 具有 cookie 持久性的会话。 基本、摘要和自定义身份验证支持。 字典的自动格式编码 请求/响应 cookie 的简单字典接口。 分段文件上传。 Unicode、gzip 和 deflate 响应的自动解码。 完全支持 unicode URL 和域名。

【讨论】:

【参考方案3】:

或者查看httplib的HTTPConnection。

【讨论】:

如何为 HTTPConnection 启用 keep-alive?我尝试将Connection: Keep-Alive 添加到请求和响应标头中,但httplib 仍然在每个请求上重新连接【参考方案4】:

不幸的是,在 urlgrabber 更改为依赖于 pycurl(支持 keep-alive)后,keepalive.py 于 2009 年 9 月 25 日从 urlgrabber 中删除:

http://yum.baseurl.org/gitweb?p=urlgrabber.git;a=commit;h=f964aa8bdc52b29a2c137a917c72eecd4c4dda94

但是,您仍然可以在此处获取 keepalive.py 的最新版本:

http://yum.baseurl.org/gitweb?p=urlgrabber.git;a=blob_plain;f=urlgrabber/keepalive.py;hb=a531cb19eb162ad7e0b62039d19259341f37f3a6

【讨论】:

【参考方案5】:

请注意,urlgrabber 并不完全适用于 python 2.6。我通过在 keepalive.py 中进行以下修改来解决问题(我认为)。

在 keepalive.HTTPHandler.do_open() 中删除这个

     if r.status == 200 or not HANDLE_ERRORS:
         return r

然后插入这个

     if r.status == 200 or not HANDLE_ERRORS:
         # [speedplane] Must return an adinfourl object
         resp = urllib2.addinfourl(r, r.msg, req.get_full_url())
         resp.code = r.status
         resp.msg = r.reason
         return resp

【讨论】:

谢谢,但如果你能解释一下这个修复了什么而不是那个无用的标记评论,那就太好了。 原始的 r 和你的 resp 都是 并且都具有相同的属性。 addinfourl 表示“将 info() 和 geturl() 方法添加到打开文件的类。”但原版已经有了 info() 和 geturl()。无法计算出收益。【参考方案6】:

请避免集体痛苦并改用Requests。默认情况下它会做正确的事情并在适用时使用keep-alive。

【讨论】:

我正在处理一些 NTLM 身份验证,但请求 NTLM 库无法正常工作。但是,urllib2 NTLM 库确实可以正常工作。因此这个问题对我很有帮助。 @JeffersonH​​udson,我不知道这一点。 github.com/requests/requests-ntlm 可能会让你的运气更好 我已经在我的答案中提出了请求,在此之前一年多发布... @PiotrDobrogost,很公平,但我的建议是,让 Requests 成为默认选择。【参考方案7】:

这是一个有点相似的 urlopen(),它确实保持活动状态,尽管它不是线程安全的。

try:
    from http.client import HTTPConnection, HTTPSConnection
except ImportError:
    from httplib import HTTPConnection, HTTPSConnection
import select
connections = 


def request(method, url, body=None, headers=, **kwargs):
    scheme, _, host, path = url.split('/', 3)
    h = connections.get((scheme, host))
    if h and select.select([h.sock], [], [], 0)[0]:
        h.close()
        h = None
    if not h:
        Connection = HTTPConnection if scheme == 'http:' else HTTPSConnection
        h = connections[(scheme, host)] = Connection(host, **kwargs)
    h.request(method, '/' + path, body, headers)
    return h.getresponse()


def urlopen(url, data=None, *args, **kwargs):
    resp = request('POST' if data else 'GET', url, data, *args, **kwargs)
    assert resp.status < 400, (resp.status, resp.reason, resp.read())
    return resp

【讨论】:

以上是关于Python urllib2 与保持活动状态的主要内容,如果未能解决你的问题,请参考以下文章

Python的urllib和urllib2模块

Python爬虫基础urllib2库的get与post方法

仅在对象实例的生命周期内保持 Python 解释器处于活动状态

Python之爬取网页时到的问题——urllib2

python urllib2.urlopen(url).read()乱码

urllib2.HTTPError:HTTP 错误 401:未经授权