【GAS】Yahooニュースをスクレイピング【サンプルソース付】

Automation
スポンサーリンク

スクレイピングを使いこなせば、インターネット上のデータを簡単に拾っていろいろやること拡がりますね。

例えば、最新のYahoo!ニュースの全カテゴリを一発で一覧に出力できたら便利です。

スクレイピングはいろいろな言語で対応可能だと思いますが、とりあえずGASで実装してみました。

Googleスプレッドシートであれば、割と簡単に自分好みのわかりやすい形にカスタマイズできます。

いろんな方法があると思いますが、正規表現によるゴリゴリの置換で実現してます。
スマートな方法ではないかもしれませんが、なるべく直感的にわかりやすいように実装してます。

もしよかったら参考にしてください。スクレイピング技術を使って必要な情報を効率的に取得しましょう。

いつのまにかYahooニュースページの仕様が変わっていたので、変更後のデータが取得できるように対応しました。※ただし、操作イメージ映像は旧のままです。ご了承ください。


スポンサーリンク

Yahoo!ニュースページの取得箇所とスクレイピング操作イメージ映像

スクレイピングで取得するYahooニュースページソースの項目と実際にマクロを起動してスプレッドシートに反映するまでの映像です。

やるべきことのイメージを沸かせてみてください。


Yahoo!ニューススクレイピングGASマクロの主な仕様

細かい処理はコメントで補足してるので、ザックリとした仕様を箇条書きで記載します。

  • Yahoo!ニュースからカテゴリ単位でページリストを取得
  • ページ番号範囲指定で複数ページを一度に取得(ただしページ制限制御あり)
  • 実行判断の確認メッセージ制御(フラグon/offあり)
  • 既に取得済データかをタイトルでチェック(既に存在している場合は反映しない)
  • ソート・枠線・フィルタ処理を追加



Yahoo!ニューススクレイピングGASマクロのソースコード

下記のソースを全てコピーして起動してください。

【GAS】Googleスプレッドシートでマクロの使い方入門【動画付】
Googleの「Google Apps Script」通称GAS。GoogleマップやGメールなど、いろんなGoogle関連のサービスと自由に連携できたり、独自のWebアプリを開発することもできる、いろんな可能性を秘めたワクワクの言語ですね...

目的に合っていない場合は適当にカスタマイズしてみてください。GASマクロの勉強にも少しは役立つと思います。

