Microsoft Cognitive Services の Text Translation API を(Node.js で)使ってみる

# はじめに
こんにちは。@albno273 です。
例の社会性フィルター([その1](http://qiita.com/albno273/items/2e17fd2d89ceb58d9578)と[その2](http://qiita.com/albno273/items/bcaf836a213b0f8d3add))をアップデートするにあたり機械学習についていろいろと調べていたのですが、ツイートを英訳して indico([参考記事](http://qiita.com/n0bisuke/items/868b43411078bc2018fb)) に投げるというやり方もアリなのではと思いつきました。
そこでテキスト翻訳 API について調べたところ、[Google の Translate API](http://qiita.com/n0bisuke/items/868b43411078bc2018fb) が100万文字あたり25ドルかかるのに対し、[Microsoft](https://datamarket.azure.com/dataset/1899a118-d202-492c-aa16-ba21c33c06cb) の方は月200万文字まで無料となっており、参考記事も [Microsoft Translator Text APIをNode.jsから使ってみる / Qiita](http://qiita.com/n0bisuke/items/350752978b16f4429b31) という自分にドンピシャなものもあって、とりあえず使ってみるのには良さそうでした。

ところが参考記事で使われている Microsoft DataMarket は

> DataMarket and Data Services are being retired and will stop accepting new orders after 12/31/2016. Existing subscriptions will be retired and cancelled starting 3/31/2017. Please reach out to your service provider for options if you want to continue service.

とあり、API は現在 [Azure Portal](https://azure.microsoft.com/ja-jp/features/azure-portal/) に移行していて、参考記事内のプログラムも今は動きません。なので使ってみたついでに修正版のスクリプトを書いてみることにしました。

# 手順
とはいえだいたい[ここ](https://www.microsoft.com/ja-jp/translator/getstarted.aspx)に書いてあるとおりです。

## 1. Azure に登録
![Microsoft Azure](https://qiita-image-store.s3.amazonaws.com/0/163084/e5cf0902-784e-0ed6-0074-4abb9d7ac6a3.png)
[ここ](https://azure.microsoft.com/ja-jp/)から Azure にサインアップします。
無料枠は1ヶ月間ですが、その後も制限を超えなければずっと無料で使えます。
ちなみに20,500円分のクレジットもついてきます。お得！

## 2. Azure アカウントにサブスクリプションを追加
Azure Portal にログインして、左のタブから「新規」→「Marketplace」→「Congnitive Services APIs」を選択して「作成」。
![Azure Portal](https://qiita-image-store.s3.amazonaws.com/0/163084/99d840c0-d405-b363-bfbb-eefb3e037443.png)

「Account name」を適当に書いて、「サブスクリプション」は ”無料試用版” を、「API Type」は ”Translator Text API” を選択。「価格レベル」は無料枠の ”F0” を選択(画像では既にサブスクリプションを作ってあるので S1 になってます)。「Resource group」は新規作成するか既に作ってあるものを割り当てます。「~ location」はどこでもいいと思いますが一番近いといいかなと思って東日本にしました。
![サブスクリプションの新規作成](https://qiita-image-store.s3.amazonaws.com/0/163084/4ed5ab3b-c5b5-cbc2-7264-fdc402e15344.png)

無事作成が終わったら、タブの「すべてのリソース」から作ったサブスクリプションを選択して「Keys」をクリック。トークン生成のためのキーが2つあるので1つをコピーしておきます。これがバレると悪用されかねないので気をつけましょう。
![API Key](https://qiita-image-store.s3.amazonaws.com/0/163084/fcf20242-b368-9167-c63a-e43664d67a41.png)

## 3. API を叩く
あとは [Authentication Token API for Microsoft Cognitive Services Translator API](http://docs.microsofttranslator.com/oauth-token.html) に API Key を投げてトークンを取得し、そのトークンと翻訳したい文字列を [Text Translation API](http://docs.microsofttranslator.com/text-translate.html) に投げればめでたく翻訳完了です。ちなみに API のリファレンスにて実際に値を打ち込んでテストすることもできます。便利！皆さんも是非 Try it out! (ボタンにそう書いてある)

# やり方はわかったからスクリプトを書いてみる
参考記事にならって Node.js でスクリプトを書いてみました。v7.4.0 での動作を確認しています。
先に ``npm install -g request`` を実行してください。

```js:app.js
const request = require('request');

// アクセストークン取得
function getAccessToken(callback) {
    let headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/jwt',
        'Ocp-Apim-Subscription-Key': 'ここにアプリIDを書く'
    };
    let options = {
        url: 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken',
        method: 'POST',
        headers: headers,
        json: true
    };

    request(options, function (err, res) {
        if (err) {
            console.log(err);
            callback(err, null);
        } else
            callback(null, res.body);
    });
}

// 翻訳 (日本語 -> 英語)
function translate(token, text, callback) {
    let base_url = 'https://api.microsofttranslator.com/v2/http.svc/Translate',
        appid = 'Bearer ' + token,
        from = 'ja',
        to = 'en';

    let url = base_url + '?appid=' + appid + 
                '&text=' + text + '&from=' + from + '&to=' + to;
    let headers = {
        'Accept': 'application/xml'
    };

    let options = {
        url: encodeURI(url),
        method: 'get',
        headers: headers,
        json: true
    };

    request(options, function (err, res) {
        if (err) {
            console.log(err);
            callback(err, null);
        } else
            callback(null, res.body.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, ''));
    });

}

// 実行
getAccessToken(function (err, token) {
    if (!err) {
        // console.log(token);
        translate(token, process.argv[2], (err, translated) => {
            if (!err)
                console.log(process.argv[2], '->', translated);
        });
    }
});
```

## 実行してみる
```bash
$ node app.js マクドナルドのハンバーガーが食べたい 。
マクドナルドのハンバーガーが食べたい。  ->  I want to eat a McDonald's burger.
```

トリプルチーズバーガーを食べるタイミングを逃してしまった悲しみ。

# まとめ
Azure は簡単に使えてめちゃくちゃ便利！