[Python] CP932 (Windows-31J) には含まれるが Shift_JIS には含まれない文字の一覧を取得する

## やりたいこと

**CP932 (Windows-31J) には含まれるが Shift_JIS には含まれない文字**があります。例えば「髙」がそうです。他にはどのような文字があるのか一覧がほしいです。

なお、CP932 と Shift_JIS の違いについてはこの記事では説明しません。例えば、以下の記事を参照してください。ややこしいですが、この記事のタイトルの SJIS は CP932 (Windows-31J) を指しています。

https://developers.freee.co.jp/entry/sjis-is-not-an-alias-of-shift-jis

## 方法

```shell-session
$ python --version
Python 3.13.2
```

```py
import sys

# CP932 に含まれる文字を取得する。
cp932_chars = set(chr(i) for i in range(sys.maxunicode) if chr(i).encode('cp932', errors='ignore'))
len(cp932_chars)
# 9408

# Shift_JIS に含まれる文字を取得する。
shift_jis_chars = set(chr(i) for i in range(sys.maxunicode) if chr(i).encode('shift_jis', errors='ignore'))
len(shift_jis_chars)
# 7072

# CP932 にあるが Shift_JIS にはない文字を取得する。
diff_chars = cp932_chars - shift_jis_chars
# {'\ue453', '珵', '朎', ..., '\ue358'}
len(diff_chars)
# 2338

# '\ue453' や '\ue358' などを取り除き、'珵' や '朎' など印字可能な文字のみに絞り込む。
printable_diff_chars = set(char for char in diff_chars if char.isprintable())
printable_diff_chars
# {'珵', '⑪', '朎', '德', '㊧', '⑭', '皂', '赶', '⑩', '晴', '伹', '匤', '⑳', '煆', '佖', '寬', '鄕', '昱', '冝', '魵', '渧', '畯', '竑', '戓', '倢', '摠', '琮', '墲', '撝', '珖', '誧', '鈹', '～', '仡', '晳', '伀', '愷', '鉷', '嶸', '釞', 'Ⅲ', '⑨', '㍑', '皜', '暠', 'ⅵ', '∑', '倞', '館', '犾', 'ⅲ', '鈊', '澵', '鑅', '譿', '鋹', '濵', '侔', '霻', '奓', '絈', '丨', '岺', '僘', '昮', '叝', 'Ⅹ', '﨏', '炫', 'Ⅳ', '鐱', '錂', '荢', '諟', '纊', '珒', '炅', '鮻', '＂', '鍰', '﨤', '鋠', '㈱', '煇', '樰', '⑧', '㏄', '暲', '㌻', '砡', '煜', '厲', '劜', '愰', '⑮', '鈼', '都', '餧', '憘', '鍗', '鮱', '㌧', '愠', '皛', '竫', '鄧', '鏆', '焏', '琇', '昤', '桄', '楨', '精', '偂', '鵫', '靃', '愑', '茁', '㎡', '焄', '㍍', '鋓', '誾', '璉', '暿', '奛', '瀨', '㊦', '㊨', '⑦', '劯', '偀', '鸙', '硺', '靍', '弴', '﨩', '暙', '∥', '⑰', '鉎', '￡', '曻', '⑫', '炻', '涬', '浯', '傔', '閒', '褜', '珣', '櫢', '㌶', '㎎', '橫', '妤', '荿', '綠', '涖', '飼', '擎', '僴', '靕', '絜', '惞', '顗', '遧', '賴', '霳', '獷', '②', '惕', '㌔', '尞', '俍', '﨟', '釥', '杦', '匀', '〝', '勛', '淸', '綷', '鎤', '犱', '橳', '﨔', '嶹', '㎞', '⑥', '祥', '朗', '枻', '渹', '玽', '㍗', '塚', '岦', '甁', '鋕', '﨧', '妺', '馞', '∮', '猪', '惲', '㌢', '菇', '繒', '鉧', '葈', '鍈', '鵰', '鋐', '㊤', '諶', '⑬', '㏍', '澈', '郞', '垬', '蕙', '銈', '裵', '弡', '睆', '㍉', '㎝', '罇', '侚', '￢', '鉑', '竧', '黑', '銧', '皦', '菶', '㌫', '鈆', '偰', '蒴', '橾', '薰', '蘒', '訒', '昕', '㌍', '羽', '㊥', '忞', '栁', '瀇', '鋙', '昞', '釤', '諸', '⑱', '瑢', '偆', '驎', '埇', '㍾', '坙', '㎏', '渼', '鋻', '抦', '淲', 'ⅱ', '釮', '髜', '硎', '㈹', '琩', '悅', '俉', '鏞', '仼', '靏', '棏', '﨡', '侊', '洄', 'ⅹ', 'ⅸ', '㌣', '⑤', '敎', '巐', '沆', '㍊', '鋿', '禔', '凬', '硤', '〟', '皞', '㍼', '蕓', '∟', '禛', '￠', '訷', '軏', '①', '蕫', '伃', 'Ⅷ', '咜', '揵', '﨎', '兊', '燾', '譓', '勀', '卲', '寀', '咊', '曺', '﨨', '奣', '毖', '鮏', '№', '昻', '隯', '珉', 'ⅴ', 'Ⅶ', '璟', '奝', '增', '哿', '猤', 'Ⅸ', '晙', '嵓', '㈲', '汯', '贒', '錝', '鈺', '鋗', '甯', '賰', '㌦', '涇', 'Ⅰ', 'Ⅴ', '櫤', '飯', 'Ⅵ', '礼', '㍻', '詹', '淏', '恝', '棈', '冾', '④', 'ⅶ', '﨣', '益', '俿', 'Ⅱ', '琪', '㎜', '釗', '崧', '汜', '﨓', '￤', '隆', '㌃', '鑈', '悊', '槢', '鈐', '泚', 'ⅷ', '③', '刕', '厓', '晗', '靖', '晥', '桒', '礰', '咩', '鶴', '蓜', '⑯', 'ⅰ', '喆', '琦', '㍽', '鋧', '逸', '鏸', '榘', '凞', '鉸', '﨑', '隝', '釭', '魲', '昉', '㌘', '燁', '埈', '匇', '嵭', '箞', '瀅', '淼', '羡', '℡', '－', '昀', '劦', '柀', '孖', '兤', '顥', '彧', '夋', '嵂', '釚', '蠇', '彅', '鉀', 'ⅳ', '侒', '寘', '⊿', '福', '氿', '緖', '橆', '湜', '神', '錞', '坥', '鉙', '⑲', '峵', '鰀', '＇', '錡', '溿', '髙', '靑', '錥'}
len(printable_diff_chars)
# 453
```

