I am trying to download a PDF file from a website and save it to disk. My attempts either fail with encoding errors or result in blank PDFs.
In [1]: import requests
In [2]: url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
In [3]: response = requests.get(url)
In [4]: with open('/tmp/metadata.pdf', 'wb') as f:
...: f.write(response.text)
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-4-4be915a4f032> in <module>()
1 with open('/tmp/metadata.pdf', 'wb') as f:
----> 2 f.write(response.text)
3
UnicodeEncodeError: 'ascii' codec can't encode characters in position 11-14: ordinal not in range(128)
In [5]: import codecs
In [6]: with codecs.open('/tmp/metadata.pdf', 'wb', encoding='utf8') as f:
...: f.write(response.text)
...:
I know it is a codec problem of some kind but I can't seem to get it to work.
ベストアンサー1
You should use response.content
in this case:
with open('/tmp/metadata.pdf', 'wb') as f:
f.write(response.content)
From the document:
You can also access the response body as bytes, for non-text requests:
>>> r.content b'[{"repository":{"open_issues":0,"url":"https://github.com/...
So that means: response.text
return the output as a string object, use it when you're downloading a text file. Such as HTML file, etc.
response.content
出力をバイトオブジェクトとして返します。ダウンロードするときに使用します。バイナリーファイルPDFファイル、音声ファイル、画像など。
response.raw
代わりに以下を使用することもできますただし、ダウンロードしようとしているファイルが大きい場合に使用します。以下は、ドキュメントにも記載されている基本的な例です。
import requests
url = 'http://www.hrecos.org//images/Data/forweb/HRTVBSH.Metadata.pdf'
r = requests.get(url, stream=True)
with open('/tmp/metadata.pdf', 'wb') as fd:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
chunk_size
は、使用するチャンク サイズです。 に設定すると2000
、リクエストはファイルの最初のバイトをダウンロードし2000
、それをファイルに書き込み、終了するまでこれを何度も繰り返します。
これにより、RAM を節約できます。ただし、response.content
この場合はファイルが小さいため、代わりに を使用することをお勧めします。ご覧のとおり、使用はresponse.raw
複雑です。
関連: