🔤

日本語のWebページをスクレイプする際に文字コードで嵌まる

2022/02/21に公開

1. きっかけ

複数年にわたる記事が蓄積されたWebをrequest使ってスクレイピングしているときに、ページのエンコーディングが記事年代によって異なっていた。しかも、おそらくは文字コード指定の方法も年代によって異なる可能性の高い事例が発生した。

下記のような処理を複数年代のurlリストからforループ回して取ってくる際に、reでサーチしての処理で、あるはずの文字がないと怒られて、なんでだろう? っていなってた。

url = 'https://hogehoge.com'
session = requests.Session()
response = session.get(url)
text = response.text
## ここからテキストに対して何かの処理みたいな ##

2. 解決方法

年代別にエンコード指定する条件分岐は実装か…面倒だな。いや、ほぼ不可能かも…と途方に暮れていたところ、response.encoding = response.apparent_encoding で解決することが判明。

requestsモジュールのソースコードを見てみると、apparent_encodingはプロパティとなっており、呼び出す度に文字コード推定モジュールchardetを用いて、HTMLのバイト列から文字コードを推定しています。
cite from Pythonのrequestsモジュールでの文字コード対策

結論としては、人間が設定しないといけないレスポンスヘッダやHTML内のメタタグは最初から信用せず、バイト列を元に推定すると良いというお話でした。
cite from Pythonのrequestsモジュールでの文字コード対策

具体的には下記のように request.Response オブジェクトのオブジェクトの処理前に response.encoding = response.apparent_encoding を挟み込む。

url = 'https://hogehoge.com'
session = requests.Session()
response = session.get(url)
+ response.encoding = response.apparent_encoding
text = response.text
## ここからテキストに対して何かの処理みたいな ##

2.1. 参考にしたサイトリンク

Pythonのrequestsモジュールでの文字コード対策

Discussion