LoginSignup
3
4

More than 1 year has passed since last update.

[python3] EUC-JPなのにShift-JISの機種依存文字が入っててUTF-8にできなかったときの対策

Posted at

表題の通りです。
先人が機種依存文字対策に苦心した痕跡がちらりほらり…
※ はしご高とかそういうタイプの機種依存文字はこの記事では扱いません。

環境

Windows 10
Python 3.8.5
スクレイピング:requests

状況(読まなくても良い)

最近 seesaawiki の記事の自サイトへの移植をごそごそとしているのですが。

seesaawikiからスクレイピングでHTMLソースを取得すると、
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
とあって確かに EUC-JP のはずなのに、wikiソース内で「」のような Shift-JIS の機種依存文字が使えるせいでたまにこれが紛れてくるんです。
で普通に

res = requests.get(url)
text = res.html

みたいに結果を取得しようとすると、なにやらREPLACEMENT CHARACTERなる特殊文字に変化している文字がある…
こまった……

という感じのことになってたいへん苦心したので、対策法を一応記事にしておきます。
誰かの役に立ったらうれしい!

対策

文字コードeuc_jis_2004を使ってbytesをデコードする。
他の言語ではそれっぽい用途にEUC-JP-MS eucJP-win CP51932なる文字コードが使えるらしいのですが、pythonだと全部対応してない…。

decode_test.py
def decode_test():
    original_string = '①②③ ⅠⅡⅢ ㍉㎜㊤㍾'  # 適当に機種依存文字
    before_decode = b'\xad\xa1\xad\xa2\xad\xa3 \xad\xb5\xad\xb6\xad\xb7 \xad\xc0\xad\xd0\xad\xe5\xad\xed'

    trying_encoding_list = ["euc_jp", "euc_jis_2004", "euc_jisx0213"]

    for enc in trying_encoding_list:
        try:
            decoded = before_decode.decode(encoding=enc)
            if decoded == original_string:
                print(enc + ": success!!")
        except UnicodeDecodeError as e:
            print(enc + ": decode failed...")
euc_jp: decode failed...
euc_jis_2004: success!!
euc_jisx0213: success!!

euc_jis_2004euc_jisx0213の違いは正直なところ全くわからないのですが、どっちも動くっぽいのでとりあえず2004の方を使いました。

そもそもEUC-JPの範囲外の文字を含んでるなら最初からcharsetに対応する文字コードを書いて欲しい…と思ったけど、一般公開するには一般的なコード名じゃないとダメなんでしょうか。

参考になったサイト

シフトJIS / EUC-JPとUnicodeとの妥当な変換表
(なんかいろいろ大変だったらしい…という勉強になりました)

pythonで丁寧な文字コード変換
(このブログ記事のおかげで解決に至りました。超感謝です)

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4