Typescriptのススメ、改めAmazon購入履歴取得2016年版

こんにちは。JWord社のS.K.です。普段はJWord プラグインE START デスクトップバーの開発をC++やC#でしています。
そんな私がブラウザ側の開発の勉強にあたってTypescriptをかじったのでブログに投稿します。

Typescriptのススメ

  • なぜTypescript使うのか
    ・静的型付けによる型チェック:コンパイル時にエラーが分かる!
    →Javascriptでブラウザで動作確認だと「実行時」なので書いてからミスに気付くまでの時間が長い
    ・クラスベースオブジェクト指向
    →C++/C#からの学習コストが低い(C#のデザイナーが設計)
    *言語仕様が近い
    ・名前空間があるので規模の大きい開発がしやすい。
    ・Javascriptも併用できる(Ver.1.8以降)
    →Javascriptから移植してメンテナンス性アップ
    ・環境(Javascriptエンジン)依存の吸収
    →従来だとjQueryとかのライブラリで吸収していたものをコンパイラが解決!
    ・慣れたVisualStudioで開発
    →Intellisenseによるコード補完があるので記述が楽!
    →デバッグ操作等UIに慣れている。
    ・ChromeデバッグAPIとの連携。
    →デバッグしやすい?
    Javascriptの勉強に!
  • どこで使われているか(事例)
    ・Angular2:GoogleのMVCフレームワーク
    ・開発に使われているみたいだけど、最終的に表に出てくるのがJavascriptなのでどの程度使われているのか不明。

 

Typescriptで開発サンプル

Amazonの購入履歴を取得するブックマークレットが流行ったことがありましたね。
*ブックマークレット:ブックマークのURL欄にJavascriptを記述し、表示中のサイトに対して実行する機能
ブックマークレットと同様なことは
・Chromeだと:Tampermonkey
・Firefoxなら:Greasemonkey
・IEなら当社のプロダクトJWord プラグインのSitePlusのユーザースクリプト
でできますが、どれも一般の方(非プログラマー)には敷居が高いです。
一般向けならアプリを実行してナビゲーションに従って操作すれば取得できるような仕組みが必要です。
VectorのAmazon注文履歴取得
とかが良い例です。

今回は
Amazonで一年間に使った金額と、注文履歴のTSVを出力するブックマークレット【2015年版】 (GitHub
上記のブックマークレットを(いきなりJavascript修正した方が早いですけど、趣旨に反するので)Typescriptに移植後、修正して2016年版を作ります。

ブックマークレットとして下記を登録します。

javascript:(function(){var a=document.createElement("script");a.src="//<HTTPSで繋げれるホスト>/<jsファイル>";document.body.appendChild(a)}());

注意点としては
・証明書の認証でブラウザのセキュリティで弾かれることがあるので
https://<HTTPSで繋げれるホスト>/<jsファイル> を新タブで開き、コードが読めることを確認しておくこと。
4
・TSVの出力ポップアップウィンドウが表示されない場合はアドレスバー右上の×印をクリックしてポップアップを許可すること。
です。
成果物rawgithub.com経由参照:
javascript:(function(){var a=document.createElement("script");a.src="//rawgithub.com/Libitina/AmazonRecord2016/master/2016/amazon_record.js";document.body.appendChild(a)}());

目的

2015年版では表示される合計金額は正しいのですが、
3
2
・TSV出力(発注日、商品名、著者、商品URL)の著者の欄が正しく取得出来ていない。
・1回に多数品目発注した場合に、省略されたアイテムの情報が取得できない。
・(内部的に)個別の値段に発注の合計金額が入っている。
という問題があります。
今回は正しくTSV出力(発注日、商品名、値段、商品URL)が得られることを目的とします。

JavascriptからTypescriptに変換

1
Visual Studio 2015で新しいプロジェクト(言語はTypescript、TypeScriptを使用したHTMLアプリケーション)を作成します。
5
デフォルトでGMT時間を表示・更新するHTMLアプリケーションのためのコードが記述されています。
6
TypeScriptファイルを追加し、Javascriptファイルの内容をそのままコピーします。
jQueryが無いためや、変数の型の不一致のエラーが表示されます。

jQueryを使えるようにしよう。
7
NuGetパッケージマネージャーから
8
jQuery.TypeScript.DefinitelyTyped
をインストールします。
以上!で移植完了です。
と書きたかったのですが、そこまで甘くはありませんでした。
追加で下記の変更を行いました。
・jQuery.ajaxのSuccess条件の書く位置がjQuery1.5以上のajax()の後ろではなく、1.4以前のajax()内に書く。
・型の記載の追加および関連して関数の引数の変更。
・オブジェクトへのメンバ追加を連想配列に変更。
2015年版オリジナルJavascirptファイル
2015年版移植Typescriptファイル
2015年版移植Javascirptファイル
オリジナルJavascirptファイルと移植Typescriptファイルの比較
オリジナルJavascirptファイルと移植Javascirptファイルの比較
★all指定した時に正しく動作しないバグ有り(84行目でnyearを変更しているのに文字のyearを更新していない)

これでTypescriptらしい記述ではないものの動作はするようになりました。
Javascriptの方が記述で省略できるところが多いものの、Typescriptの方が慣れ親しんだ記載という印象。

修正

・紅茶等の食品や家電にはautherが無いので、autherの代わりに値段を出力させる。
・単純にautherをpriceに変更するとその決済時の金額が入っているので、個別の値段を取得するようにする。。
・商品URLに余計なパラメータが含まれているので削る
・「○個すべての商品を表示」のような一度に多数個発注した場合に個別の内容を取得出来ていないので対応させる。
※配達日が別れた場合や、別注文が1発送にまとめられる場合にも対応を確認しました。
修正後Typescriptファイル
修正後Javascirptファイル
変更後と修正後のTypescriptファイルの比較

感想

結局jQueryの非同期処理が一番の難関でした。
近年のスクリプト言語(Javascript)とC#の機能の取り入れ合いによって言語仕様自体は近いものになっているのが大きいです。
関数の引数違いでのオーバーロードがサポートされていないのが地味にめんどくさかったです。

残件

・Typescript的な書き方に変換する。
function(){}はアロー関数で()⇒{}で置き換えれる。
型を厳密に定義する。(any型も便利ですけど)
・autherの取得を正しく行えるようにする。
・注文詳細ページでの情報取得が並列動作している。1ページずつの逐次の方が好ましい。
*amazonなので負荷は問題にならないと思いますが行儀の問題。
・Amazonの購入履歴を開いてから情報取得までを一連で行うクライアントの開発
*Amazonのスマホアプリが購入済み製品を警告してくれないのでダブる対策や既刊買ってるのに新刊をオススメしてくれなくて買い逃す対策したい。