表題の通りです。
先人が機種依存文字対策に苦心した痕跡がちらりほらり…
※ はしご高とかそういうタイプの機種依存文字はこの記事では扱いません。
環境
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だと全部対応してない…。
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_2004
とeuc_jisx0213
の違いは正直なところ全くわからないのですが、どっちも動くっぽいのでとりあえず2004の方を使いました。
そもそもEUC-JP
の範囲外の文字を含んでるなら最初からcharset
に対応する文字コードを書いて欲しい…と思ったけど、一般公開するには一般的なコード名じゃないとダメなんでしょうか。
参考になったサイト
シフトJIS / EUC-JPとUnicodeとの妥当な変換表
(なんかいろいろ大変だったらしい…という勉強になりました)
pythonで丁寧な文字コード変換
(このブログ記事のおかげで解決に至りました。超感謝です)