DTPab

DTPにまつわるあれこれ

もくもく会#9 開催報告

先月22日、DTPerのスクリプトもくもく会#9を開催しました。仕事がべらぼうに忙しく、なかなかブログを更新できずにおりました。というわけで開催報告です。

今回はまたコワーキングスペースによる有料開催ということで、最初から6名と少なめの募集にしました。が、最終的にはおかげさまで7名の方にご参加いただき、盛況のうちに終えることができました。
開催からちょっと時間が空いてしまったこともあり、スクリプトに関する宿題(質問)も特になかったように記憶しているのですが、もし僕が忘れてたら一方ください^^;;

スライド

さて、今回は久しぶりにプロジェクターを使った発表なぞさせてもらいました。Twitterで散々騒いでいた、Yahoo! のルビ振りAPIを利用するスクリプトについてです。
当日のスライドはこちら(SlideShareにうまくアップできなかったのでGoogleドライブです)

docs.google.com

ひとまずはこのスライドの通りです。時間がない中で作ったものなので、出来が雑でわかりにくいと思います…。
以下、順を追って説明をしていきますが

  • Googleアカウントを持っている
  • Yahoo!アカウントを持っている
  • Yahoo! Web APIのClientIDを取得できている
  • curlコマンドを実行し、GASで立てたWebAPIを叩くことに成功した

というひと揃いの状態までできたことを前提として話を進めていきます。
なので、前掲のスライドでは10ページ目から説明をしていきます。

Yahoo! APIにアクセスする

まずは、GoogleAppsScriptでYahoo! APIにアクセスしてみましょう。

function yahooAPITest() {
  var url = "https://jlp.yahooapis.jp/FuriganaService/V1/furigana";
  url += "?appid=XXXXXXX"; //ここにYahoo! APIのClientIDを入力
  url += "&grade=1";
  url += "&sentence=" + encodeURI("寿限無寿限無");
  Logger.log(UrlFetchApp.fetch(url));
}

これがアドレスになるので、調べたい文字列(今回は適当に「寿限無寿限無」としました)をURIエンコードします。結果をログに吐き出すので、GASから実行したらログを覗いてください。XMLとして値が取得できているはずです。 f:id:uske_S:20181006232604p:plain

GASの構築

GASからYahoo! APIにアクセスして値を取得することができました。ここからGASを肉付けしていきます。盛り込みたい要素は以下のとおりです。

  • 取得したXMLをパースし、必要な情報(今回はルビとしてのふりがな)だけ抽出する
  • このGASをWebAPIとして公開し、外部からアクセスできるようにする
  • ルビを取得したい親文字(文字列)を引数として渡せるようにする

という感じですね。最後にはreturnし、実行元へ値を戻してGASはおしまいになります。

XMLをパースする

いろいろ面倒なので、XMLをパースするGASのライブラリをお借りしました。

tadaken3.hatenablog.jp

導入の仕方、メソッドの使い方はサイトを参照してください。
このライブラリを利用すると、「寿限無寿限無」のうち、1つ目の語句としての「寿限無」のふりがなは以下のようなコードで抽出できます。

function test() {
  var url = "https://jlp.yahooapis.jp/FuriganaService/V1/furigana";
  url += "?appid=XXXXXXX"; //ここにYahoo! APIのClientIDを入力
  url += "&grade=1";
  url += "&sentence=" + encodeURI("寿限無寿限無");
  var xml = XmlService.parse(UrlFetchApp.fetch(url)).getRootElement();
  Logger.log(parser.getElementsByTagName(xml, "Furigana")[0].getValue());
}

実行すると… f:id:uske_S:20181006233556p:plain こんな感じになります。

Logger.log(parser.getElementsByTagName(xml, "Furigana")[0].getValue());

この部分、parser.getElementsByTagName(xml, "Furigana")[0].getValue()ですが、[0]としているので、最初の(ゼロベースインデックスなので0番目)単語の"Furigana"タグを抽出しています。語句数が多い場合はこの部分をfor文で回すなどしてもらう必要がありますが、今回は割愛します。

