Operation KiWi

一生使える言語はPythonだと信じてる

Pythonでスクレイピング中、文字コードで詰まった時の対処法

経験則ですが、スクレイピング中なんかおかしいなぁって思ったときは、恐らくあなたではなくwebサイト側に問題があります。文字コードがきちんと設定されてない、もしくは設定されているけど間違っているのです。

鉄則

head内のcharsetは見ないこと

これ。言い方は悪いですが、絶対に信用してはいけません…。必ず痛い目を見ますよw

chardetは使わないこと

糞重いし、必ずしも正確ではないというのが理由です。これは最終手段としてとっておきましょう。

必ずheadersのcontent-type内を参照すること

正解。面倒ですが必ずここを確認しましょう。以下に手順を記述します…

事前準備

pip install requests

やってみよ~

requestsを使って中身を覗くと、こんな感じになっています。

import requests


r = requests.get('http://hayabusa.open2ch.net/news4vip/subback.html')
r.headers
結果
{'Date': 'Wed, 21 Jun 2017 09:12:51 GMT', 'Content-Type': 'text/html;charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Set-Cookie': '__cfduid=db0430cc2ec9e1a0e0444fee5710732791498036371; expires=Thu, 21-Jun-18 09:12:51 GMT; path=/; domain=.open2ch.net; HttpOnly, a=16e51a6bb0eafd2a73f4c04f7ef84937; domain=.open2ch.net; path=/; expires=Thu, 21-Jun-2018 09:12:51 GMT', 'Vary': 'Accept-Encoding', 'Server': 'cloudflare-nginx', 'CF-RAY': '3725d93b719b2e21-NRT', 'Content-Encoding': 'gzip'}

ここから、文字コードが格納されている、content-typeを抜き出して見ます。

 r.headers['content-type']
結果
'text/html;charset=utf-8'

このページのエンコードはutf-8で行われているようですね。"=“以前の文字は必要ないので、文字コードだけを取り出してセットする関数を書いてみました。*1

import requests


def set_encoding(r):
    """headersから文字コードを抽出して改めてセットする。"""
    if "content-type" in r.headers:
        try:
            charset = r.headers['content-type'].index('=') + 1
        except ValueError:
            r.encoding = "Shift_JIS"
        else:
            r.encoding = r.headers['content-type'][charset:]
    else:
        r.encoding = 'Shift_JIS'

r = requests.get('http://hayabusa.open2ch.net/news4vip/subback.html')
set_encoding(r)

r.encoding
結果
'utf-8'

 終わり

以上です。正直めっちゃハマったので…文字コードは厄介ですね~。

Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-

Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-

*1:ごめんなさい。最初forループとか使ってグルグル回しながら文字の位置探してましたが、index()使えば一発でしたね…お恥ずかしいw