まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2016/06

IBM のコグニティブエンジンである Watson の各種 API を実際に使って動作を確認するためのサービス: Watson API Explorer を紹介します:
https://watson-api-explorer.mybluemix.net/


上記サイトにブラウザでアクセスすると、このような画面になり、IBM Bluemix で提供されている各種 Watson API が一覧で並んでいます。ここから実際に使ってみたい API を選択します:
2016062901


今回は自然言語テキストをカテゴリ分類する NLC(Natural Language Classifier) の API を試してみましょう。というわけで Natural Language Classifier (以下 NLC)を選択します:
2016062902


すると NLC の Open API Document 形式のページが表示されます。ここに NLC で提供されている各種 API の概要と、そのエンドポイント URL、メソッド、などが一覧表示されています:
2016062903


試しに一番上の GET /v1/classfiers をクリックしてみると、この API の詳細情報が展開されます。実行時に必要なクエリーパラメータがある場合はその情報も表示され、実行結果のフォーマットサンプルも表示されています。またこの Watson API Explorer サービスの最大の特徴ですが、 "Try it out!" と書かれたボタンをクリックすると、この API を(ここで指定したパラメータで)実際に実行して、その実行結果を確認することも可能です:
2016062904


ただし、実行にはこのサービスを利用するための認証情報が必要になります。画面右上に username と password を入力するフィールドがあり、ここに Watson API を実行するための正しい認証情報を指定する必要があります:
2016062905


この認証情報は IBM Bluemix で対象サービス(今回の例であれば NLC)を追加すると確認することができます。もしまだ NLC を Bluemix で使っていない場合は追加しましょう。Bluemix のカタログページから Watson カテゴリ内の NLC を選択します:
2016062906


今回はランタイムアプリケーションとのバインドを行わずに実行するので、アプリケーション欄は「アンバインド」を選択します。そしてサービスを作成します:
2016062907


サービスが作成できたら左メニューから「サービス資格情報」を選び、この NLC サービスを利用するための認証情報を確認します。画面右にサービス資格情報の JSON テキストが表示され、その中に username と password が表示されるはずです:
2016062908


この username と password を Watson API Explorer 画面の NLC の username および password として指定します。これで準備は整いました:
2016062901


では改めて GET /v1/classifiers を実行してみましょう。この API は現在作成した(学習させた) classifier の一覧を取得する API です。特にパラメータは必要ないのでそのまま "Try it out!" ボタンをクリックします:
2016062902


すると指定した username と password を使って API が実行されます。まだ特に NLC で学習データを作っていない場合は classifier は1つも存在していないので、Response Body の "classifiers" には空配列([])が指定されているはずです。また画面内にはこの処理を curl コマンドで実行する場合に指定するコマンドや、実際にアクセスする先のエンドポイント URL(のホスト名を含めた全文字列)、HTTP レスポンスのヘッダやステータスコードなどが確認できます:
2016062903


とりあえず今回はここまで。Watson API Explorer を使うには目的の Watson サービスインスタンスを作って接続情報(username と password)を取得し、それらの情報を使って API を実行する、という流れを紹介しました。 別の機会により具体的な Watson API ごとの利用方法を紹介するつもりです。



 

ウェブブラウザである Chrome の機能を拡張する Chrome extension を作ってみます。今回は試しに
 Chrome でアマゾンの商品ページを見ている時に、そのページ内の ASIN コードを取り出して表示する
というシンプルな機能を実装してみます。

この Chrome 拡張機能の開発方法に関してはこちらに公式ドキュメントがあります。が、Chrome 自身のバージョンアップにともなって機能変更が加わり、それが混乱を招いてしまっている側面はあると思っています。今回紹介する内容はとりあえず 2016/Jun/23 時点では動くことを確認していますが、将来的な保証はないことを最初にお断りしておきます。

今回用意するファイルは次の3つです:
ファイル名用途・コメント
jquery-3.0.0.min.jsjQuery ライブラリ。ここから最新版をダウンロードし、manifest.json 内にファイル名を記述する
manifest.json拡張機能の定義ファイル
script.js拡張機能の実装ファイル


まず jQuery の最新版ライブラリを使います。jQuery のダウンロードページから最新バージョン(今回の例では 3.0.0)をダウンロードします。

次に定義ファイルである manifest.json です。Chrome 拡張機能を作る際に必須の JSON ファイルで、Chrome はこのファイルの中に記述されている通りに拡張されます。今回は以下の様な内容にします:
{
  "name": "AmazonASIN",
  "version": "0.0.1",
  "manifest_version": 2,
  "description": "Amazon商品ページからASINコードを取り出す拡張",
  "content_scripts": [
    {
      "matches": ["http://www.amazon.co.jp/*","https://www.amazon.co.jp/*"],
      "js": ["jquery-3.0.0.min.js","script.js"]
    }
  ]
}

