Google Apps ScriptでYahoo Finance（米国版）の財務データをスクレイピング

#やったこと
+ スプレッドシートに営業キャッシュフローマージンを調べたい米国企業のティッカーシンボルを記入
+ このティッカーシンボルをもとに、米国版yahoo financeから対応する銘柄の営業キャッシュフローと売上高をスクレイピング
+ それらの比率を計算し、スプレッドシートに書き出し

最近米国株に興味が出て「ＭａｒｋｅｔＨａｃｋ流 世界一わかりやすい米国式投資の技法」という本を読みました。
本の中に、営業キャッシュフローマージンが15〜35%ある会社を狙えと書いてありました。
営業キャッシュフローマージンの算出は、米国版yahoo financeの「financials」ページにある、"Total Cash Flow From Operating Activities"（営業キャッシュフロー）と"Total Revenue"（売上高）の比をとれば良いとのことです。
GASの勉強がてら、これをスクレイピングしてスプレッドシートに書き出すようにしてみました。
※売上高（Total Revenue）のページ。日付もこのページのRevenueの行から抜き出す。
<img width="910" alt="スクリーンショット 2019-05-20 0.11.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250449/d8608a20-d3f3-4fcb-7e59-2d7374748b1f.png">

※営業キャッシュフロー（Total Cash Flow From Operating Activities）のページ。
<img width="911" alt="スクリーンショット 2019-05-20 0.11.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250449/0223cc02-f8da-f344-2977-40a261048a0d.png">



※日本のyahooファイナンスはスクレイピング禁止とのことですが、米国版の方をざっと見た所、そのような記述が見当たりませんでした。間違っていたらすいません。

変数名とかクラス名がアレですが、↓メインの流れ。

```javascript
function my_Function(){
  //スプレッドシートに記入されているティッカーを配列として取得
  var sheet = SpreadsheetApp.getActiveSheet();
  var ticker_array = sheet.getRange(2, 1, sheet.getLastRow()-1, 1).getValues();

  //銘柄ごとに、後述のStock_itemインスタンスを作成
  var output_array = [];
  for(var i = 0; i<ticker_array.length; i++){
    var Stock_item_1 = new Stock_item(ticker_array[i]);
    
    //get_item_arrayメソッドを実行。items配列の要素に合致するデータをサイトから取得。メンバーのdata_arrayにpushしていく。Revenueとしているが実態は決算の日付を取得。
    var items = ['Revenue','Total Revenue','Total Cash Flow From Operating Activities'];
    for(var j = 0; j<items.length; j++){
      Stock_item_1.get_item_array(items[j]);
      };
    
    //get_marginメソッドで営業キャッシュフローマージンを計算し、data_array配列にpush。
    Stock_item_1.get_margin();
    var output_array = output_array.concat(Stock_item_1.data_array);
  };
  

  //スプレッドシートに書き出し
  sheet.getRange(2, 3, output_array.length, output_array[0].length).setValues(output_array);
}

```


コンストラクタ↓。インスタンス作成時に、プロパティにティッカーシンボルを設定。

```javascript
var Stock_item = function(ticker){
  this.ticker = ticker;
  this.data_array =[];//空の配列。get_item_arrayメソッドで取得データをpush
};
```


get_item_arrayメソッド↓。銘柄ごとに、日付、売り上げ、営業キャッシュフロー（これらをitemとしました）をスクレイピングで取得し、プロパティに配列として設定。メソッドとはこんな感じで良いのでしょうか。。。

```javascript
Stock_item.prototype.get_item_array = function(item){
  this.item = item;
  
  //itemによって適当なURLを設定。★要エラー処理。
  var URL_base = 'https://finance.yahoo.com/quote/';
  if (this.item != "Total Cash Flow From Operating Activities"){
    this.URL = URL_base + this.ticker + '/financials?p=' + this.ticker;
  } else {
    this.URL = URL_base + this.ticker + '/cash-flow?p=' + this.ticker;
  }
  
  //HTMLを取得。目的の数字が<span>タグで囲まれていたので、これでHTML内検索。
  //タグを削除した配列にし、目的の値のみ抜き出し。
  var html = UrlFetchApp.fetch(this.URL).getContentText();
  html = html.match(/<span data-reactid=".*?<\/span>/gi);//ここからhtmlは配列
  html = html.map(function(value,index,array){
    return removeTag(value);
  });
  var begin_index = html.indexOf(this.item);
  var temp_array = html.slice(begin_index,begin_index+5);
  this.data_array.push(temp_array);
};
```

get_marginメソッド↓。営業キャッシュフローマージンを計算してthis.data_array配列に追加する。スクレイピングした値が文字列だったので、カンマを取り除き数値に変換しています。

```javascript
Stock_item.prototype.get_margin = function(){
  var _ = Underscore.load();
  var temp_Trans = _.zip.apply(_, this.data_array);
  var i_TR = temp_Trans[0].indexOf('Total Revenue');
  var i_CF = temp_Trans[0].indexOf('Total Cash Flow From Operating Activities');
  
  var margin = ["C/F margin"];
  for (var i = 1; i<5; i++){
    var value_cf = parseInt(this.data_array[i_CF][i].replace(/,/g, ""),10);//カンマ取り除いて整数にする。
    var value_tr = parseInt(this.data_array[i_TR][i].replace(/,/g, ""),10);
    var value_margin = value_cf/value_tr;
    margin.push(value_margin);
  };
  
  this.data_array.push(margin);
};
```

タグ削除関数↓。get_item_arrayメソッド内で、とってきたHTMLの配列の各要素からタグを削除する。

```javascript
function removeTag(str){
  return str.replace(/<\/?[^>]+>/gi, '');
}
```

###実行前
<img width="931" alt="スクリーンショット 2019-05-20 0.01.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250449/8cf2dd84-309a-0215-fe2d-426c928f8e88.png">

###実行後
出力した表のどれがどの銘柄なのかわかるようにしたり、グラフによる可視化などを今後付け加えたいです。Visaの営業キャッシュフローマージンがかなり高い。
<img width="936" alt="スクリーンショット 2019-05-20 0.02.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250449/42027c79-f169-09e6-e068-4b1541a0d320.png">

###参考にしたもの
参考になりました。
https://www.amazon.co.jp/dp/B07BNB1Z9L/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1