Download and save PDF file with Python requests module Ask Question

Download and save PDF file with Python requests module Ask Question

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複雑です。


関連:

おすすめ記事