2015,10,18, Sunday
Google Apps Scriptで日本語の引数を受け取りたい
Yahoo! Pipesのサービスが終了してしまったので、RSSをフィルターするアプリをGoogle Apps Script(GAS)で作っていました。
ほぼほぼできあがったところで欲が出てきてしまい、「引数を日本語対応させたいなぁ」と考えてしまいました。
で、対応させようと思ったら思いのほか面倒だったのでメモを残します。
この先はGASに興味の無い方にはどうでも良い内容だと思う(しかも無駄に長い)ので、続きが気になる方は無駄に長い事を覚悟の上で「続きを読む」からどうぞ。
ほぼほぼできあがったところで欲が出てきてしまい、「引数を日本語対応させたいなぁ」と考えてしまいました。
で、対応させようと思ったら思いのほか面倒だったのでメモを残します。
この先はGASに興味の無い方にはどうでも良い内容だと思う(しかも無駄に長い)ので、続きが気になる方は無駄に長い事を覚悟の上で「続きを読む」からどうぞ。
Webアプリに値を渡す方法は2つあり、「GETリクエストにパラメータをつける方法」と「POSTリクエストにリクエストボディをつける方法」があります。
今回はRSSリーダーでつかうアプリなので、GETリクエストにパラメータをつける方法で実装しました。
GETリクエストのパラメータの受け取りかたについてGoogleさんで調べたところ、こちらのページに解説がありました。
上記のページを参考にして、こんなスクリプトにしてみました。
※伝統的にはdoGetの引数は「e」で受け取りますが、自分がわかりやすくするためにPHP風の「_Get」にアレンジしています。
こんなアプリを作ってWebアプリとして公開した後、ブラウザでアクセスしてみたところ、引数がアルファベットの時は正常にLogにpage名が記録されるんですが、日本語の引数を渡すと文字化けして上手くいかないときがある。
その条件は「UTF-8以外の文字コードで記述された日本語をURLエンコードして引数として渡したとき」
たとえば、「引数」という日本語をUTF-8でURLエンコードすると「%E5%BC%95%E6%95%B0」という文字列になり、GASのparamaterにも「引数」として正しくデコードされる。
しかし、EUC-JPでURLエンコードすると「%B0%FA%BF%F4」という文字列となり、GASのparamaterは文字化けしてしまっている。
どうしたものかなぁ、と悩んで調べたところJavaScriptの世界(?)ではUTF-8が標準で、GASも引数はUTF-8と見なしてデコードしてしまっているらしい。(原典のURLをブックマークし忘れたのでリンクが張れない… )
文字化けしたものに対して文字コード判定を行っても無意味なので、デコードされる前のqueryStringを自前でデコードする事に。
JavaScriptには標準で「decodeURIComponent」という関数があるので、これを使ってデコードを試みるが、UTF-8以外でURLエンコードされた日本語をデコードさせようとするとエラーになってしまう。
困り果てたところで行き着いたのが「Encoding.js」というライブラリの存在。(作者のブログ)
これでバッチリじゃん! と思いきや、サーバーサイドのJavaScriptで動かすにはNode.jsなるものを導入しなくてはならないらしい。
◆ここから先は私が勝手にやったバッドノウハウです。綺麗で正しいやり方をご存じの方はご教示いただけると幸いです◆
んで、ネットの海をさまよって見つけたのが「nougat (ヌガー)」というライブラリの存在。
でも、どうやってEncoding.jsをヌガー化したら良いかわからない…
あれこれいじったらなんか動いてしまったので、自分がやった方法をメモしておきます。
※これははっきり言ってダメなやり方です。もっとスマートなやり方があればご教示ください
・Encoding.jsをダウンロードして保存する
・GASのスクリプトエディタで「ファイル」→「新規作成」→「スクリプトファイル」を選択してEncoding.gsファイルを作成する
・作成したEncoding.gsに保存したEncoding.jsを貼り付ける
・スクリプトエディタで「リソース」→「ライブラリ」を選択してnougatライブラリを追加する
・メインのスクリプト(code.gs)に下記のコードを挿入する
これで、自分のスクリプトでEncoding.***を呼び出す事が可能になりました。
んでもってEncoding.jsを取り込んでUTF-8以外の文字コードも対応させた関数が下記。
※実際はこの関数を呼び出す前にEncoding.jsを有効にするために上のコードが記述されています
これでなんとか日本語の引数が処理できない問題は解決したのですが、もっと綺麗な解決方法を知りたいのでバッドノウハウである事を承知でブログに記事として書いてみました。
どなたか正しいヌガー化の方法を教えてください…
■この記事は役に立ちましたか? この記事の平均評価: (2人)
ツイート
今回はRSSリーダーでつかうアプリなので、GETリクエストにパラメータをつける方法で実装しました。
GETリクエストのパラメータの受け取りかたについてGoogleさんで調べたところ、こちらのページに解説がありました。
上記のページを参考にして、こんなスクリプトにしてみました。
function doGet(_Get) {
// 引数なしの時はエラー
if (_Get.parameter == undefined || _Get.parameter.page == undefined) {
var msg = '引数が正しくありません';
Logger.log(msg);
Logger.log(_Get.parameter.page);
var html = outputLogHtml(); //←エラー用のhtmlを生成している自前の関数
return html;
} else {
Logger.log("[page] %s", _Get.parameter.page);
page = _Get.parameter.page;
}
~以下変数「page」について処理をしている~
※伝統的にはdoGetの引数は「e」で受け取りますが、自分がわかりやすくするためにPHP風の「_Get」にアレンジしています。
こんなアプリを作ってWebアプリとして公開した後、ブラウザでアクセスしてみたところ、引数がアルファベットの時は正常にLogにpage名が記録されるんですが、日本語の引数を渡すと文字化けして上手くいかないときがある。
その条件は「UTF-8以外の文字コードで記述された日本語をURLエンコードして引数として渡したとき」
たとえば、「引数」という日本語をUTF-8でURLエンコードすると「%E5%BC%95%E6%95%B0」という文字列になり、GASのparamaterにも「引数」として正しくデコードされる。
しかし、EUC-JPでURLエンコードすると「%B0%FA%BF%F4」という文字列となり、GASのparamaterは文字化けしてしまっている。
どうしたものかなぁ、と悩んで調べたところJavaScriptの世界(?)ではUTF-8が標準で、GASも引数はUTF-8と見なしてデコードしてしまっているらしい。(原典のURLをブックマークし忘れたのでリンクが張れない… )
文字化けしたものに対して文字コード判定を行っても無意味なので、デコードされる前のqueryStringを自前でデコードする事に。
JavaScriptには標準で「decodeURIComponent」という関数があるので、これを使ってデコードを試みるが、UTF-8以外でURLエンコードされた日本語をデコードさせようとするとエラーになってしまう。
困り果てたところで行き着いたのが「Encoding.js」というライブラリの存在。(作者のブログ)
これでバッチリじゃん! と思いきや、サーバーサイドのJavaScriptで動かすにはNode.jsなるものを導入しなくてはならないらしい。
◆ここから先は私が勝手にやったバッドノウハウです。綺麗で正しいやり方をご存じの方はご教示いただけると幸いです◆
んで、ネットの海をさまよって見つけたのが「nougat (ヌガー)」というライブラリの存在。
でも、どうやってEncoding.jsをヌガー化したら良いかわからない…
あれこれいじったらなんか動いてしまったので、自分がやった方法をメモしておきます。
※これははっきり言ってダメなやり方です。もっとスマートなやり方があればご教示ください
・Encoding.jsをダウンロードして保存する
・GASのスクリプトエディタで「ファイル」→「新規作成」→「スクリプトファイル」を選択してEncoding.gsファイルを作成する
・作成したEncoding.gsに保存したEncoding.jsを貼り付ける
・スクリプトエディタで「リソース」→「ライブラリ」を選択してnougatライブラリを追加する
・メインのスクリプト(code.gs)に下記のコードを挿入する
(this.UiApp ? nougat : require('nougat')).$(
this.UiApp ? {g: this} : {g: global, m: module},
function(glace) {
'use strict';
return { Encoding: glace.require('Encoding') };
});
これで、自分のスクリプトでEncoding.***を呼び出す事が可能になりました。
んでもってEncoding.jsを取り込んでUTF-8以外の文字コードも対応させた関数が下記。
※実際はこの関数を呼び出す前にEncoding.jsを有効にするために上のコードが記述されています
function doGet(_Get) {
// 引数なしの時はエラー
if (_Get.queryString == null) {
var msg = '引数が正しくありません';
Logger.log(msg);
var html = outputLogHtml(msg); //←エラー用のhtmlを生成している自前の関数
return html;
}
// 引数を取得
var qstr = _Get.queryString.split('&');
var params = new Object();
for(var i = 0; i < qstr.length; i++) {
var keySearch = qstr[i].search(/=/);
var key = '';
if(keySearch != -1) key = qstr[i].slice(0, keySearch);
var val = qstr[i].slice(qstr[i].indexOf('=', 0) + 1);
if(key != '') params[key] = Encoding.urlDecode(val);
}
var strarray = params['page'];
var from_encoding = Encoding.detect(strarray);
var utf8array = Encoding.convert(strarray, 'UNICODE', from_encoding);
var page = Encoding.codeToString(utf8array);
Logger.log("[page] %s", page);
~以下変数「page」について処理をしている~
これでなんとか日本語の引数が処理できない問題は解決したのですが、もっと綺麗な解決方法を知りたいのでバッドノウハウである事を承知でブログに記事として書いてみました。
どなたか正しいヌガー化の方法を教えてください…
■この記事は役に立ちましたか? この記事の平均評価: (2人)
| プログラミング::Google Apps Script | 02:26 PM | comments (2) | trackback (0) |
8 years ago on this day
コメント
ここ最近このエントリーにコメントを残そうとしている人がいるみたいなので、試しにコメント受付期間制限を緩和して上手くコメント出来るかテスト。
コメントがスパムコメントばかりだったら元に戻すかも
コメントがスパムコメントばかりだったら元に戻すかも
| ほりさん | EMAIL | URL | 2017/05/08 01:00 AM | D6wpIUtQ |
コメント受付制限解除したけど、スパムコメントばかりがログに残っていてさみしいなぁ…
| ほりさん★ | EMAIL | URL | 2018/06/11 10:31 PM | NYJGIi2g |
コメントする
トラックバックURL
http://horisanu.info/tb.php/315