DTPab

DTPにまつわるあれこれ

更新されたYahoo!のテキスト解析APIにExtendScriptからPOSTリクエストする

前置き

Yahoo! デベロッパーネットワークのテキスト解析APIがV2になったという話題が前回のもくもく会で出ました。

uske-s.hatenablog.com

これに伴いリクエストとレスポンスの内容が変わるため、このAPIを利用していたスクリプト等は改修を余儀なくされることになります。
今回はこのバージョンアップしたAPIをExtendScriptから利用する方法を紹介します。

ちなみにこの記事で紹介するものは基本Macでしか動きませんので予めご了承ください。

事前に必要なもの

Yahoo! APIのClient IDを取得しておいてください。本記事はClient IDを既に取得してある前提です*1

APIにPOSTリクエストする

前掲のもくもく会開催報告記事にも書いたように、パラメーターを&で区切ってURLに記述するだけのGETリクエストが使えなくなりました。適宜パラメーターを設定したPOSTリクエストを送る必要があります。
ExtendScriptからAPIにリクエストを送る方法として、今回はシェルのcurlコマンドを叩く方法を採用しました。
ExtendScriptからは直接curlコマンドは実行できないので、ExtendScript → doScriptでAppleScriptを実行 → do shell scriptcurlコマンドを実行、という流れになります。

GETではなくPOSTでリクエストする

何もオプションを付けずにリクエストするとGETリクエストになりますが、明示的にリクエストメソッドを変更する場合は-Xオプションをつけます*2
リクエストするURLは末尾に記します。

curlコマンドにリクエストヘッダを指定する

POSTリクエストは-Hコマンドでリクエストヘッダを指定できます。今回のリクエストにはレスポンスの形式を指定するContent-Typeのみを指定します。
ほかにUser-Agentの指定も必要ですが、こちらは-Aオプションで指定します*3

Content-Typeにはapplication/jsonを指定します。
また、User-Agentには既に取得したClient IDを指定しますが、Yahoo AppID: <アプリケーションID>という形で指定する必要があります*4

リクエストボディ

肝心のボディのパラメータは公式を参考にしてください。

developer.yahoo.co.jp

上記にありますがこっちにも載せておきます。

パラメータ 説明
id string, integer 値は任意で、指定した値がレスポンスのidにも返ります。今回は適当にしました
jsonrpc string 2.0(固定)
method string jlp.furiganaservice.furigana(固定)
params object 下記2つのパラメータをもたせたオブジェクトです
q string ふりがなを付ける対象のテキストです
grade integer 1〜8の整数で指定します(詳細は公式ヘルプ参照)

これらをJSONの形(key: value)で-dオプションをつけて指定します。paramsは値がオブジェクトになるのでparams: { q: hoge, grade: 1}みたいになります。

curlコマンドで送る内容の整理

ここまでを整理すると、このようになります。

curl -H 'content-type: application/json' -A 'Yahoo AppID: <アプリケーションID>' -X POST -d '{"id": "1234", "jsonrpc": "2.0", "method": "jlp.furiganaservice.furigana", "params": {"q": "彗星が僕の頭上を翔んだ", "grade": "1"}}' https://jlp.yahooapis.jp/FuriganaService/V2/furigana

ご自分のClient IDを入れてターミナルを叩いてみてください。paramsqに指定した文字列のルビ情報などが含まれたJSONが返ってくれば成功です。

AppleScriptからPOSTリクエストする

AppleScriptからシェルスクリプトを叩くにはdo shell scriptを使います。先ほどのスクリプトをdo shell scriptの引数に渡すのですが、文字列として渡すためdo shell script "curl ..."という形になります。これはつまりダブルクオーテーションは全部エスケープする必要があるということです。
ということでスクリプトエディタでダブルクオーテーションをエスケープして、do shell scriptを使ってみてください。

do shell script "curl -H 'content-type: application/json' -A 'Yahoo AppID: <アプリケーションID>' -X POST -d '{\"id\": \"1234\",\"jsonrpc\": \"2.0\",\"method\": \"jlp.furiganaservice.furigana\",\"params\": {\"q\": \"彗星が僕の頭上を翔んだ\",\"grade\": \"1\"}}' https://jlp.yahooapis.jp/FuriganaService/V2/furigana"

