【问题标题】:Python: Downloading files from HTTP serverPython:从 HTTP 服务器下载文件
【发布时间】:2011-01-31 20:36:56
【问题描述】:

我已经编写了一些 python 脚本来从 HTTP 网站下载图像,但是因为我使用的是 urllib2,所以它会关闭现有连接,然后在打开另一个连接之前打开另一个连接。我不太了解网络,但这可能会大大减慢速度,并且一次抓取 100 张图像需要相当长的时间。

我开始寻找 pycurl 或 httplib 等其他替代方案,但发现与 urllib2 相比,它们难以计算,并且没有找到很多我可以直接使用的代码 sn-ps。

简单地说,我将如何建立与网站的持久连接并下载许多文件,然后仅在完成后关闭连接? (可能是显式调用关闭它)

【问题讨论】:

  • 与一般图像的大小相比,我认为这几个字节的网络开销并不算多。除非你有相反的证据,否则这可能不值得麻烦。
  • Dive into Python 完成了类似的任务。
  • 我不同意网络开销并没有太大的区别。因为 auf TCP 慢启动 (en.wikipedia.org/wiki/Slow-start) 每个新创建的连接一开始都会很慢。因此,如果数据足够大,重用相同的 TCP 连接会有所不同(我认为 100 张图片将在 10 到 100 MB 之间)
  • “我要与网站建立持久连接吗” 好问题。取决于网络服务器。您需要检查标头以查看支持的软件和 HTTP 协议的版本。

标签: python http


【解决方案1】:

因为你要求 httplib sn-p:

import httplib

images = ['img1.png', 'img2.png', 'img3.png']

conn = httplib.HTTPConnection('www.example.com')

for image in images:
    conn.request('GET', '/images/%s' % image)
    resp = conn.getresponse()
    data = resp.read()
    with open(image, 'wb') as f:
        f.write(data)

conn.close()

这将对列表中的图像发出多个(顺序)GET 请求,然后关闭连接。

【讨论】:

  • 谢谢,我从没想过要为图片的位置创建一个列表。
  • 试过了。没有足够的声誉这样做。
【解决方案2】:

我找到了urllib3,它声称可以重用现有的 TCP 连接。

正如我在对该问题的评论中已经说过的那样,我不同意这种说法,这不会产生很大的影响:因为 auf TCP Slow Start 算法一开始每个新创建的连接都会很慢。因此,如果数据足够大,重用相同的 TCP 套接字会有所不同。而且我认为对于 100,数据将在 10 到 100 MB 之间。

这是来自http://code.google.com/p/urllib3/source/browse/test/benchmark.py的代码示例

TO_DOWNLOAD = [
'http://code.google.com/apis/apps/',
'http://code.google.com/apis/base/',
'http://code.google.com/apis/blogger/',
'http://code.google.com/apis/calendar/',
'http://code.google.com/apis/codesearch/',
'http://code.google.com/apis/contact/',
'http://code.google.com/apis/books/',
'http://code.google.com/apis/documents/',
'http://code.google.com/apis/finance/',
'http://code.google.com/apis/health/',
'http://code.google.com/apis/notebook/',
'http://code.google.com/apis/picasaweb/',
'http://code.google.com/apis/spreadsheets/',
'http://code.google.com/apis/webmastertools/',
'http://code.google.com/apis/youtube/',
]

from urllib3 import HTTPConnectionPool
import urllib

pool = HTTPConnectionPool.from_url(url_list[0])
for url in url_list:
    r = pool.get_url(url)

【讨论】:

  • 我会研究 urllib3 看看我能做什么。我最近安装了pycurl,使用了一个示例代码,似乎运行多个线程来建立连接,但我看不懂代码,目前只能复制/粘贴。
【解决方案3】:

如果您不打算提出任何复杂的请求,您可以打开socket 并提出自己的请求:

import sockets

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((server_name, server_port))

for url in urls:
    sock.write('get %s\r\nhost: %s\r\n\r\n' % (url, server_name))
    # Parse HTTP header
    # Download picture (Size should be in the HTTP header)

sock.close()

但我不认为建立 100 个 TCP 会话通常会产生很多开销。

【讨论】:

    猜你喜欢
    • 2011-06-03
    • 2012-07-30
    • 2013-09-23
    • 2022-11-21
    • 2021-09-28
    • 1970-01-01
    相关资源
    最近更新 更多