[JavaScript]SBI証券のポートフォリオのデータを抜き取ってHTMLに変換するブックマックレットを作った。

株式投機の記録をするために作ったブログで使うために、SBI証券のポートフォリオのデータを抜き取ってHTMLに変換するブックマックレットを作った。

bookmarklet←完成品

SBI証券ログイン後のポートフォリオの画面(上の画像を参照)でこのブックマークレットを使うとテーブルHTMLを生成して、左上にテキストエリアで表示する。★★★の部分は手動で入力…ポートフォリオの画面に出てこない数字だから。。

メモ

なんだか作っててグダグダだったな…ヘタクソなソースだ。まぁブックマークレットはいちおうキチンと動くからいいけど、もっと基本的なことしっかり覚えなきゃ。

以下、読む価値はないソース

/* 抽出用RegExp */
//それぞれの株のポートフォリオ
var regex_pf_each = new RegExp('<B>株式(現物/特定預り)</B>[\\s\\S]+?</table>', 'i');
//合計のポートフォリオ
var regex_pf_sum = new RegExp('株式\\(現物/特定預り\\)<br>合計[\\s\\S]+?</table>', 'i');
//TR要素
var regex_pf_tr = new RegExp('<tr[^>]*?>[\\s\\S]+?</tr>', 'ig');
//TD要素
var regex_pf_td = new RegExp('<td[^>]*?>[\\s\\S]*?</td>', 'ig');

/* データ抽出用の関数 */
/**
 - テーブルHTMLをスクレイピングして get_pf_data 関数に渡す。
 - で、get_pf_data が処理して返してきた配列データをそのまま返す
 -
 - @param string data
 - @param object RegExp
 - @return array
 */
function scrape_table(htmldata, regex)
{
  var scraped_table = htmldata.match(regex)[0];
  return get_all_pf_data(scraped_table);
}

/**
 - 引数に渡されたテーブルのHTMLデータをtr要素に分解後、
 - tr要素内の各データを取り出して、配列にして返す。
 - scrape_table() から呼ばれる
 *
 - @param string table
 - @return array All PortFolio Data
 */
function get_all_pf_data(table)
{
  // 抽出データ格納場所
  var all_pf_data = new Array();

  // 各tr要素を取り出す
  var tr_data = table.match(regex_pf_tr);

  // 各tr要素をcvsっぽいデータに変換して
  // all_pf_data に渡す
  var i;
  for(i=0; i < tr_data.length; i++)
  {
    all_pf_data[i] = get_pf_data(tr_data[i]);
  }
  return all_pf_data;
}

/**
 - 引数に含まれるtd要素から各データを取り出して返す
 - get_all_pf_data() から呼ばれる。
 *
 - @param arguments
 - @return string data
 */
function get_pf_data(td_data)
{
  var pf_data = [];
  var data = td_data.match(regex_pf_td);
  var i;
  for(i=0; i < data.length; i++)
  {
    data[i] = data[i].replace(/<[^>]*>/g, '');
    pf_data.push( data[i] );
  }
  return pf_data.join('|/|');
}

/* 抽出したデータをテーブルHTMLに変換する関数
 -
 - @param array data table_data テーブルのデータ
 - @param string top_html テーブルの最初の部分
 - @param array ignore_line 無視する行
 - @param array ignore_column 無視する列
 */
