Microsoft Translator APIによる文字列の言語判定(Perl)

以下は、Microsoft Translator APIのdetectメソッドで言語判定するPerlスクリプトを書いたののメモ。「Microsoft Translator API(HTTP版)を使ってみました - kurukuru-papaのブログ」というエントリが大変参考になりました。ありがとうございました。



数十文字以下の文字列の言語を自動判定する方法[*1]を探していて、

あたりが見つかる。

3番目はBing Translatorのバックエンドで使われているアルゴリズムらしい。ふだんはGoogle翻訳しか使ってないのだけど、APIは有料になっちゃったし、Bingのほうも何件かテストしてみたら悪くなかった。ので、試してみることにした。




準備

(1) Microsoftアカウントを作成

GMailのメールアドレスをそのままアカウントに使えた。
http://www.microsoft.com/ja-jp/msaccount/default.aspx


(2) Windows Azure Marketplaceで登録

右上の「2,000,000文字/月(無料)」をクリック。
https://datamarket.azure.com/dataset/1899a118-d202-492c-aa16-ba21c33c06cb


(3) 自作アプリケーションの登録

「クライアントID」は適当に決めていい。「顧客の秘密」という変な名前のAPIキーを取得できる。
https://datamarket.azure.com/developer/applications/




全体の流れ

APIにはAjax、HTTP、SOAPの3種類が用意されてる。ここでは気楽にHTTP。
http://msdn.microsoft.com/en-us/library/ff512423.aspx


(1) Access Tokenの取得

まずはAPIの利用に必要なAccess Token(有効期間は10分間)を取得する。
http://msdn.microsoft.com/en-us/library/hh454950.aspx

そのためにはHTTP POSTで、

https://datamarket.accesscontrol.windows.net/v2/OAuth2-13

に対して以下のデータを送信する(すべて必須項目)。

client_id 申請した「クライアントID」
client_secret 取得した「顧客の秘密」
scope http://api.microsofttranslator.com(固定値)
grant_type client_credentials(固定値)

すると、JSONで以下のデータが返ってくる。

access_token
token_type http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0(固定値)
expires_in
scope http://api.microsofttranslator.com(固定値)

access_token以外は(少なくともこの用途では)使わない。


(2) detectメソッドを叩く

先ほど取得したaccess_tokenを使い、HTTP GETで、

Authorization: Bearer <access_token>

というヘッダを付けて、

http://api.microsofttranslator.com/V2/Http.svc/Detect?appId=&text=<判定したい文字列>

のように送信する。< と > は不要。「Bearer+半角スペース」の部分は固定で、appIdは空でいいようだ(Authorizationヘッダでaccess_tokenを送っているから)。

すると、以下のように言語コードを含めたXMLが返ってくる。

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">fr</string>

コード体系がよく分からなかったので以下のコードでは「\S」で抜いてるけど、あとで探したらちゃんと言語コードの一覧があった。

繰り返し detect する際には、その都度ヘッダ付きでGETする。access_tokenの有効期間が切れたらどうなるかは試してないので分からない(1600件ほど処理したらちょうど9分ちょいで終わった)。



サンプルコード

#!/usr/bin/perl -w

use strict;
use LWP::UserAgent;
use JSON;

my $ua = LWP::UserAgent->new;
my $res;

my $text = 'なにか適当に判定したい文字列を';

# access_token取得
my $authurl = 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13';
my $param = {
	client_id => '設定した「クライアントID」',
	client_secret => '取得した「顧客の秘密」',
	scope => 'http://api.microsofttranslator.com',
	grant_type => 'client_credentials'
};
$res = $ua->post($authurl, $param)->content;
my $access_token = JSON->new->decode($res)->{access_token};

# detect実行
my $detecturl = 'http://api.microsofttranslator.com/V2/Http.svc/Detect?text=';
$res = $ua->get(
	$detecturl . $text, 
	'Authorization' => 'Bearer ' . $access_token
)->content;

# 言語コード抽出
$res =~ />(\S{1,})</;
print $1, "\n";

*1:正確に言うとやりたいのは、書籍のタイトルの言語を判定して、本文の言語として設定するという2段階に無理のあるはなしなんだけど。