リモート(HTTP)ファイルの特定の位置を探して、その部分だけをダウンロードできるようにするにはどうすればよいですか?
リモートファイルのバイトが1234567890だったとしましょう
私は4を探し、そこから3バイトをダウンロードしたいので、次のようになります:456
また、リモートファイルが存在するかどうかを確認するにはどうすればよいですか?os.path.isfile()を試しましたが、リモートファイルのURLを渡すとFalseが返されます。
HTTP経由でリモートファイルをダウンロードする場合は、Range
ヘッダーを設定する必要があります。
この例で、それがどのように行われるかを確認してください。このように見えます:
myUrlclass.addheader("Range","bytes=%s-" % (existSize))
編集:私はちょうどより良い実装を見つけました。このクラスは、docstringに示されているように、非常に簡単に使用できます。
class HTTPRangeHandler(urllib2.BaseHandler):
"""Handler that enables HTTP Range headers.
This was extremely simple. The Range header is a HTTP feature to
begin with so all this class does is tell urllib2 that the
"206 Partial Content" reponse from the HTTP server is what we
expected.
Example:
import urllib2
import byterange
range_handler = range.HTTPRangeHandler()
opener = urllib2.build_opener(range_handler)
# install it
urllib2.install_opener(opener)
# create Request and set Range header
req = urllib2.Request('http://www.python.org/')
req.header['Range'] = 'bytes=30-50'
f = urllib2.urlopen(req)
"""
def http_error_206(self, req, fp, code, msg, hdrs):
# 206 Partial Content Response
r = urllib.addinfourl(fp, hdrs, req.get_full_url())
r.code = code
r.msg = msg
return r
def http_error_416(self, req, fp, code, msg, hdrs):
# HTTP's Range Not Satisfiable error
raise RangeError('Requested Range Not Satisfiable')
更新:「より良い実装」は、byterange.pyファイルのgithub:excid3/urlgrabberに移動しました。
リクエストライブラリを使用することを強くお勧めします。これは、私が今まで使用した中で最も優れたHTTPライブラリです。特に、あなたが説明したことを達成するために、あなたは次のようなことをするでしょう:
import requests
url = "http://www.sffaudio.com/podcasts/ShellGameByPhilipK.Dick.pdf"
# Retrieve bytes between offsets 3 and 5 (inclusive).
r = requests.get(url, headers={"range": "bytes=3-5"})
# If a 4XX client error or a 5XX server error is encountered, we raise it.
r.raise_for_status()
AFAIK、これはfseek()などを使用しては不可能です。これを実現するには、HTTPRangeヘッダーを使用する必要があります。このヘッダーはサーバーでサポートされている場合とされていない場合があるため、マイレージは異なる場合があります。
import urllib2
myHeaders = {'Range':'bytes=0-9'}
req = urllib2.Request('http://www.promotionalpromos.com/mirrors/gnu/gnu/bash/bash-1.14.3-1.14.4.diff.gz',headers=myHeaders)
partialFile = urllib2.urlopen(req)
s2 = (partialFile.read())
編集:これはもちろん、リモートファイルとはHTTPサーバーに保存されているファイルを意味すると仮定しています...
必要なファイルがFTPサーバー上にある場合、FTPは開始オフセットのみを指定でき、範囲は指定できません。これが必要な場合は、次のコードで実行する必要があります(テストされていません!)
import ftplib
fileToRetrieve = 'somefile.zip'
fromByte = 15
ftp = ftplib.FTP('ftp.someplace.net')
outFile = open('partialFile', 'wb')
ftp.retrbinary('RETR '+ fileToRetrieve, outFile.write, rest=str(fromByte))
outFile.close()
httpioを使用して、リモートHTTPファイルにローカルであるかのようにアクセスできます。
pip install httpio
import zipfile
import httpio
url = "http://some/large/file.zip"
with httpio.open(url) as fp:
zf = zipfile.ZipFile(fp)
print(zf.namelist())