/* Yahoo!ニューススクレイピング */
function yahooNewsScraping() {
  
  // 確認メッセージフラグ
  var confirmMsgFlg = 0; // 0:確認メッセージを表示しない、1:確認メッセージを表示する
  
  // 開始位置
  var startRow = 4;
  var startColumn = 1;
  
  // 目次シートと各シート左上に目次リンク作成処理
  yahooNewsScrapingShori(confirmMsgFlg,
                         startRow,
                         startColumn);
  
}
////////////////////////////////////////////////////////////////////////////////
/* スクレイピング処理 */
function yahooNewsScrapingShori(confirmMsgFlg,
                                startRow,
                                startColumn) {
  
  var spSheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = SpreadsheetApp.getActiveSheet(); // アクティブシート
  var pageRange = 10; // ページ制限範囲
  var outColCnt = 5; // 出力列数
  var categoryCol = 1; // カテゴリ
  var titleCol    = 2; // タイトル
  var upDtTmCol   = 3; // 掲載日時
  var urlCol      = 4; // URL
  var addDtTmCol  = 5; // 追加日時
  
  var inCategory = sheet.getRange(1,2).getValue();
  var inPageNo = sheet.getRange(2,2).getValue();
  var inPageNoTo = sheet.getRange(3,2).getValue();
  
  //////////チェック//////////
  if (inCategory == "") {
    Browser.msgBox("カテゴリが入力されていません。\\n"+"処理を終了します。"+"処理を終了します。");
    return;
  }
  if (inPageNo == "") {
    Browser.msgBox("ページ番号が入力されていません。\\n"+"処理を終了します。");
    return;
  } else {
    if (isNaN(Number(inPageNo))) {
      Browser.msgBox("ページ番号が数値ではありません。\\n"+"処理を終了します。");
      return; 
    } else {
      inPageNo = Number(inPageNo);
    }
  }
  if (inPageNoTo == "") {
    inPageNoTo = Number(inPageNo);
  } else {
    if (isNaN(inPageNo)) {
      Browser.msgBox("ページ番号Toが数値ではありません。\\n"+"処理を終了します。");
      return;
    } else {
      inPageNoTo = Number(inPageNoTo);
    }
    if (inPageNo > inPageNoTo) {
      Browser.msgBox("ページ範囲指定が逆です。\\n"+"処理を終了します。");
      return;
    }
    if (inPageNoTo-inPageNo+1 > pageRange) {
      Browser.msgBox("ページ制限範囲「"+pageRange+"」を超えてます。\\n"+"処理を終了します。");
      return;
    }
  }
  
  //////////確認処理//////////
  if (confirmMsgFlg == 1) {
    var msg = "";

    if (inPageNoTo == inPageNo) {
      msg = msg
      +"・Yahooニュース「"+inCategory+"」"+inPageNo+"ページ目のリストを出力します。\\n";
    } else {
      msg = msg
      +"・Yahooニュース「"+inCategory+"」"+inPageNo+"ページ目から"+inPageNoTo+"ページ目のリストを出力します。\\n";
    }
    
    msg = msg
     +"・タイトルで存在チェックし、既に存在している場合は追加しません。\\n";
    
    // 実行確認
    if (msg != "") {
      var msgRtn = Browser.msgBox(msg+"\\n実行してよろしいですか?",Browser.Buttons.OK_CANCEL);
      if (msgRtn == 'cancel') {return;}
    }
    
  }

  //////////コンテンツ取得//////////
  var Data = [];
  for (var p=inPageNo;p<=inPageNoTo;p++) {
  
    // 対象URL取得
    switch(inCategory) {
      case '全て':
        var inUrlArr = [
          ["国内",   "https://news.yahoo.co.jp/topics/domestic?page=" + p]
         ,["国際",   "https://news.yahoo.co.jp/topics/world?page=" + p]
         ,["経済",   "https://news.yahoo.co.jp/topics/business?page=" + p]
         ,["エンタメ","https://news.yahoo.co.jp/topics/entertainment?page=" + p]
         ,["スポーツ","https://news.yahoo.co.jp/topics/sports?page=" + p]
         ,["IT",     "https://news.yahoo.co.jp/topics/it?page=" + p]
         ,["科学",   "https://news.yahoo.co.jp/topics/science?page=" + p]
         ,["地域",   "https://news.yahoo.co.jp/topics/local?page=" + p]
        ];
        break;
      case '主要':
        var inUrl = "https://news.yahoo.co.jp/topics/top-picks?page=" + p;
        break;
      case '国内':
        var inUrl = "https://news.yahoo.co.jp/topics/domestic?page=" + p;
        break;
      case '国際':
        var inUrl = "https://news.yahoo.co.jp/topics/world?page=" + p;
        break;
      case '経済':
        var inUrl = "https://news.yahoo.co.jp/topics/business?page=" + p;
        break;
      case 'エンタメ':
        var inUrl = "https://news.yahoo.co.jp/topics/entertainment?page=" + p;
        break;
      case 'スポーツ':
        var inUrl = "https://news.yahoo.co.jp/topics/sports?page=" + p;
        break;
      case 'IT':
        var inUrl = "https://news.yahoo.co.jp/topics/it?page=" + p;
        break;
      case '科学':
        var inUrl = "https://news.yahoo.co.jp/topics/science?page=" + p;
        break;
      case '地域':
        var inUrl = "https://news.yahoo.co.jp/topics/local?page=" + p;
        break;
      default:
        Browser.msgBox("対象外のカテゴリです。\\n"+"処理を終了します。");
        return;
    }
    
    // HTML結果取得
    if (inCategory == "全て") {
      for (var i=0;i<\/div><\/div><\/div><\/a><\/li>/g);
  var liTag,aTag,url,dlTag,title,category,timeTag,upDtTm,upDate,upTime,addDtTm;
  for (var i=0;i<=liTags.length-1;i++) {
    // 空の配列作成
    var data = [];
    
    /////htmlタグからコンテンツを抽出/////
    liTag = liTags[i];
    // 「」と「
」に囲まれたデータを取得(改行なし) title = String(liTag.match(/.*?<\/div>/g)) .replace(//,"").replace(/<\/div>/,""); category = inCategory; // カテゴリーは記載がない!! // 「」に囲まれたデータを取得 timeTag = String(liTag.match(//g)); Logger.log(timeTag); // 「」に囲まれたデータを取得 upTime = String(timeTag.match(/\).*?<\/time>/g)) .replace(/\)/,"").replace(/<\/time>/,""); // 日時整形 if ((upDate.match(/\//g )||[]).length == 1) { // "/"の数が1の場合はmm/dd、2の場合はyyyy/mm/ddと判断 // 最新のYahoo!ニュース上の日付は年が付いていないので付加して変換 upDtTm = formatDate(new Date(new Date().getFullYear()+"/"+upDate+" "+upTime),'yyyy/mm/dd(aaa) HH:MM'); } else { upDtTm = formatDate(new Date(upDate+" "+upTime),'yyyy/mm/dd(aaa) HH:MM'); } // 現在日時取得 var now = Utilities.formatDate(new Date(),'Asia/Tokyo','yyyy/MM/dd HH:mm:ss'); addDtTm = formatDate(new Date(now),'yyyy/mm/dd(aaa) HH:MM:ss'); // 2次元配列に格納 data.push(category); // カテゴリ data.push(title); // タイトル data.push(upDtTm); // 掲載日時 data.push(url); // URL data.push(addDtTm); // 追加日時 Data.push(data); // 1行データ格納 } return Data; } //////////////////////////////////////////////////////////////////////////////// /* 日時フォーマット変換処理 */ function formatDate(date, format) { format = format.replace(/yyyy/g, date.getFullYear()); format = format.replace(/mm/g, ('0' + (date.getMonth() + 1)).slice(-2)); format = format.replace(/dd/g, ('0' + date.getDate()).slice(-2)); format = format.replace(/aaa/g, ['日','月','火','水','木','金','土'][date.getDay()]) format = format.replace(/AAA/g, ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][date.getDay()]) format = format.replace(/HH/g, ('0' + date.getHours()).slice(-2)); format = format.replace(/MM/g, ('0' + date.getMinutes()).slice(-2)); format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2)); format = format.replace(/SSS/g, ('00' + date.getMilliseconds()).slice(-3)); return format; }; //////////////////////////////////////////////////////////////////////////////// /* クリア処理 */ function yahooNewsClear() { // 開始位置 var spSheet = SpreadsheetApp.getActiveSpreadsheet(); var sheet = SpreadsheetApp.getActiveSheet(); // アクティブシート var startRow = 4; var startColumn = 1; var outColCnt = 6; /////罫線削除///// // データ部 sheet.getRange(startRow+1,1,sheet.getMaxRows(),outColCnt) .setBorder(false,false,false,false,false,false); // クリア処理(開始位置から最終行まで一旦クリアし再作成する) sheet.getRange(startRow,startColumn,sheet.getMaxRows()-startRow+1,outColCnt).clearContent(); try{ sheet.getFilter().remove(); } catch(e) { Logger.log(e); } }

最後に

Googleスプレッドシートの使い方は人それぞれ、いろんなやり方があると思いますが、一例としてご紹介させていただきました。

GASマクロはちょっとした向上心さえあれば、取っ付きやすいプログラムなのでショートカットキーなどと組み合わせてぜひ活用してみてください。

Googleスプレッドシート全ショートカットキー一覧はこちら↓↓↓

Googleスプレッドシートの使い方や機能がわかるショートカットキー全まとめ一覧【初心者こそ必見】
表計算ソフトとして、まだまだExcelのシェア率は高いですが、GoogleスプレッドシートにはExcelにはない超強力な関数があったり、Excelとは違って常に最新版を無料で使用できます。なにより、インターネットを使ったオンライン上での活用...

ちょっと工夫すれば、ちょっとした操作に1分かかっていた作業を10秒でこなすことができるようになる可能性があります。

それだけでも、積み上げれば相当の工数を削減できるはずなので、ぜひ自分に合ったやり方を模索していきましょう。


コメント