1. ホーム
  2. python

[解決済み] Python 3 で Web からファイルをダウンロードする

2022-03-23 23:20:43

質問

同じゲーム/アプリケーションの.jadファイルに指定されたURLを読み込んで、Webサーバーから.jar(java)ファイルをダウンロードするプログラムを作成しています。Python 3.2.1を使っています。

JADファイルからJARファイルのURLを抽出することはできましたが(すべてのJADファイルにはJARファイルのURLが含まれています)、ご想像の通り、抽出された値はtype()stringです。

該当の関数はこちらです。

def downloadFile(URL=None):
    import httplib2
    h = httplib2.Http(".cache")
    resp, content = h.request(URL, "GET")
    return content

downloadFile(URL_from_file)

しかし、上記の関数の型は文字列ではなく、バイトでなければならないというエラーが常に発生します。URL.encode('utf-8') や bytes(URL,encoding='utf-8') を使ってみましたが、いつも同じか似たようなエラーになります。

つまり、基本的に私の質問は、URLが文字列型で保存されている場合、サーバーからファイルをダウンロードする方法ですか?

どのように解決するのですか?

ウェブページの内容を変数に取得したい場合は、単に read の応答は urllib.request.urlopen :

import urllib.request
...
url = 'http://example.com/'
response = urllib.request.urlopen(url)
data = response.read()      # a `bytes` object
text = data.decode('utf-8') # a `str`; this step can't be used if data is binary


ファイルをダウンロードし、保存する最も簡単な方法は urllib.request.urlretrieve 関数を使用します。

import urllib.request
...
# Download the file from `url` and save it locally under `file_name`:
urllib.request.urlretrieve(url, file_name)

import urllib.request
...
# Download the file from `url`, save it in a temporary directory and get the
# path to it (e.g. '/tmp/tmpb48zma.txt') in the `file_name` variable:
file_name, headers = urllib.request.urlretrieve(url)

ただし、以下の点に注意してください。 urlretrieve レガシー で、非推奨になる可能性があります(理由は不明ですが)。

そのため、最も 正しい を使用することです。 urllib.request.urlopen 関数を使って、HTTP レスポンスを表すファイルのようなオブジェクトを返し、それを実際のファイルにコピーすることができます。 shutil.copyfileobj .

import urllib.request
import shutil
...
# Download the file from `url` and save it locally under `file_name`:
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

これがあまりに複雑に思えるなら、もっとシンプルに、ダウンロードしたもの全体を bytes オブジェクトを作成し、それをファイルに書き出します。しかし、これは小さなファイルに対してのみうまく機能します。

import urllib.request
...
# Download the file from `url` and save it locally under `file_name`:
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
    data = response.read() # a `bytes` object
    out_file.write(data)


を抽出することが可能です。 .gz (しかし、そのような操作を行うには、おそらくHTTPサーバーがファイルへのランダムアクセスをサポートすることが必要です。

import urllib.request
import gzip
...
# Read the first 64 bytes of the file inside the .gz archive located at `url`
url = 'http://example.com/something.gz'
with urllib.request.urlopen(url) as response:
    with gzip.GzipFile(fileobj=response) as uncompressed:
        file_header = uncompressed.read(64) # a `bytes` object
        # Or do anything shown above using `uncompressed` instead of `response`.