この中では以下の様な指定を行っています:
  • 拡張の名前(name)は "AmazonASIN"
  • 拡張のバージョン(versoin)は 0.0.1
  • マニフェストのバージョン(manifest_version)は2(固定)
  • description に拡張の説明を記述
  • content_script 内にスクリプトの条件を指定
  • このスクリプトは http(s)://www.amazon.co.jp/ 内のページを参照している時だけ動く
  • 動くファイルは前述の jquery-3.0.0.min.js と後述の script.js

簡単に言うと、アマゾン(www.amazon.co.jp)のページを参照している時に script.js が動く、という指定をしています(jquery-3.0.0.min.js は script.js 内で利用しているのでここに記述しています)。

そして今回紹介する拡張機能の本体となるのが script.js です。この内容は以下のとおりです:
$(function(){
 $(".col2 .pdTab tr:first").each(function(){
  var tr = $(this);
  var td1 = tr.children('td:first');
  if( td1.html() == "ASIN" ){
    var td2 = tr.children('td:nth-child(2)');
    var asin = td2.html();
    window.prompt( "ASIN", asin );
  }
 });
});

jQuery にある程度詳しい人であれば簡単に理解できそうなほどシンプルな内容ですが、中身を一応紹介します。

まず最初に、自動化したい作業はこんな感じです:
  1. アマゾンの商品ページを開いたら、
  2. 「登録情報」の「ASIN」と書かれた箇所(下図参照)を探して、
  3. その横の ASIN 番号を取り出して表示する

2016062301

↑この機能、アフィリエイターに需要ありますかね・・・


そしてこのアマゾン商品ページの HTML ソースを見ると、『「登録情報」の「ASIN」と書かれた箇所』というのが、『col2 クラスを持った div パート内の、pdTab クラスを持った div 内のテーブルの、最初の tr パート』であることがわかります:

2016062302


この tr の2番目の td に目的の ASIN 番号が書かれているのでこれを取り出すのが目的です。というわけで、上記の script.js 内では以下の様な処理を記述しています:
  • Amazon のページでのみ以下を実行する(manifest.json で指定済み)
  • ページが全て読み込まれた後に以下を実行
  • col2 クラス以下の pdTab クラスの更に下にあるテーブルの最初の1行(最初のtr)を取り出す
  • 取り出した tr 内の1つ目の td を取り出し、その中に "ASIN" と書かれていることを確認する
  • 確認できたら tr の2つ目の td (ここに ASIN 番号がある)を取り出して、その HTML 文字列を取り出す
  • 取り出した ASIN 番号を画面に表示する

これで処理の記述はできたので、上記3つのファイルを全て同じフォルダ(下図では c:\tmp\amazon_extension)内に保存します:
2016062303


作成した Chrome 拡張はデベロッパーモードの Chrome 内に読み込ませて利用することができます。Chrome を起動後、右上のメニューボタンから 「その他のツール」-「拡張機能」 を選択します:
2016062304


Chrome 拡張機能のメニューが表示されたら、右上の「デベロッパーモード」にチェックを入れます。これでデベロッパーモードになったので、更に「パッケージ化されていない拡張機能を読み込む」ボタンをクリックします:
2016062305


先程作成した3つのファイルを格納したフォルダ(上記の例では C:\tmp\amazon_extension\)を指定して拡張機能を読み込みます:
2016062306


拡張機能にエラーがなければ正しく読み込まれ、拡張機能一覧に表示されます。「有効」にチェックが入っていることを確認してください(チェックを外すと、この拡張機能は動きません。またその右のゴミ箱アイコンをクリックすることで拡張機能を Chrome から削除することもできます):
2016062307


では改めてアマゾンの商品ページを見てみましょう。例えばこのページを参照してみると、、
https://www.amazon.co.jp/gp/product/B014CGROJW/


商品ページがロードされた後に以下の様なダイアログが表示され、ASIN コードが取り出されたことが確認できるはずです(必要であれば、ここからコピーできます):
2016062308


Chrome 拡張機能のごくシンプルな例ですが、こんな感じで作れます。実体はクライアントサイドの JavaScript ですが、クロスサイトスクリプティングの制約を受けることなく AJAX が実行できたりするので、この中で外部連携も含めた様々な処理を記述できます。例えばここで紹介されているサンプルでは Chrome 拡張から Watson API を実行していたりします:
女優・ディベロッパー池澤あやかさんが作成したアプリとは? |Bluemix Developers Lounge


Node.js サーバーのリバースプロキシとして、高性能な Nginx を利用する方法を紹介します。以下では CentOS 環境を前提とした方法を紹介します。

まずは Node.js + アプリケーションの環境を構築します。特に今回は Node.js 上で StrongLoop LoopBack アプリケーションを動かすという前提としてます(独自のアプリケーションでも構いません)。この環境を整えるための手順はこちらを参照ください:
CentOS に StrongLoop をインストールする

アプリケーションが準備できたら Node.js を起動しておきます。実際には forever を使って Node.js をデーモン化しておくと便利だと思います。この辺りの手順はこちらを参照ください:
Forever で Node.js をデーモン化する

