【GASスクレイピング】スプレッドシートで株管理【超簡易サンプル】

テクノロジー

こちらの記事

ご好評につきたくさんのアクセスを頂いております(ありがとうございます!)

しかし、内容の難易度が高いことから質問もいくつか頂いております

その中でも多くもらっている質問に答えるため、超簡易サンプルを提供させていただけたらと思います

経緯

多く頂いている質問の多くが

このサンプルはスプレットシートと連携はできているの?

というものでした

はい、実はできていません(すいません🙇‍♂)

情報取得はできていますが、それをログに出すところまでのサンプルになります

ということでスプレットシートと連携する超簡易サンプルを用意しました

実装コード

実装コードはこちらになります

コード.gs
function getTag(str, offset)
{
  var res = {};

  res.begin = str.indexOf('<', offset);
  res.end = str.indexOf('>', res.begin) + 1;
  res.tag = str.slice(res.begin, res.end);
  res.name = res.tag.replace('/','').replace('<','').replace('>','').split(' ')[0];
  res.isClose = res.tag.indexOf('</') >= 0;
  res.isComment = res.tag.indexOf('<!') >= 0;
  res.isSingle = res.tag.indexOf('/>') >= 0;

  return res;
}

function searchEnd(content, begin)
{
  var end = begin;
  var list = [];
  var offset = begin;
  while (true)
  {
    var res = getTag(content, offset);
    if (res.begin < 0) break;
    offset = res.end;

    if (res.isSingle) continue;
    if (res.isComment) continue;

    if (res.isClose)
    {
      while (list.length > 0)
      {
        var name = list.shift();
        if (name == res.name) break;
      }
    }
    else
    {
      list.unshift(res.name);
    }

    if (list.length <= 0)
    {
      end = offset;
      break;
    }
  }
  return end;
}

function removeParentTag(content)
{
  var begin = content.indexOf('>') + 1;
  var end = content.lastIndexOf('<');
  return content.slice(begin, end);
}

function searchId(content, hierarchy)
{
  var id = hierarchy.replace('*[@','').replace(']','');
  var index = content.indexOf(id);
  return content.lastIndexOf('<', index);
}

function searchTag(content, hierarchy)
{
  var array = hierarchy.replace('[', ',').replace(']', '').split(',');

  var tag = array[0];
  var count = 1;
  if (array.length > 1)
  {
    count = parseInt(array[1]);
  }

  var begin = 0;
  var list = [];
  var offset = 0;
  while (true)
  {
    var res = getTag(content, offset);
    if (res.begin < 0) break;
    offset = res.end;

    if (res.isSingle) continue;
    if (res.isComment) continue;

    if (res.isClose)
    {
      while (list.length > 0)
      {
        var name = list.shift();
        if (name == res.name) break;
      }
    }
    else
    {
      if (list.length <= 0)
      {
        if (tag == res.name)
        {
          --count;
        }
      }
      list.unshift(res.name);
    }

    if (count <= 0)
    {
      begin = res.begin;
      break;
    }
  }
  return begin;
}

function searchBegin(content, hierarchy)
{
  var index = hierarchy.indexOf('@');
  if (index < 0)
  {
    return searchTag(content, hierarchy);
  }
  return searchId(content, hierarchy);
}

function extractText(content)
{
  var offset = 0;
  var res = getTag(content, offset);
  if (res.begin < 0)
  {
    return content;
  }
  var begin = searchTag(content, res.name);
  var end = searchEnd(content, begin);
  var remove = content.slice(begin, end);
  return content.replace(remove, '');
}

function narrow(content, hierarchy)
{
  if (hierarchy.length <= 0) return content;

  if (hierarchy.indexOf('text()') >= 0)
  {
    return extractText(content);
  }

  var begin = searchBegin(content, hierarchy);
  var end = searchEnd(content, begin);
  var target = content.slice(begin, end);
  return removeParentTag(target);
}

function searchXPath(content, xpath)
{
  var result = [];
  for (var i in xpath)
  {
    var target = content;
    var array = xpath[i].split('/');
    for (var j in array)
    {
      if (array[j].length <= 0) continue;
      target = narrow(target, array[j]);
    }
    result.push(target);
  }
  return result;
}

function searchXPathFromURL(url, xpath)
{
  var content = UrlFetchApp.fetch(url).getContentText('UTF-8');
  return searchXPath(content, xpath);
}

function getInformation(range)
{
  // セルから銘柄コードを取得
  var code = range.getValue();

  // 銘柄コードから URL を生成 (xxxxxxx.xx の部分は適宜変更してください)
  var url = 'https://xxxxxxx.xx/stock/?code=' + code;

  // 銘柄名の XPath
  var name = '//*[@id="stockinfo_i1"]/div[1]/h2/text()';  // 銘柄名
  // 株からの XPath
  var price = '//*[@id="stockinfo_i1"]/div[2]/span[2]';   // 株価
  // XPath の配列を用意します
  var xpath = [name, price];

  // ページ情報を HTML 形式(文字列)で取得
  // このタイミングでページにアクセスしています
  var content = UrlFetchApp.fetch(url).getContentText('UTF-8');
  
  // HTML 解析を行い、指定の XPath の情報を取得します
  var result = searchXPath(content, xpath);

  // 取得した銘柄名を銘柄コードのセルの1つ右隣に設定
  range.offset(0, 1).setValue(result[0]);
  // 取得した株価を銘柄コードのセルの2つ右隣に設定
  range.offset(0, 2).setValue(result[1]);
}

function Execute()
{
  // スプレットシートを取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // 今回読み書きするシートを名前で取得
  var sheet = spreadsheet.getSheetByName('銘柄一覧');

  // シートから銘柄コードのあるセルを取得し、getInformation に渡す
  getInformation(sheet.getRange("A2"));
  getInformation(sheet.getRange("A3"));
  getInformation(sheet.getRange("A4"));
}

 

こちらの記事に載せているコードの一部を改変したものになります

コード解説

元々 Text_01 となっていたメソッドを getInformation というメソッドに置き換えました

またセルごとに処理を行うため Execute というメソッドで getInformation を銘柄分呼び出しています

詳細な解説は実装コード中に記載していますので、参考にしていただければと

実行方法

スプレッドシートはこんな感じで用意します

手順は、

  1. [拡張機能] → [App Script] で コード.gs を追加
  2. 実行ボタンを右クリック、[︙] から [スクリプトを割り当て] で、Execute を設定
  3. 実行ボタンを押す

結果は、

こんな感じで取得した情報がスプレッドシート上に表示されます!

まとめ

今回はスプレッドシートの特定のセルを3つ参照する形で実装してみました

下の行に追加していくと自動で参照するようにもできると思います

getLastRowfor文 などを使うとできると思います

また今回は「銘柄名」と「株価」のみを取得していますが、実際はもっと取得できます

その辺りの拡張は元になっている記事の実装コードを参考にして、追加してみてください!

以上、参考になれば幸いです!


このあたりの書籍、面白いです!よかったら!

コメント

タイトルとURLをコピーしました