function html_pf_each(data, top_html, ignore_lines, ignore_columns)
{
  var contents= [];

  // テーブルHTMLの先頭の部分
  if(typeof top_html === 'string'){
    contents.push(top_html);
  }else{
    contents.push('<table>');
  }

  var arr = [];
  var i,j,k,x,y,tr;

  lines :
  for(i=0; i < data.length; i++)
  {
    // 指定行を無視する
    if(ignore_lines instanceof Array){
      for(x = 0; x < ignore_lines.length; x++){
        if( i === ignore_lines[x] ){
          continue lines;
        }
      }
    }

    // 行の色分け
    if( i%2 === 1 ){
      tr = '<tr class="c_pf01">';
    } else {
      tr = '<tr class="c_pf02">';
    }
    contents.push(tr);
    arr[i] = data[i].split('|/|');

    columns :
    for(j=0; j < arr[i].length; j++)
    {
      // 指定列を無視する
      if(ignore_columns instanceof Array){
        for(y = 0; y < ignore_columns.length; y++){
          if( j === ignore_columns[y] ){
            continue columns;
          }
        }
      }

      // プラスは赤字、マイナスは青地
      if(arr[i][j].substr(0,1) === '+'){
        k = '<span class="pf_plus">';
        k += arr[i][j];
        k += '</span>';
        arr[i][j] = k;
      }else if(arr[i][j].substr(0,1) === '-' && arr[i][j].substr(0,2) !== '--'){
        k = '<span class="pf_minus">';
        k += arr[i][j];
        k += '</span>';
        arr[i][j] = k;
      }
      contents.push('<td>');
      contents.push(arr[i][j]);
      contents.push('</td>');

    }
    contents.push('</tr>');
  }
  contents.push('</table>');

  // 結合してHTMLエスケープ
  contents = contents
    .join('')
    .replace(/&/g, '&amp;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
  return contents;
}

/* HTMLをテキストエリアに出力
 *
 - @param string str 出力したい文字列
 - @return void
 */
function output(str){
  var div_ele = document.createElement('div');
  div_ele.style.zIndex = '100';
  div_ele.style.position = 'absolute';
  div_ele.style.top = '20px';
  div_ele.style.left = '20px';

  var ta_ele = document.createElement('textarea');
  ta_ele.innerHTML = str;
  ta_ele.onclick =
    function()
    {
      this.focus();
      this.select();
    };

  div_ele.appendChild(ta_ele);
  document.body.appendChild(div_ele);
}

/* データの生成~出力 */
var _output_html = scrape_table(document.body.innerHTML, regex_pf_sum);
_output_html = _output_html[0].split('|/|');

var output_html = [];
output_html[0] = '';
output_html[1] = '<span class="b">資産</span>';
output_html[2] = '★★★';
output_html[3] = '<span class="b">余力</span>';
output_html[4] = '★★★';
output_html[5] = '<span class="b">合計</span>';
output_html[6] = _output_html[3];
output_html[7] = _output_html[1];
output_html[8] = _output_html[2];
output_html[9] = _output_html[0];
output_html[10] = "";
output_html = [output_html.join("|/|")];
output_html = scrape_table(document.body.innerHTML, regex_pf_each).concat(output_html);
output_html = html_pf_each(
  output_html,
  '<table class="portfolio"><tr class="c_pf00"><th>銘柄</th><th>買付日</th><th>数量</th><th>取得単価</th><th>現在値</th><th>基準値比</th><th>損益</th><th>損益(%)</th><th>評価額</th></tr>',
  // 0行目はただの目次なので不要。
  [0],
  // (0)取引 (1)銘柄 (2)買付日 (3)数量 (4)取得単価 (5)現在値
  // (6)前日比/基準値比 (7)損益 (8)損益% (9)評価額 (10)編集
  // という順番で並んでいる。(0) と (10) は不要。したがって…
  [0,10]
);
output(output_html);

これを一行に変換してHTMLエスケープしてブックマークレット化。とりあえず動けばいいみたいな内容のプログラム。

最近ミスったメモ

このエントリとは関係ないっす。

  • or 演算子が使えなかった
  • いつのまにか変数に $ が付いてた。phpじゃないってば
  • elseif じゃなくて else if だった
  • header で window.onload を使わずに getElementById つかって動かない
  • object.foo.bar = function(){} で foo が未定義で動かない
  • object.foo(){} という表記でメソッド定義をしようとして動かない
Share
関連記事