(↓ 3000 番ポートで Node.js アプリが動いている様子)
2016061601



この環境にリバースプロキシとして利用する Nginx を導入します。Nginx の導入手順はここの内容を参考にしています:
CentOS に Nginx をインストールして PHP を使う
# rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# yum install nginx

Nginx の設定ファイル(/etc/nginx/conf.d/default.conf)を以下のように編集します(青字が追加部分、赤字がコメントです):
# backend_node に LoopBack サーバー(localhost:3000)を追加
upstream backend_node { ip_hash; server 127.0.0.1:3000; } server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/log/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm;

# 存在するファイルパスが指定された場合はそのまま Nginx で処理 if ( -f $request_filename ) { break; }
# 存在しないファイルパスが指定された場合は backend_node で処理 if ( !-f $request_filename ) { proxy_pass http://backend_node; break; } } : :

これで準備完了です。この状態で Nginx を起動します:
# /etc/init.d/nginx start

改めて同サーバーにウェブブラウザでアクセスします。まずドキュメントルートにアクセスすると、これは Nginx が処理できるパスなので、Nginx のウェルカムページが表示されます:
2016061603


次に /explorer というパスを指定してアクセスしてみます。すると、このファイルやディレクトリは存在しないので Nginx は処理せず、backend_node で指定した 3000 番ポートのサーバー(つまり Node.js)に内部転送して、その結果が表示されます:
2016061602


これで 3000 番ポートを指定しなくても(Node.js 上で動いている)LoopBack サーバーにアクセスできるようになっただけでなく、HTML や画像、CSS、JavaScript といった静的ファイルは Node.js ではなく(高速な)Nginx に任せる、ということもできるようになります。


 

以前に CentOS 環境に StrongLoop LoopBack を導入する手順を紹介しました:

上記の手順ではまず Node.js を導入し、その Node.js 上に StrongLoop LoopBack を導入して OpenAPI 環境を構築していました。リンク先でも紹介されているように、この方法では LoopBack(Node.js) の起動をコマンドラインで行う必要がありました。つまりシステムが起動した後に明示的に LoopBack(Node.js) サーバーをアプリケーションとして起動する、という方法でした:
# cd myapp
# node .

今回の目的はこれをデーモン化することです。

LoopBack に限った話ではないのですが、Node.js アプリケーションをデーモン化する場合には forever というツールを使うことが多いです。forever は Node.js スクリプトの死活監視ツールで、 npm を使ってインストールします:
# npm install forever -g

forever で Node.js アプリをデーモン化して起動する場合は、forever コマンドの start オプションとして実行する JavaScript ファイルを指定します。LoopBack の場合はアプリケーションディレクトリ(上記例の場合は myapp)に package.json というファイルがあり、その中に以下のような記述があります:
{
  "name": "myapp",
  "version": "1.0.0",
  "main": "server/server.js",
  "scripts": {
    "start": "node .",
      :
      :

つまり LoopBack の場合は server/server.js が起動時に実行されていることがわかります。したがって forever を使って LoopBack アプリケーションを起動する場合はアプリケーションディレクトリからこのように server/server.js ファイルを指定すればよい、ということになります:
# cd myapp
# forever start server/server.js

これで LoopBack が実行されます。ウェブブラウザで http://(LoopBack アプリサーバー):3000/explorer にアクセスすると、Open API の API Reference にアクセスできることが確認できます:
2016061601


なお forever は start 以外にも以下の様なコマンドが用意されています:
コマンド目的
forever start (Node.js JavaScript ファイル)指定したアプリケーションの起動
forever list実行中のスクリプトの表示
forever stop (Node.js JavaScript ファイル)指定したアプリケーションの停止
forever stopall起動中の全アプリケーションの停止
forever restart (Node.js JavaScript ファイル)指定したアプリケーションの再起動
forever restartall起動中の全アプリケーションの再起動







 

CentOS に nano エディタを導入して使ってみます:
2016061602


nano は GNU プロジェクトの1つとして開発されているスクリーンエディタです。PuTTY や Teraterm、SSH などのコマンドライン環境下でも使うことができます。vi や Emacs と異なり、(Windows のメモ帳に近い)一般的・直感的なキーバインドで利用することができます。またコマンドが画面下部に表示されているため、初心者でも比較的使いやすいテキストエディタです:
2016061601

Linux に対応したテキストエディタは(他にも Eclipse, ATOM, Sublime, Geany など)多くありますが、ターミナル環境下で使えるものは必ずしも多くありません。クラウド環境を初期状態でセットアップする場合では(SSH で利用できる必要がある、など)テキストエディタに制約があります。vi は vi で便利だと思っていますが、慣れない vi を苦労しながら使うよりは nano の方が効率的に作業することができる、という考え方もあると思います。

そんな nano は yum コマンドでインストールできます:
# yum install nano

インストール後にコマンドラインから "nano" と入力すると起動できます。特定のファイルを開く場合はオプションで指定します:
# nano (filename)


 

このページのトップヘ