1. ホーム
  2. python

[解決済み] PythonリクエストモジュールによるPDFファイルのダウンロードと保存

2022-10-28 21:59:36

質問

ウェブサイトから PDF ファイルをダウンロードし、それをディスクに保存しようとしています。私の試みは、エンコード エラーで失敗するか、空白の PDF になってしまいます。

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)
   ...: 

何らかのコーデックの問題だとは思うのですが、どうしてもうまくいきません。

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

この場合 response.content を使うべきです。

with open('/tmp/metadata.pdf', 'wb') as f:
    f.write(response.content)

から ドキュメント :

テキスト以外のリクエストでは、レスポンスボディをバイトでアクセスすることもできます。

>>> r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...

ということは、つまり response.text は出力を文字列オブジェクトとして返します。 テキストファイル . HTMLファイルなど。

そして response.content は出力をbytesオブジェクトとして返します。 バイナリファイル . 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 と設定すると、requests はそのファイルをダウンロードするときに、最初の 2000 バイトをダウンロードし、それをファイルに書き込み、終了しない限り何度も何度もこれを繰り返します。

というわけで、これはRAMを節約することができます。しかし、私はどちらかというと response.content を使う方がいいと思います。ご覧のように response.raw は複雑です。


関係する。