WebAPIとして公開する

前述の通り、スライドにも載せたWebAPIとして公開する手順が書かれたQiitaの記事でWebAPIとしての公開がすでにできている前提で話を進めます。
まだだよ、というひとはこちらからどうぞ。

qiita.com

公開したWebAPIにアクセスする際の注意点はスライドに書いてありますのでご参照ください。

さて、このQiitaの記事では、関数の名前がdoGetになっていますね。これはGASの予約語、もとい予約関数名です。関数名をdoGetとすることで、APIにGETリクエストが送られた際に動作する関数になります。

というわけで、記事を参考にしながら、前記のコードを合体させてみたものが以下のコードです。

function doGet(e) {
  var url = "https://jlp.yahooapis.jp/FuriganaService/V1/furigana";
  url += "?appid=XXXXXXX"; //ここにYahoo! APIのClientIDを入力
  url += "&grade=1";
  url += "&sentence=" + encodeURI("寿限無寿限無");
  var xml = XmlService.parse(UrlFetchApp.fetch(url)).getRootElement();
  var result = createContent(e.parameter.callback, parser.getElementsByTagName(xml, "Furigana")[0].getValue());
  return result;
}

function createContent(callback , returnObject ) { //JSONまたはJSONPの文字列を返します
  if(callback) {
    return ContentService.createTextOutput(callback + '(' + JSON.stringify(returnObject) + ')').setMimeType(ContentService.MimeType.JAVASCRIPT);
  } else {
    return ContentService.createTextOutput(JSON.stringify(returnObject)).setMimeType(ContentService.MimeType.JSON);
  }  
}

さて、GAS側のWebAPIはできました。これをAPIとして公開したら、そのアドレスに(ターミナルからcurlコマンドでもブラウザでもいいので)アクセスしてみてください。"じゅげむ"という結果が取得できれば成功です。 f:id:uske_S:20181007000155p:plain

引数として文字列を渡す

今度は引数に適当な文字列を指定し、そのふりがなを取得してみましょう。ここでやっとExtendScriptの出番ですw
今回はAppleScriptを利用するので、このコードはMac用です。Windowsの場合、curlコマンドがVBSで実行できれば理論上は同じことができるはずです。まずはExtendScriptでこんなコードを用意。

#target "indesign"
var url = "https://script.google.com/macros/s/XXXXXXXX/exec"; //公開したGASのWebAPIアドレス
var tgString = "仮名";
var scpt = [
    'do shell script "curl -L ', //リダイレクトされるため-Lオプションをつける
    url,
    '?tgstring='+encodeURI(tgString), //アクセスするためにURIエンコードをしておく
    '"'
].join("");
app.doScript(scpt, ScriptLanguage.APPLESCRIPT_LANGUAGE);

続いて、GAS側は引数を受け取れるようにコードを修正。

function doGet(e) {
  if(!e.parameter.tgstring) { //tgstringが指定されてない場合
    return createContent(e.parameter.callback , {error :'target string is required'});
  }

  var url = "https://jlp.yahooapis.jp/FuriganaService/V1/furigana";
  url += "?appid=XXXXXXX"; //ここにYahoo! APIのClientIDを入力
  url += "&grade=1";
  url += "&sentence=" + e.parameter.tgstring;
  var xml = XmlService.parse(UrlFetchApp.fetch(url)).getRootElement();
  var result = createContent(e.parameter.callback, parser.getElementsByTagName(xml, "Furigana")[0].getValue());
  return result;
}

GASをWebAPIとして公開する限りは、コードを修正したら必ず改めて公開の手順を踏んでくださいね(スライド参照)。そうしないとコードの内容が更新されません。

さぁ、ここまで来たらもうできたも同然です。InDesignからスクリプトを実行し、「仮名」のふりがなが取得できればOKです。あとは煮るなり焼くなり、好きにしてください!

ちょっと長くなりましたが、以上、InDesignから(Socket通信を利用せず)GoogleAppsScriptを使ってYahoo! WebAPIを叩く方法でした。
いやー、やってみて思ったけど、けっこうまだるっこしいですねwww