証券会社ページで頻出する文字化け
かねてより気になっていたことだが、証券会社やネットバンクのウェブサイトでときおり「ツ�(半角のツ+置換文字)」という謎の文字化けが見られるようになった。今のところこの現象は、「住信SBIネット銀行」と「SBI証券」、「岡三オンライン」で確認している。以下がその実際の様子である(なお今回の記事は全て「岡三オンライン」を例に取り上げる)。

各ページ全体がこんなふうになっており、その挿入箇所から推測するに、「何らかのスペース文字」が文字化けしていると思われる。他の日本語などはちゃんと表示されているので、やや可読性が落ちるくらいでサイト機能に大きな影響はないのだが、まぁ目障りであることには変わりない。できれば解決したいところだ。
しかしいくつかの方法で調べてみても、これと同じ現象についての情報は全く見つけられなかった。みんな正常な表示で何事もなくサイトを利用しているのか、はたまた「そんな小っちゃいことは気にしないぜ! ワカチコワカチコ~♪」な精神の持ち主なのか……。もし後者なら、ぜひとも見習いたいものである……。
原因は文字コードの不一致?
岡三オンラインのトップページにて、開発者ツール[F12]を使ってみたところ、サイトのHTML内ではメタタグで「shift_jis」という文字コードを指定していて、サーバーがウェブブラウザに対し送信する「レスポンスヘッダー(Response Header)」では、「windows-31j」という文字コードを指定していることが分かった。



「Shift_JIS(シフトジス)」は1980年代初期に、「Microsoft Windows」や「MS-DOS」で日本語を使用するために開発された文字コード(エンコーディング)であり、1バイト文字で英数字記号(ASCII文字)や半角カタカナを、2バイト文字で日本語のひらがな、カタカナ、漢字を表現することができる。
コード範囲としてはASCII文字が(0x00~0x7F)で、半角カタカナが(0xA1~0xDF)、マルチバイト文字マルチバイト文字の第1バイトが(0x81~0x9F)(0xE0~0xFC)、第2バイトが(0x40~0x7E)(0x80~0xFC)となっている。
対して「Windows-31J」はShift_JISの上位互換として、1980年代から90年代にかけてWindowsの日本語環境で登場した文字コードだ。ほとんどShift_JISと同じだが、Microsoft独自の機種依存文字などをサポートする拡張がなされている。
例えば「①」(丸数字)や「Ⅲ」(ギリシャ数字)、「㍑」(単位記号)、「㈱」(特殊文字)などを有する「NEC特殊文字」(0x8740~0x879C)や、「髙」や「﨑」、「靑」、「黑」のような異体字を含む「NEC選定IBM拡張文字」(0xED40~0xEEFC)などが追加された。
だからもし、Windwos-31Jで追加されたコードポイント(コード番号)をShift_JISで解釈しようとすると、データが割り当てられていないため文字化けすることになるわけだが、先の岡三オンラインの件でも同じことが起こっているかと言われると、少し疑問が残る。なぜならブラウザは、大抵”レスポンスヘッダーの命令を優先する”ので、送られてくる文字データをWindows-31Jとして解釈するはずだからである。そうなった場合、文字化けしている説明はつかないことになる。
やはりUnicodeは最強
ちなみに、世の中の大抵のウェブサイトで文字化けが起こらない理由は、文字コードとして「UTF-8(Unicode Transformation Format – 8 bit)」を指定しているケースが多いからだ。これは「Unicode (ユニコード)」という、世界中の文字を一意のコードポイントで管理する国際的な文字セットを、可変長(1~4バイト)のデータとして保存・送信するためのエンコーディングである。
つまり「UTF-8」はShift_JISやWindows-31Jとは異なり、世界中の言語を1〜4バイトで表現できる文字コードなのだが、こと”日本語”として使用した場合、Shift_JISやWindows-31Jなら全ての文字を2バイトで表現できるのに対し、UTF-8では”一般的な漢字”で3バイト、”異体字”や”拡張漢字”、”絵文字”で4バイト必要になったりするというわけだ。
よって基本的に日本人しか利用しないようなウェブサイトでは、通信速度やクライアントの消費メモリ節約のため、あえてShift_JISやWindows-31Jを利用する場合も多いと考えられる。ただしそれで文字化けしたりもするのだから、難儀なことである。
昨今、グローバル化の流れはネット界でも顕著になっており、何らかのサービスを提供するウェブサイトは軒並みサイト内言語を多様化しているように見受けられるが、証券会社などの”その国限定のサービス”を提供するサイトでは、そういった変化が事実上必要ないのだろう。それこそが、俺がこの文字化け現象を他サイトでは目にしていない理由かもしれない。
Microsoft Edgeにも責任があるかも?
話は少し反れるが、俺は以前、ウェブブラウザとして「Firefox」を好んで使っていた。理由はWindows既存のIE(Internet Explorer)よりもセキュリティに優れていて、なおかつ拡張機能も豊富で、軽量だったからである。それからグーグル関連サービスの重要性が増してきたことで、「Google Chrome」に乗り換えて長らく使っていた。
しかし最近、ひょんなことからWindowsの再インストールを余儀なくされたことで、またChromeやその拡張機能などを入れなおすのも面倒だなと思い、わりかし評判の良かった新既存ブラウザ「Microsoft Edge」を使い始めた。今思えばそのころかもしれない、文字が化け始めたのは……。
Edgeには”IE互換モード”というのがあり、かつてのIEと同じ設定でページを読み込むことができる。「edge://settings/defaultBrowser」にアクセスして、「Internet Explorerモードでの再読み込みを許可」を「許可」に設定し、Edgeを再起動すると、このIEモードが使用できる。そうして同じ岡三オンラインのページを読み込むと、「ツ」と置換文字が消えて空欄(おそらくスペースではない別の文字)になった。
そもそもこれらの文字は何なの?
ここまで登場した文字化け文字を調べてみると、半角カタカナの「ツ」が(U+FF82)、「�」が(U+FFFD)、「」が(U+F8F0)あることが分かった。何が重要かというと、「これら全てはUnicodeには含まれるが、後の二つはShift_JISやWindows-31Jには含まれない」ということである。「�」は不明な文字、認識できない文字を表す”置換文字”であり、「」はUnicodeにも割り当てられていない領域全般を示す”未割当文字”だ。つまりウェブページはUnicodeでエンコードされていたわけだ(文字自体は全てUnicode文字)。
Shift_JISは、1バイト文字(ASCII、半角カナなど)と2バイト文字(漢字など)が混在するエンコーディングであるが、この2バイト文字がUTF-8などに変換される際、誤って1バイト文字2つとして解釈されてしまう可能性があるのだ。例えば「結」という字は、Shift_JISのバイト列では「0x8C 0x8B」となるが、これが1バイトずつ解釈されると、「0x8C → X、0x8B → Y」となる恐れがある(XとYは単なる変数である)。
岡三オンラインのページをよく見ると、文字化けが出現しているのは”何もない場所”か”絵文字の後ろ”であることが分かる。このことから”スペース文字”が文字化けの正体であることは窺えるが、仮にそれが全角スペースであるならば、Shift_JISでは2バイト文字の最初の最初、「0x81 0x40」でコードされいるので、1バイトずつ解釈されるなら「0x81 → Shift_JISで未割当 → UTF-8で�、0x40 → Shift_JISで@ → UTF-8でも@」と変換され、ウェブページ上では「�@」と表示されうるだろう(詳しくはこちらのShift_JISコード表を参照)。
ついに正体が判明!
一日ほど調べた結果(どんだけ小っちゃいことを気にしてんだ)、岡三オンラインのHTML上にも「ツ�」が散見されることに気づいた(以下の画像を参照)。