ここまでできたらあと一息です。

ExtendScriptからPOSTリクエストする

InDesignのApplication.doScript()メソッドはAppleScriptを実行できる*5のでそれを利用します。ちょっとだけ使いやすく加工したのが以下のスクリプトです。

解説

テキストを囲むメソッドを自前で用意

テキストを引用符で囲むのが面倒臭すぎたのでプロトタイプ拡張しました(String.surroundQuotes()メソッド)。引数に渡した文字列で元のテキストを囲むだけのものです。

"hoge".surroundQuotes("X"); //結果は XhogeX

みたいに使います。

リクエストパラメータを記述するオブジェクト

サンプルコードではpオブジェクトとしてそこにリクエストしたいパラメータをまとめてJSONで記述しています。特にp.bodyプロパティは、リクエストパラメータ: 値という形式で記述します。後でそのままリクエストボディとしてテキスト化するのを楽にするためです。

AppleScriptを文字列として用意する

scpt変数に"do shell script "と記述し、続けてシェルスクリプトを記述しています。
コマンドやオプションを細かくスペースで区切るのが手間なので、一旦配列で必要な文字列だけ準備して、最後にArray.join(" ")としてすべてスペースでつないで1行にします。

リクエストボディに記述するJSONのテキストを用意する関数

getParamString()メソッドは、渡したオブジェクトのキーと値を\"key\": \"value\"の形にするためのものです。それぞれを\"で挟む処理が面倒くさすぎたため、冒頭のプロトタイプ拡張と合わせて導入しました。入れ子のオブジェクトは再帰的に処理するようにしています。

レスポンスを加工する

レスポンスはJSONなので、eval("(" + result + ")")で無理やりパースします。公式のレスポンスフィールドの項の通り、JSON.result.wordプロパティにふりがなを含んだ単語の配列が得られます。

ちなみに、「彗星が僕の頭上を翔んだ」という文字列のレスポンスは以下のようになります。

{
    "id": "1234",
    "jsonrpc": "2.0",
    "result": {
        "word": [{
                "furigana": "すいせい",
                "roman": "suisei",
                "surface": "彗星"
            },
            {
                "furigana": "",
                "roman": "ga",
                "surface": ""
            },
            {
                "furigana": "ぼく",
                "roman": "boku",
                "surface": ""
            },
            {
                "furigana": "",
                "roman": "no",
                "surface": ""
            },
            {
                "furigana": "ずじょう",
                "roman": "zuzyou",
                "surface": "頭上"
            },
            {
                "furigana": "",
                "roman": "wo",
                "surface": ""
            },
            {
                "furigana": "かけん",
                "roman": "kaken",
                "subword": [{
                        "furigana": "かけ",
                        "roman": "kake",
                        "surface": ""
                    },
                    {
                        "furigana": "",
                        "roman": "n",
                        "surface": ""
                    }
                ],
                "surface": "翔ん"
            },
            {
                "furigana": "",
                "roman": "da",
                "surface": ""
            }
        ]
    }
}

ご覧の通り「翔(と)んだ」みたいな変わった読み方には対応できませんが、結果がしっかりJSONで得られています。

これを利用してInDesignのルビを設定していくわけですね。記事が長くなったので、得られたJSONを基にしてルビをつける部分の解説は割愛しますが、InDesignでのルビの処理に必要なプロパティなどは過去に解説した記事があるのでそちらも参照ください。

uske-s.hatenablog.com

以上、Yahoo! のテキスト解析APIにInDesignのExtendScriptからPOSTリクエストする方法でした。

*1:ご利用ガイドを参照

*2:リクエストメソッドの変更にはこちらを参考にしました
curlコマンドでちょこっとHTTPリクエストを試すだけの記事 - Qiita

*3:curlコマンドのリクエストヘッダについてはこちらを参考にしました
curlコマンドでHTTPヘッダを扱うレシピ - Qiita

*4:下記URLの「アプリケーションIDについて」を参照
WebAPIの使い方(POSTリクエスト) - Yahoo!デベロッパーネットワーク
本記事はUser-Agent方式にしました

*5:Macの場合。Winの場合はVBSが実行できる代わりにAppleScriptは使えません