CP932 には含まれるが Shift_JIS には含まれない文字は 2,338 文字あり、そのうち印字可能な文字[^1]は以下の 453 文字であることが分かりました。それらの文字を出力してみます。

```py
# Unicode コードポイントの昇順にソートする。
sorted_printable_diff_chars = sorted(printable_diff_chars, key=lambda char: ord(char))
# 20 文字ずつ出力する。
n = 20
for sub_list in [list(sorted_printable_diff_chars)[i: i+n] for i in range(0, len(sorted_printable_diff_chars), n)]:
    print(', '.join(sub_list))
```

```
№, ℡, Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ, Ⅵ, Ⅶ, Ⅷ, Ⅸ, Ⅹ, ⅰ, ⅱ, ⅲ, ⅳ, ⅴ, ⅵ, ⅶ, ⅷ
ⅸ, ⅹ, ∑, ∟, ∥, ∮, ⊿, ①, ②, ③, ④, ⑤, ⑥, ⑦, ⑧, ⑨, ⑩, ⑪, ⑫, ⑬
⑭, ⑮, ⑯, ⑰, ⑱, ⑲, ⑳, 〝, 〟, ㈱, ㈲, ㈹, ㊤, ㊥, ㊦, ㊧, ㊨, ㌃, ㌍, ㌔
㌘, ㌢, ㌣, ㌦, ㌧, ㌫, ㌶, ㌻, ㍉, ㍊, ㍍, ㍑, ㍗, ㍻, ㍼, ㍽, ㍾, ㎎, ㎏, ㎜
㎝, ㎞, ㎡, ㏄, ㏍, 丨, 仡, 仼, 伀, 伃, 伹, 佖, 侊, 侒, 侔, 侚, 俉, 俍, 俿, 倞
倢, 偀, 偂, 偆, 偰, 傔, 僘, 僴, 兊, 兤, 冝, 冾, 凬, 刕, 劜, 劦, 劯, 勀, 勛, 匀
匇, 匤, 卲, 厓, 厲, 叝, 咊, 咜, 咩, 哿, 喆, 坙, 坥, 垬, 埇, 埈, 增, 墲, 夋, 奓
奛, 奝, 奣, 妤, 妺, 孖, 寀, 寘, 寬, 尞, 岦, 岺, 峵, 崧, 嵂, 嵓, 嵭, 嶸, 嶹, 巐
弡, 弴, 彅, 彧, 德, 忞, 恝, 悅, 悊, 惕, 惞, 惲, 愑, 愠, 愰, 愷, 憘, 戓, 抦, 揵
摠, 撝, 擎, 敎, 昀, 昉, 昕, 昞, 昤, 昮, 昱, 昻, 晗, 晙, 晥, 晳, 暙, 暠, 暲, 暿
曺, 曻, 朎, 杦, 枻, 柀, 栁, 桄, 桒, 棈, 棏, 楨, 榘, 槢, 樰, 橆, 橫, 橳, 橾, 櫢
櫤, 毖, 氿, 汜, 汯, 沆, 泚, 洄, 浯, 涇, 涖, 涬, 淏, 淲, 淸, 淼, 渧, 渹, 渼, 湜
溿, 澈, 澵, 濵, 瀅, 瀇, 瀨, 炅, 炫, 炻, 焄, 焏, 煆, 煇, 煜, 燁, 燾, 犱, 犾, 猤
獷, 玽, 珉, 珒, 珖, 珣, 珵, 琇, 琦, 琩, 琪, 琮, 瑢, 璉, 璟, 甁, 甯, 畯, 皂, 皛
皜, 皞, 皦, 睆, 砡, 硎, 硤, 硺, 礰, 禔, 禛, 竑, 竧, 竫, 箞, 絈, 絜, 綠, 綷, 緖
繒, 纊, 罇, 羡, 茁, 荢, 荿, 菇, 菶, 葈, 蒴, 蓜, 蕓, 蕙, 蕫, 薰, 蠇, 裵, 褜, 訒
訷, 詹, 誧, 誾, 諟, 諶, 譓, 譿, 賰, 賴, 贒, 赶, 軏, 遧, 郞, 鄕, 鄧, 釗, 釚, 釞
釤, 釥, 釭, 釮, 鈆, 鈊, 鈐, 鈹, 鈺, 鈼, 鉀, 鉎, 鉑, 鉙, 鉧, 鉷, 鉸, 銈, 銧, 鋐
鋓, 鋕, 鋗, 鋙, 鋠, 鋧, 鋹, 鋻, 鋿, 錂, 錝, 錞, 錡, 錥, 鍈, 鍗, 鍰, 鎤, 鏆, 鏞
鏸, 鐱, 鑅, 鑈, 閒, 隝, 隯, 霳, 霻, 靃, 靍, 靏, 靑, 靕, 顗, 顥, 餧, 馞, 驎, 髙
髜, 魲, 魵, 鮏, 鮱, 鮻, 鰀, 鵫, 鵰, 鸙, 黑, 朗, 隆, 﨎, 﨏, 塚, 﨑, 晴, 﨓, 﨔
凞, 猪, 益, 礼, 神, 祥, 福, 靖, 精, 羽, 﨟, 蘒, 﨡, 諸, 﨣, 﨤, 逸, 都, 﨧, 﨨
﨩, 飯, 飼, 館, 鶴, ＂, ＇, －, ～, ￠, ￡, ￢, ￤
```

## 参考

### CP932

- [Microsoftコードページ932 - Wikipedia](https://ja.wikipedia.org/wiki/Microsoft%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8932)
- [本当は怖くないCP932 #文字コード - Qiita](https://qiita.com/kasei-san/items/cfb993786153231e5413)

### Python

- [sys.maxunicode](https://docs.python.org/ja/3.13/library/sys.html#sys.maxunicode)
- [str.encode()](https://docs.python.org/ja/3.13/library/stdtypes.html#str.encode)
- [str.isprintable()](https://docs.python.org/ja/3.13/library/stdtypes.html#str.isprintable)
- [sorted()](https://docs.python.org/ja/3.13/library/functions.html#sorted)

[^1]:「印字可能文字」の定義は [str.isprintable()](https://docs.python.org/ja/3.13/library/stdtypes.html#str.isprintable) を参照してください。