[Nodejs] spookyjsを使って「¥」(半角)マークを置換したい時

2017年5月15日

Nodejs テクノロジー プログラミング

¥マークの扱いは、色々なシステムでトラブルになりがちです。 この問題は、システムのコーディングをする人であれば、1度くらいは経験した事があるのではないでしょうか?

¥マーク問題

¥マークは、共通仕様ではなく、OSによって文字コードが違うという事実を知っていないエンジニアはWEB開発を続けていると痛い目にあってしまいます。 ちなみに、文字コードは以下のようになっているようです。
windows : (0x5C) mac : (0xA5)
僕もこの情報は知らなかったので、↓こちらのサイトで確認しました。 円マークについて | Fusic Developers Weblog そして、大手サイトなどでは、0x5Cで統一するのが一般的な対応のようです。

spookiejsでWEBサイトスクレイピングをする時の事象

Spookiejs内のcasperjsでWEBサイト内の文字列を取得して、それをDBに格納する処理を作ろうとした時に、 ECサイトだったため、料金表示が「¥ 1,000」のようになっていりるケースは多いと思います。

¥マークを使うとspookiejsが落ちる問題

この際に、「,(カンマ)」「半角スペース」「¥(円マーク)」は、不要文字として除外して数値だけにしたいのですが、 spookiejs内のスクレイピング中に、javascript内に「¥」マークが存在すると、システムが途中停止(ハングアップ)してしまうようです。 ただし、これは、以下の条件で発生しており、他の環境では再現しないという事も分かっています。
OS : MaxOSX : 10.12.4 Nodejs : v7.10.0 Phantomjs : 2.1.1 Casperjs : 1.1.4 Spookiejs : 0.2.5

解決

ダメだったパターン

var txt = "¥ 1,000"; txt = txt.replace(/¥/g,""); txt = txt.replace(/\¥/g,""); txt = txt.replace(/\\/g,""); txt = txt.replace(/(U+00A5)/,""); txt = txt.replace(/(U+FFE5)/,""); txt = txt.replace(/(0x5C)/g,""); txt = txt.replace(/(0xA5)/g,"");

成功パターン

var txt = "¥ 1,000"; txt = txt.replace(/(\u005C)/g,""); txt = txt.replace(/(\u00A5)/g,""); または txt = txt.replace(/(\u005C)|(\u00A5)/g,"");

注意点

・replaceはgオプションで文字列内全てのマッチに対応する ・¥マークは文字の存在したいが、システムに影響をきたすので、文字コードで対応(この時に文字コードの文字の最初をエスケープしないといけないらしい) ・文字コードを正規表現で使うには()括弧で囲む必要があるようだ。

考えたいこと

システム構築で重要なのは、出来る限りシンプルで且つ、汎用性を持っていなければいけません。 データベースに格納する文字列も、今回のように出来る限りシンプルにする事で、それを利用する別担当者が、困らないように(いらん時間を取られないように)する必要があるという事ですね。 さらに、元々のWEBページでも、¥マークを表示するのではなく、「¥」という特殊文字をHTMLに記述することで、裏のシステムではこうしたエンコード問題が発生しないような仕組みにする事も重要でしょう。 こういうのは経験しないと中々頭が理解するのは難しいので、ある意味この事象に出会ったことに感謝する事にしましょう。
  • ユゲタ
    2017/05/15 at 09:34
    ¥マークだけでなく、Phantomjsはコメントやら文字列に2バイト文字をコーディングに組み込むと、実行時にハングアップするようです。 ただし、サイトから取得した2バイト文字を変数に格納した場合は、ハングアップしませんでした。 恐らくインタプリタ実行時のコードが2バイト対応できていないようですね。 これを機に、コーディングに2バイト使うのやめてもいいかも。 文字列判定など書くのが大変そうだけど、こういうのは慣れ!

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。