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

2021-01-12

GAS プログラミング

B!

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




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

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

スプレッドシートの準備

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

Parserライブラリの導入

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

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

ソースコード

  1. // -----------------------------------------------------------------------------
  2. // スクレイピングサンプル.
  3. // -----------------------------------------------------------------------------
  4. // 出力先のスプレッドシートID.
  5. var SheetID = "スプレッドシートのIDを指定";
  6. // 定数.
  7. var DataStartY = 2;
  8. var DataTitleX = 1;
  9. var DataPriceX = 2;
  10. var DataURLX = 3;
  11. // -----------------------------------------------------------------------------
  12. // myFunction.
  13. // 名前はどうだっていい.
  14. // -----------------------------------------------------------------------------
  15. function myFunction() {
  16. var outSheet = SpreadsheetApp.openById(SheetID).getSheetByName('log');
  17. // リセット処理.
  18. outSheet.getRange( 2,1, outSheet.getLastRow() ).clearContent();
  19. var options = {muteHttpExceptions : true};
  20. var response = UrlFetchApp.fetch(
  21. 'ここにスクレイピング先のURLを指定',
  22. options );
  23. // タイトルを取得.
  24. var fromText = '<h3 class="Product__title">';
  25. var toText = '</h3>';
  26. var dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
  27. // <a>タグを外す処理.
  28. for(var i = 0; i < dataList.length; i++ ) {
  29. dataList[i] = getTitle( dataList[i] );
  30. }
  31. outputData( outSheet, dataList, DataTitleX );
  32. // urlを取得.
  33. dataList.splice(0);
  34. dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
  35. // urlを取り出す処理.
  36. for(var i = 0; i < dataList.length; i++ ) {
  37. dataList[i] = getURL( dataList[i] );
  38. }
  39. outputData( outSheet, dataList, DataURLX );
  40. // 値段を取得.
  41. fromText = '<span class="Product__priceValue u-textRed">';
  42. toText = '</span>';
  43. dataList.splice(0);
  44. dataList = Parser.data(response.getContentText()).from(fromText).to(toText).iterate();
  45. outputData( outSheet, dataList, DataPriceX );
  46. }
  47. // -----------------------------------------------------------------------------
  48. // outputData.
  49. // 指定スプレッドシートにスクレイピング結果を出力する.
  50. // -----------------------------------------------------------------------------
  51. function outputData( outSheet, dataArray, indexX ) {
  52. for(var i = 0; i < dataArray.length; i++ ) {
  53. outSheet.getRange(i + DataStartY, indexX).setValue( dataArray[i] );
  54. }
  55. }
  56. // -----------------------------------------------------------------------------
  57. // getTitle.
  58. // 指定stringから<a>ここを抜き出す</a>.
  59. // 失敗したら"".
  60. // -----------------------------------------------------------------------------
  61. function getTitle( str ) {
  62. var tmp = str.match(/>.*?</gi);
  63. if ( tmp === null ) { return ""; }
  64. return tmp[0].substr(1, tmp[0].length-2);
  65. }
  66. // -----------------------------------------------------------------------------
  67. // getURL.
  68. // 指定stringからhref="ここを抜き出す".
  69. // 失敗したら"".
  70. // -----------------------------------------------------------------------------
  71. function getURL( str ) {
  72. var tmp = str.match(/href=".*?"/gi);
  73. if ( tmp === null ) { return ""; }
  74. return tmp[0].substr(6, tmp[0].length-7);
  75. }

実行結果

解説

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

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

20行目:シート名

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

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

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

コードはChromeの場合、右上のメニューから「その他のツール」→「デベロッパーツール」で見れます。
  1. <h3 class="Product__title">
  2. <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>
  3. </h3>
例の場合、<h3 class="Product__title">から</h3>がすべての商品名のタグで共通で使用されることがわかります。
これを指定すると、<a>~</a>がごっそり取得されますが、気にせず進めます。

35行目:

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

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

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

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

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

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



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

Translate

魔王と愉快な仲間

このブログを検索

ラベル

ブログ アーカイブ

メッセージ

名前

メール *

メッセージ *

Powered by Blogger.

フリー写真素材ぱくたそ

QooQ