【GAS】実践・スクレイピング

2021-01-12

GAS プログラミング

B!

シンプルで手っ取り早い方法。
エラーチェックなど、改良が必要です。
また、トリガーで使用する場合は制限がありますので注意が必要です。




システム要件・完成目標とイメージ

とりあえず今回は適当なyahoo!オークションのこんな感じのページから、「リンクタイトル」「値段」「url」の3つのデータを取り出し一覧にするという簡単なものとします。
スクレイピングをするにあたり、「Parser」というライブラリを使用します。
「Parser」の他にも色々なライブラリがありますので、探してみると面白いかもしれません。

スプレッドシートの準備

まずはスプレッドシートを用意します。 イメージはこんな感じで。ここはas you likeです。
メニューの「ツール」「拡張機能」からスクリプトエディタを起動します。
まだインストールしてないよって人はインストールから。

Parserライブラリの導入

Parserライブラリを使用するため、プロジェクトに導入していきます。
左側の「ライブラリ」から+ボタンを押して追加します。
スクリプトIDに「1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw」を入力し、「検索」。
バージョンは「8」で、「追加」。

これでParserを使用する準備が出来ました。

ソースコード

// -----------------------------------------------------------------------------
// スクレイピングサンプル.
// -----------------------------------------------------------------------------

// 出力先のスプレッドシートID.
var SheetID = "スプレッドシートのIDを指定";

// 定数.
var DataStartY = 2;
var DataTitleX = 1;
var DataPriceX = 2;
var DataURLX = 3;

// -----------------------------------------------------------------------------
// myFunction.
// 名前はどうだっていい.
// -----------------------------------------------------------------------------
function myFunction() {

  var outSheet = SpreadsheetApp.openById(SheetID).getSheetByName('log');

  // リセット処理.
  outSheet.getRange( 2,1, outSheet.getLastRow() ).clearContent();

  var options = {muteHttpExceptions : true};
  var response = UrlFetchApp.fetch(
    'ここにスクレイピング先のURLを指定',
     options );
  
  // タイトルを取得.

  var fromText = '<h3 class="Product__title">';
  var toText = '</h3>';
  
  var dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();

  // <a>タグを外す処理.
  for(var i = 0; i < dataList.length; i++ ) {
    dataList[i] = getTitle( dataList[i] );
  }
  outputData( outSheet, dataList, DataTitleX );

  // urlを取得.
  dataList.splice(0);
  dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
  // urlを取り出す処理.
  for(var i = 0; i < dataList.length; i++ ) {
    dataList[i] = getURL( dataList[i] );
  }
  outputData( outSheet, dataList, DataURLX );

  // 値段を取得.
  fromText = '<span class="Product__priceValue u-textRed">';
  toText = '</span>';
  dataList.splice(0);
  dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
  outputData( outSheet, dataList, DataPriceX );

}


// -----------------------------------------------------------------------------
// outputData.
// 指定スプレッドシートにスクレイピング結果を出力する.
// -----------------------------------------------------------------------------
function outputData( outSheet, dataArray, indexX ) {
  for(var i = 0; i < dataArray.length; i++ ) {
    outSheet.getRange(i + DataStartY, indexX).setValue( dataArray[i] );
  }
}

// -----------------------------------------------------------------------------
// getTitle.
// 指定stringから<a>ここを抜き出す</a>.
// 失敗したら"".
// -----------------------------------------------------------------------------
function getTitle( str ) {
  var tmp = str.match(/>.*?</gi);
  if ( tmp === null ) { return ""; }
  return tmp[0].substr(1, tmp[0].length-2);
}
// -----------------------------------------------------------------------------
// getURL.
// 指定stringからhref="ここを抜き出す".
// 失敗したら"".
// -----------------------------------------------------------------------------
function getURL( str ) {
  var tmp = str.match(/href=".*?"/gi);
  if ( tmp === null ) { return ""; }
  return tmp[0].substr(6, tmp[0].length-7);
}

実行結果

解説

6行目:スプレッドシートID

// 出力先のスプレッドシートID.
var SheetID = "スプレッドシートのIDを指定";
スプレッドシートのIDとは、スプレッドシートを開いた時のURLの「d/~/」「~」部分です。

20行目:シート名

  var outSheet = SpreadsheetApp.openById(SheetID).getSheetByName('log');
「log」の部分は各々のシート名に合わせてください。

32行目:タイトルを取得するためのタグを設定

  var fromText = '<h3 class="Product__title">';
  var toText = '</h3>';
スクレイピングしたいページのコードを見て、タイトル部分を表示しているタグを探します。

コードはChromeの場合、右上のメニューから「その他のツール」→「デベロッパーツール」で見れます。
<h3 class="Product__title">
	<a class="Product__titleLink" href="https://page.auctions.yahoo.co.jp/jp/auction/k521422870" rel="noopener" target="_blank" data-ylk="rsec:aal;slk:tc;pos:1;atax:0;arbn:;catid:2084048018;cid:k521422870;etc:p=2222,etm=1610806119,stm=1610201319,w=2,wtm=1610424400,we=1,wo=1,vsc=-1.2394298261409065;sid:ekalder_xf;st:1610201319;end:1610806119;op:;grat:100.0;ppstr:;seltyp:2;best:" title="ローズマリー マリンブルー 5号 スリット鉢" data-rapid_p="155">ローズマリー マリンブルー 5号 スリット鉢</a>
</h3>
例の場合、<h3 class="Product__title">から</h3>がすべての商品名のタグで共通で使用されることがわかります。
これを指定すると、<a>~</a>がごっそり取得されますが、気にせず進めます。

35行目:

  var dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
システムに丸投げです。ありがたや。
配列形式で返ってきます。

38行目・77行目:取得したデータからタイトル文字列のみを取り出す

  // <a>タグを外す処理.
  for(var i = 0; i < dataList.length; i++ ) {
    dataList[i] = getTitle( dataList[i] );
  }
function getTitle( str ) {
  var tmp = str.match(/>.*?</gi);
  if ( tmp === null ) { return ""; }
  return tmp[0].substr(1, tmp[0].length-2);
}  
getTitle()内でmatch()を使った文字列取得処理をしています。
ここの処理は色々と方法があるので、これが一番、という事ではありません。
今回はこの方法でやってみた。というだけの事です。

41行目・66行目:スプレッドシートに入力する

  outputData( outSheet, dataList, DataTitleX );
function outputData( outSheet, dataArray, indexX ) {
  for(var i = 0; i < dataArray.length; i++ ) {
    outSheet.getRange(i + DataStartY, indexX).setValue( dataArray[i] );
  }
}
outputData()では指定列にデータを入力する処理を書いています。
適当なので、参考程度に。

以下、値段、urlも同じような処理をします。



ブログランキング・にほんブログ村へ

Translate

魔王と愉快な仲間

このブログを検索

人気の投稿

ラベル

ブログ アーカイブ

メッセージ

名前

メール *

メッセージ *

Powered by Blogger.

フリー写真素材ぱくたそ

QooQ