まずrequests.Response
のドキュメントにあたりますよね。
https://requests.readthedocs.io/en/latest/api/#requests.Response.raw
File-like object representation of response (for advanced usage). Use of raw requires that stream=True be set on the request. This requirement does not apply for use internally to Requests.
と出てくるのでstream=True
の時にセットされるファイルライクのオブジェクトだと分かりますね。
stream=True
をセットして型を見ますね。
python
1>>> import requests
2>>> req = requests.get('https://teratail.com/', stream=True)
3>>> print(type(res.raw))
4<class 'urllib3.response.HTTPResponse'>
urllib3のドキュメントにあたる必要があるとわかるわけです。PyPIからドキュメントに行って"decode_content"で検索しますよね。
https://urllib3.readthedocs.io/en/stable/reference/urllib3.response.html?highlight=decode_content
decode_content – If True, will attempt to decode the body based on the ‘content-encoding’ header.
っ書いてあるんで ‘content-encoding’ ヘッダが関係することが分かりますね。decode_contentがTrueだと、content-encoding ヘッダに従って本体ほデコードしようと試みるよ、と。
content-encoding ヘッダの振る舞いが分かっていればここで理解できて調査終了ですね。
そうでないならMDNとかを読みにいきますね。
この時点で私は挙動が推測できています。
content-encoding ヘッダが例えばgzipに設定されているレスポンスをこの処理で取得する時、decode_content=Trueを指定しないとネットワークを流れてきたgzip圧縮されたデータが取得できて、decode_content=Trueを指定するとヘッダを見てくれて自動でgzipでデコードしてくれたデータが取得されるんだろうな、と思っています。
そこで確認するコードを書きます。
python
1import shutil
2
3req = requests.get('https://teratail.com/', stream=True)
4if req.status_code == 200:
5 req.raw.decode_content = True
6 with open('decode_content_true_test', 'wb') as f:
7 shutil.copyfileobj(req.raw, f)
8
9req = requests.get('https://teratail.com/', stream=True)
10if req.status_code == 200:
11 with open('decode_content_false_test', 'wb') as f:
12 shutil.copyfileobj(req.raw, f)
として、macOSなのでターミナルに戻って
shell
1% file decode_content_false_test
2decode_content_false_test: gzip compressed data, from Unix, original size modulo 2^32 220957
3% file decode_content_true_test
4decode_content_true_test: HTML document text, Unicode text, UTF-8 text, with very long lines (20700), with CRLF line terminators
としてやると、decode_content=Trueがないとgzip形式、decode_content=Trueがあるとテキストファイル形式で取得できることが確認できました。