2018-02-20

【GAS】IMPORTXML関数で取得した値を、1時間おきに定期実行で行を追加する

IMPORTXML関数で取得した結果を、一時間おきに新たに行に追加する




前回は相席屋の空席情報をIMPORTXML関数を利用して、スクレイピングしました。

相席居酒屋の空席状況をリアルタイムでスプレッドシートに更新し、グラフ化することで男しかいない糞相席屋を撲滅する試み

糞相席屋を撲滅する試み 昔友達とネタで相席居酒屋に入ったら、男しかいなくて「相席でもなんでもねえじゃん」と思って遺憾の意だったため。行くまで空席状況がわかりにくいというのが問題だと思う。

今回は、Google Apps Scriptのスクレイピングを、IMPORTXML関数で行い、その結果をGoogle Apps Scriptで定期実行プログラムを組むことによって、時系列データを取得してみたいと思います。これをすることによって、リアルタイムの1点の値ではなく、時系列データを取得することができるようになります。





手順としては、

1. IMPORTXML関数で各相席屋の空席状況を取得し、表形式にまとめる
2. 1時間おきに、それらのリストから時系列データを各シートにまとめる

という流れです。

取得するページ


例によって以下3店舗の在籍情報をリアルタイムで更新したいと思います。

ORIENTAL LOUNGE EVE SHIBUYA
渋谷区宇田川町13-8 ちとせ会館7階

ORIENTAL LOUNGE EVE SHINJUKU
新宿区歌舞伎町2-23-1 風林会館5F

ORIENTAL LOUNGE EVE MACHIDA
町田市原町田6-7-8ティップス町田ビル4階

1. IMPORTXML関数で各相席屋の空席状況を取得し、表形式にまとめる

IMPORTXML関数で、リアルタイムの結果を反映します。
以下のページで、全店舗の現在の在籍状況が分かるページがあるので、こちらのページからデータを取得します。

ORIENTAL LOUNGE GROUP(オリエンタルラウンジグループ)

出会いのある合コンスタイルの相席ラウンジを展開するORIENTAL LOUNGE GROUP(オリエンタルラウンジグループ)。


importxml関数では、引数にURLと、取得したい値のXPATHを指定します。なので、
A9、A10、A11のセルには、上記のURLを設定し、IMPORTXML関数の第一引数にURLのセル、第二引数に該当するXPATHを取得します。

=importxml(A9,"//a[@id='box_shinjuku']") =importxml(A10,"//a[@id='box_shibuya']")
=importxml(A11,"//a[@id='box_machida']")


この結果、XPATHで取得したデータをリアルタイムで更新できます。

Google Apps Scriptで定期実行


次に、このスクレイピングした結果を1時間おきにセルに追加し、時系列データを取得します。その場合、


1. IMPORTXML関数でスクレイピングした男性・女性数の2つのセルの範囲を指定して、値を取得する
2. Google Apps Scriptによって取得した値を、別のシートを選択し、そこに1時間おきに値を追加していく


という流れになります。それを実現しているコードが下記のようになります。

//TODO: スプレッドシートの取得

//スプレッドシートのid  
var id= "1zfy9Np2E7sB4tj570YaTap5o8VM_wC7IoCaRCU19CLw"
var File = SpreadsheetApp.openById(id);
var baseSheet = File.getSheets()[0]; 


function MainFrame() {

  //TODO: スプレッドシートの決まった箇所に決まった値を挿入
  setManFemaleNumList(1,getMenFemaleArray(17,4,1,2)); //D17 2行分取得
  setManFemaleNumList(2,getMenFemaleArray(18,4,1,2));  
  setManFemaleNumList(3,getMenFemaleArray(19,4,1,2));  
}

//TODO:スプレッドシートに、相席ラウンジ 銀座店の現在の男女の数を行に追加する
function setManFemaleNumList(sheetNum, manFemaleArray){
  var Sheet = File.getSheets()[sheetNum];
  Sheet.appendRow(manFemaleArray);
}


//TODO:指定範囲のセルから、取得日時 男性数 女性数をリターンする

function getMenFemaleArray(row,col,rowNum,colNum){
  var array = baseSheet.getRange(row,col,rowNum,colNum).getValues()[0];
  var date = new Date();
  array.unshift(date)
  return array; // 取得日時 男性数 女性数をリターンする
}

この結果を、定期実行します。定期実行の方法は過去記事を参照してください。


Google Apps Scriptでスクレイピングを定期実行して、News Picksのソーシャルデータを取得する方法をまとめてみた

Google Apps Script(GAS)でスクレイピング Google Apps Scriptで、Web上のデータのスクレイピングを定期実行する方法をまとめてみたいと思います。 


取得結果はどんな感じになる?


スプレッドシートに1時間おきに反映されています。
https://docs.google.com/spreadsheets/d/1zfy9Np2E7sB4tj570YaTap5o8VM_wC7IoCaRCU19CLw/edit#gid=626799838

渋谷店のデータだと例えばこんな感じ。



取得した値を時系列グラフにします。渋谷店の在籍状況です。



新宿店



町田店



今回はコードの解説は特にしませんが、今後使いそうな関数の忘備録としてまとめていきたいと思います。

getSheets()


指定されているシートをリスト形式で取得します。例えばシートが5つの存在する場合は、5つ分をリスト形式で取得します。1つしかタブがない場合は、getSheets()[0]で取得することができるみたいです。二つ目のシートはgetSheets()[1]で取得できます。

getRange(row, column, rownum, colnum)


シートから、範囲を指定することができます。引数には、行番号、列番号、取得する行数、取得する列数が指定できます。例えば、A1からA2のセルを取得したい場合は、
getRange(1,1,1,2)となります。A1からB1を取得したい場合は、getRange(1,1,2,1)となります。

getValues()


取得した範囲オブジェクトから、値を取得します。取得結果は、二次元配列で返されます。二次元配列に関しては、下記の記事を参考にしてください。

多次元配列 - 配列 - JavaScript入門

配列の要素に別の配列を代入し多次元配列として利用する方法を確認します

appendRow(array)


シートの一番下の行に、配列を挿入します。こちらは1次元配列を挿入しなければなりません。getValuesの結果は2次元配列なので、取得した値を行に追加したい場合は、1次元配列にするために最初の行をインデックス指定して、挿入しています。

function getMenFemaleArray(row,col,rowNum,colNum){
  var array = baseSheet.getRange(row,col,rowNum,colNum).getValues()[0];
  var date = new Date();
  array.unshift(date)
  return array; // 取得日時 男性数 女性数をリターンする
}


ログインが必要なく、かつクリックなどの操作が必要なく、一定のVIEWをスクレイピングするだけなら、Google Apps Scriptでスクレイピングするのが非常によい選択肢だと思われます。





注目の投稿

 PythonのTweepyを利用して、Twitter APIを利用している。 その中で、ハマったポイントをメモしておく。 まず、Searchに関して。 Twitter検索は、クライアントアプリ側では、全期間の検索が可能になっている。 一方で、APIを利用する際は、過去1週間しか...