【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

魔王と愉快な仲間

このブログを検索

ラベル

Blogger (7) FX (1) GAS (13) Utility (1) ゲーム (1) ツール (9) プログラミング (19) レポート (2) 移住 (3) 覚書 (1) 金策 (9) 手法 (1) 土壌 (2) 独り言 (5) 読み物 (22) 農業 (3) 農薬 (1)

ブログ アーカイブ

メッセージ

名前

メール *

メッセージ *

Powered by Blogger.

フリー写真素材ぱくたそ

QooQ