これを見てピーンっと来た。きっとウェブ上に絵文字などを表示する際、それをフォントに含まれる”文字”としてではなく、岡三オンライン・オリジナルの”画像”として表示するために、予め画像を格納した要素を追加しておいて、必要なときに「空タグ」で呼び出すという運用方法をとっているに違いない。
そのとき空タグが無効にならないために(あるいは単なる余白を演出するために)、何らかの”見えない文字”を挿入することがテクニックとしてあるのだが、そのときよく使われるのが「ノーブレークスペース(英: no-break space, non-breaking space, NBSP)」である。
ノーブレークスペースはスペースの箇所での自動的な改行を防ぐ特殊なスペースであるため、HTMLで余白を調節するのに重宝する。なぜならHTMLは通常のスペースが複数連続した場合、それを一つのスペースにまとめてしまう仕様があるからだ。NBSPならこの制限を突破して好きな幅の余白を作ることができるのだ。
そしてこのNBSP、何とUTF-8では(C2 A0)でコードされていたのである! つまりこれを1バイトずつShift_JIS(またはWindows-31J)で解釈した場合、「0xC2 → Shift_JISで「ツ」 → UTF-8でも「ツ」、0xA0 → Shift_JISで見割当 → UTF-8では「�」」となるのである! そして(C2 A0)を2バイト文字としてではなく1バイト文字二つと誤解してしまう理由は、そもそも(C2 A0)がShift_JISなどでは未割当領域だからである! もうこれだろう! これってことにしよう!w

つまりまとめると?
ウェブページ全体はUTF-8で書かれているのに、HTMLでShift_JIS、またサーバーのレスポンスヘッダーでWindows-31Jとして解釈するよう指定しているため、ブラウザがどちらか(たぶん後者)で解釈しようとした結果、UTF-8のノーブレークスペース(C2 A0)をそれぞれ(C2)=「ツ」、(A0)=「�」に誤変換してしまい、サイト上で「ツ�」が点在する様相を呈してしまう、という次第である。
修正依頼でも出してみようかな
これで事態のあらましは掴めたわけだが、結局のところ原因が相手方のサーバーや、そこ保存されたHTMLファイルにあるなら、クライアント側の設定などでは解決しようがない(FirefoxやChomeとかならブラウザ側でエンコーディングを変えられるようだが……)。大人しく改善されるのを待つほかあるまい。考えられる修正点としては、サーバーのリクエストヘッダーとHTMLの内容をそれぞれ以下のように変更することである。
Content-Type: text/html; charset=UTF-8
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
もっとも、本当にこれで解決するのかは不明である。しかし何らかの手を打たなければ解決しようもないので、とりあえず問い合わせしてみようと思う。以上、小っちゃいことを気にしすぎた「結ぃつぃ」のレポートでした。
03/13追記:いつの間にか直っていた
マイクロソフト・エッジの更新が一回あったのが原因か、いつのまにか岡三オンラインおよびSBIネット銀行、SBI証券での文字化けが解消されていた。現状で改めて確認すると、岡三オンラインのHTML内の該当箇所には、「 」というノーブレーク・スペースを表すエンティティコードで正常に表示されている(正体はあってたね)。詳しい作用機序は不明だが、結局ブラウザ側の問題だった説が濃厚かもしれない。とにかく直ってよかった、めでたしめでたし。
コメント