2011-03-14 5 views
7

urllibを使用してファイルをダウンロードする方法を知っています。しかし、サーバが許せば、同じファイルのいくつかの部分を同時にダウンロードしてからマージする方がはるかに高速です。1つのファイルのいくつかの部分をPythonと同時にダウンロードしますか?

これはPythonでどうやってやっていますか?標準のlibで簡単に行うことができない場合は、あなたがそれを行うことができるlib?

+7

通常、ネットワーク接続のボトルネックに制限されているため、ファイルの複数の部分を並行してダウンロードするのは高速ではありません。サーバが接続ごとに限られた帯域幅*しか許さない場合にのみ、あなたは改善を得るでしょう。 –

+0

これは、あなたが急流でダウンロード速度を達成するという印象の下に何らかの形で起こっている場合、単一のクライアント、単一サーバのケースであなたが役に立たないことを実感することに失望します。あなたが複数のソースからダウンロードしている場合は*高速です*と*それぞれがあなたの合計ダウンロード帯域幅よりも少ないアップロード帯域幅を持っています。ダウンロード帯域幅以上の(利用可能な)アップロード帯域幅を持つ単一のサーバーからの直接ダウンロードより高速なダウンロードはありません。 –

+3

@Sven:それは誤りです。現実の世界では、ほとんどのサーバーとの接続では、複数のストリームをダウンロードする方がはるかに高速です。残念なことですが、原因を突き止めるのは難しいかもしれませんが、そこには多くの人々が対処するしかありません。 –

答えて

6

PycURLでも可能です。 PycURLはlibcurlへのPythonインターフェイスです。 urllib Pythonモジュールと同様に、PythonプログラムからURLで識別されるオブジェクトを取得するために使用できます。 PycURLは成熟した、非常に速く、多くの機能をサポートします。

+0

OKそれは質問に答える?? – pouya

12

私はGregoryが既存のライブラリを使用する提案に同意しますが、Range HTTPヘッダーを使用してこれを行うことができます。サーバーがバイト範囲の要求を受け入れる場合、複数のスレッドを開始して、ファイルの複数の部分を並行してダウンロードすることができます。あなたは、リモートリソースのサイズを決定し、サーバーがサポートするHEADリクエストを送信することにより、要求の範囲であったかどうかを確認することができます

import urllib2 
url = 'http://example.com/test.zip' 
req = urllib2.Request(url, headers={'Range':'bytes=0-65535'}) 
data = urllib2.urlopen(req).read() 

:このスニペットは、例えば、唯一の指定されたファイルのバイト0 65535をダウンロードします

import urllib2 

class HeadRequest(urllib2.Request): 
    def get_method(self): 
     return "HEAD" 

url = 'http://sstatic.net/stackoverflow/img/sprites.png' 
req = HeadRequest(url) 
response = urllib2.urlopen(req) 
response.close() 
print respose.headers 

上記プリント:我々はファイルサイズが16542バイト('Content-Length')で、サーバがバイト範囲をサポートしていることを見ることができるから、

Cache-Control: max-age=604800 
Content-Length: 16542 
Content-Type: image/png 
Last-Modified: Thu, 10 Mar 2011 06:13:43 GMT 
Accept-Ranges: bytes 
ETag: "c434b24eeadecb1:0" 
Date: Mon, 14 Mar 2011 16:08:02 GMT 
Connection: close 

'Accept-Ranges: bytes')。

+1

+1これを手動で行う方法を説明するだけです。 –

+0

ですので、サイズ65535バイトのファイルを5つのバッファに分割することができます。= 13107 これは、各バッファの範囲が になることを意味しますか?req = urllib2.Request(url、headers = {'Range': 'bytes = 0-13107 '}) ' ' req2 = urllib2。' ' req3 = urllib2.Request(url、headers = {'範囲': 'バイト= 26215-39321'}) ' ' req5 = urllib2.Request(url、headers = {'Range': 'bytes = 52430-65535'} req4 = urllib2.Request(url、headers = {'Range': 'bytes = 39322-52429'}) ) ' もしそうなら' data = urllib2.urlopen(req).read() 'を使ってどうすればいいですか? –

+0

@sanという簡単な方法では、スレッドごとにurlopen()。read()を呼び出し、結果をスレッドセーフなコンテナに格納することができます(この場合、リストまたはdictが行います)。その後、メインスレッドでこれらのスレッドが終了するまで待って(join())、パートを結合します。 – efotinis

関連する問題