Google Apps Scriptの翻訳機能を試してみる

[自動要約＆ニューラルネット翻訳で海外の記事を読みやすくするSlackBot](http://qiita.com/riverwell/items/7413496b0f5fb0081836)という記事を読み、海外のニュースを（自社で使われている）チャットワークに通知するbotをサクッと作れないか試してみました。

[この間の記事](http://qiita.com/ninomiyt/items/0ba732b91ac08d13f55d)で既にRSSのパースとチャットワークへの通知はできているので、要約・翻訳部分をなんとかすれば大丈夫です。

# 対象サイト

[PropertyPortalWatch](http://www.propertyportalwatch.com/)を対象にします。[About Us](http://www.propertyportalwatch.com/about-us/)にもある通り、世界のポータルサイトの動向のニュース記事が掲載されています。

> Property Portal Watch site provides up-to-the-minute news and views as well as in-depth content including interviews, opinions, overviews and directories. Daily updates include acquisitions, new features, site launches and staff movements for property portals around the world.

# ソースコード

文章要約してGoogle翻訳にかけようと思ったのですが、なんとGoogle Apps Scriptには[LanguageAppという文章翻訳の機能](https://developers.google.com/apps-script/reference/language/language-app#translatetext-sourcelanguage-targetlanguage-advancedargs)があります。

また、ニュースサイトという性質上、ニュースのタイトル直後の一文目が、ほぼ全体の要約になっています。今回は通知を目的にしているので、その概略だけを日本語でパッと通知して、気になる記事は英語で詳しく読もう、という方針で実装しようと思います。

また、[XmlService](https://developers.google.com/apps-script/reference/xml-service/xml-service)はrootのノードから辿っていく必要があるため、RSSのパースは正規表現を使ったほうが個人的には楽でした（ただし、例えば記事の中にRSSで使われているものと同名のタグがある場合、以下のコードのままではバグる可能性があります）。

```js
var ARTICLE_REGEXP_DICT = {
  'title': /<title>([\s\S]*?)<\/title>/,
  'link': /<link>([\s\S]*?)<\/link>/,
  'content': /<content:encoded>([\s\S]*?)<\/content:encoded>/
};

function myFunction() {
  var text = fetchUrl('http://feeds.feedburner.com/PropertyPortalWatch?format=xml');
  var result = parseArticles(text, /<item>([\s\S]*?)<\/item>/g, ARTICLE_REGEXP_DICT);
  Logger.log(result[0]['content'])
  Logger.log(LanguageApp.translate(result[0]['content'], 'en', 'ja'))
}

/**
 * 正規表現で与えたXML要素を取り出す
 */
function parseArticles(rss, parent_regexp, article_regexps) {
  var rows = parseAllTags(rss, parent_regexp);
  return rows.map(function(node) {
    return parseOneArticle(node, article_regexps)
  });
}

/**
 * 一つの記事に対応するノードをハッシュテーブルに変換する
 */
function parseOneArticle(article_node, article_regexps) {
  var result = {};
  for (var key in article_regexps) {
    var regexp = article_regexps[key];
    result[key] = parseToText(parseMatchedElement(article_node, regexp));
  }
  return result
}

/**
 * 正規表現にマッチする要素全てを取得する
 */
function parseAllTags(html, regexp) {
  return html.match(regexp);
}

/**
 * 正規表現にマッチした要素を取得する
 */
function parseMatchedElement(html, regexp) {
  var match = regexp.exec(html);
  if (!match) throw String(regexp) + 'にマッチする要素が見つかりませんでした';
  return match[1].replace(/^\s*(.*?)\s*$/, "$1"); // strip
}

/**
 * htmlタグを取り除き、テキストのみを返す
 */
function parseToText(html) {
  return html.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'')
}

/**
 * URLからデータを取得する
 */
function fetchUrl(url) {
  var response = UrlFetchApp.fetch(url);
  return response.getContentText();
}
```

# 翻訳結果

こちらの記事が翻訳されました。

* [Pellicano Group launches property listing app for its $350m portfolio](http://www.propertyportalwatch.com/pellicano-group-launches-property-listing-app-for-its-350m-portfolio/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+PropertyPortalWatch+%28Property+Portal+Watch%29&utm_content=FeedBurner)

英語の本文はこんな感じです。

> Pellicano's new app lists all of the properties in its portfolio
Diversified property group Pellicano has responded to the rapidly disrupting market by developing its own app to manage its $350 million property portfolio, after recognising the demand for a digital platform amongst its clients.
(以下略)

翻訳はこんな感じ

> ペリカーノの新しいアプリは、そのポートフォリオ内のすべてのプロパティを一覧表示します
多様化プロパティグループペリカーノは、そのクライアントの間でデジタルプラットフォームの需要を認識した後、その$ 350百万財産ポートフォリオを管理するために、独自のアプリを開発することによって急速に破壊し、市場に対応してきました。
(以下略)

あれ？[この間ニューラルネットワークでかなり文章が自然になったGoogle翻訳](http://www.itmedia.co.jp/news/articles/1611/16/news085.html)っぽくない訳ですね？

試しに、ブラウザ画面で同じ文章を翻訳してみましょう。

> Pellicanoの新しいアプリは、ポートフォリオのすべてのプロパティを一覧表示します
多様なプロパティグループPellicanoは、クライアント間のデジタルプラットフォームの需要を認識した後、3億5,000万ドルの不動産ポートフォリオを管理する独自のアプリを開発することで、急速に混乱する市場に対応しました。
(以下略)

これこれ、この「多様なプロパティグループPellicanoは～急速に混乱する市場に対応しました。」というような文章が通知したかったのです。

# 結果と展望

LanguageAppの翻訳は、（2017年3月の現時点では）ブラウザ画面の自然な文章とは異なり、Google Apps Scriptのみでサクッと海外ニュースの通知はできませんでした。

しかし、LanguageAppの使いどころによっては、ほとんどプログラミング不要で楽に実装できそうです。
例えば、よく言われているように日本語・韓国語間みたいな語順の似た言語の間なら、今のままでもそれなりに自然な訳が出ると思います。

また、今後LanguageAppにもブラウザと同様の翻訳結果が反映されるものだと期待しています:smiley: