Python3 – requestsの文字化け対策

いつものごとくスクレイプの話ですが、requestsを使っていて文字化けに少々ハマりましたので、残しておきます。

結果的にそもそも文字コードの扱いについてちゃんと理解できていなかったことが問題でしたー

 

HTMLのcharset

今回スクレイプしようとしていたWebサイトはmetaタグのcharsetにEUC-JPが設定されていました

requestsさんですが、基本的にはmetaタグではなくHTTPレスポンスヘッダのcontent-typeをみてcharsetを判断しているようです。が、content-typeが対象のWebで設定されておらず読めない場合はデフォルトのISO-8859-1となってしまうようです

result = requests.get('スクレイプするURL')
print(result.encoding)
実行結果
ISO-8859-1

 
ちょっとググったら以下のやり方でうまいことエンコーディングしてくれる、という記事が見つかったりもしたのですが、今回はうまくいきませんでした。

result = requests.get('スクレイプするURL')
result.encoding = result.apparent_encoding
print(result.encoding)
実行結果
Windows-1252

ぬぬぬ・・・試してみたところWindows-1252と判定されてしまいました( ´・ω・`)

reqeustsの中でchardetを使って自動判定しているようなのですが、完璧ではないのだろうと思われます。当然、print(result.text)の結果も文字化けしてしまっています

 
イラっときたので、直接ぶちこみました

result = requests.get('スクレイプするURL')
result.encoding = 'EUC-JP'
print(result.encoding)
実行結果
EUC-JP

文字化けも解消したので万事解決です(*´∀`*)

 

そもそもの理解不足について

上記までの説明でおっけーという方はページを閉じて頂いて構いません!
今回の問題を解決するにあたって少々ハマってしまったのは、文字コードに対する理解が浅かったためです(まだまだ足りてませんが・・)
 

文字化け

python3でstr型はUnicode形式です、また.encode()を使って特定の形式にエンコードしたbytes型に変換することもできます

str = 'あ'
print(str)
# あ

print(type(str))
# class 'str'

print(str.encode('utf-8'))
# b'\xe3\x81\x82'

print(type(str.encode('utf-8')))
# class 'bytes'

 
つまりはstr型とbytes型は特定のエンコーディング形式で互いを行き来するのみになります

ここでなぜか私はresult.textで得られるstr型をutf-8でencodeしようとしてみたり、そっからEUC-JPでdecodeしようとしてみたりとトンチンカンなことをやってしまっていました・・・(utf-8でencodeしたならば、当然utf-8でdecodeしなければなりません)

文字化けしてるEUC-JPをなんとかしてUTF-8に変換したい~みたいな思いがあったような気がしますが、Unicodeのstr型の時点で文字化けしていたので、どうもしようもありませんでした・・・

問題は入り口の時点で正しいエンコーディングで読めていなかったことだったのです(*´・∀・)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です