LoginSignup
1
1

More than 3 years have passed since last update.

Qiita Organizationランキングをスクレイピングで取得してSlackに通知してみた。

Posted at

なんで作ったの?

この記事を見て、自分もQiita Organizationランキングをチェックできるものが欲しい・・
と思いたったので、自前のSlackBotにスクレイピングを利用して投稿するようにしてみた。

何を使用したの?

・Google App Script
 ※SlackへMSGを送る部分は、右記ライブラリ使用→SlackApp
・Slack

ソースコードは?

以下のソースコードより、Organizationランキング(週間、月間)の取得を行なっております。
GoogleAppScriptの時刻起動トリガーを指定してすれば、定刻起動も可能です。
※トリガーの設定方法は本記事では省略してます。(ぽちぽち簡単に設定できます。)

ソースコード
//メイン
function main(){
  var msg = qiitaOrgGet()
  sendSlack(msg)
}

//qiita organizationのスクレイピングと文字列の整形を行う。
function qiitaOrgGet(){

  //スクレイピングURL
  var url = ['https://qiita.com/organizations?sort=default' //週間
            ,'https://qiita.com/organizations?sort=activity_stats_total'] //月間

  //organizationURL連結用
  var orgurl = 'https://qiita.com/organizations/'

  //organization名取得用パース文字
  var from1 = '<strong class="ol-Item_name" itemprop="name"><a href='
  var to1 = '</a></strong><p class="ol-Item_description" itemprop="description">'

  //投稿数取得用パース文字
  var from2 = '<div class="ol-Item_postNum mr-1of2">'
  var to2 = '</div>'

  //orgnizaton情報格納用
  var orglist = [[''],['']]

  //emoji変換用
  var emoji = [':first_place_medal:',':second_place_medal:',':third_place_medal:',':four:',':five:',':six:',':seven:',':eight:',':nine:',':keycap_ten:']

  //slackmsg用
  var msg = '*Qiita Organization投稿ランキングチェッカー*' + String.fromCharCode(10) + '順位、投稿数、Organization名' + String.fromCharCode(10)



  //スクレイピング&データ加工
  for(var i in url){
    var html = UrlFetchApp.fetch(url[i]).getContentText()
    var name = Parser(html,from1,to1)
    var postCnt = Parser(html,from2,to2)

    //事後処理
    for(var j in name){
      orglist[i].push([i
                   ,name[j].slice(name[j].indexOf('>')+1)
                   ,orgurl + name[j].slice(name[j].indexOf('s/')+2
                   ,name[j].indexOf('>')-1)
                   ,postCnt[j]])
    }
  }

  //Slack用にMSG整形
  for(var i in orglist){
    for(var j=1;j<=10;j++){

      if(i == 0 && j == 1){
        msg = msg + '  _*週間ランキング*_' + String.fromCharCode(10)
      }else if(i == 1 && j == 1){
        msg = msg + String.fromCharCode(10) +'  *月間ランキング*' + String.fromCharCode(10)
      }
        msg = msg + '    ' + emoji[j-1] + ' ` ' + orglist[i][j][3] + '` ' + '<' + orglist[i][j][2] + '|' + orglist[i][j][1] + '>' + String.fromCharCode(10)
    }
  }
  Logger.log(msg)
  return msg
}

//直前(from)、直後(to)の文字列で囲われたデータを取得する。
function Parser(data,from,to){

  /*
  data ・・ パース対象の文字列が含まれるテキストデータ
  from ・・ パース対象の文字列の直前のテキストを指定
  to   ・・ パース対象の文字列の直後のテキストを指定

  from,toで囲われた文字を全て検索して配列に格納します。
  */

  //初期値
  var tmp = []
  var tmpindex
  var fromindex = data.indexOf(from)
  var toindex = data.indexOf(to)

  if(fromindex != -1){
    for(var i=0;i<=data.length;i++){

      //後続あるなし判定
      if (toindex == -1 || fromindex == -1) {
          break;
      }

      //from < to なら代入
      if(fromindex + from.length < toindex){
        tmp.push(data.slice(fromindex + from.length,toindex))
      }


      tmpindex = toindex

      //後続indexサーチ
      fromindex = data.indexOf(from,tmpindex)
      toindex = data.indexOf(to,tmpindex + 1)
    }
  }
  //Logger.log(tmp)
  return tmp
}


//SlackへMSG送信(lib_SlackApp使用)
function sendSlack(ToSlackMsg){
  var slackApp = SlackApp.create('TOKENKEY')//任意のTOKENKEY
  var icon = ':ICON名称:'//任意のアイコン名
  var options = {
  icon_emoji: icon,
  username: "BOT名称"//任意のBot名
  }
  slackApp.postMessage('#チャンネル', ToSlackMsg, options);//任意のチャンネル名
}

実際の出力結果は?

以下の形式で、1位〜10位までの週間、月間それぞれのランキングの
順位、Qiita投稿数、Organization名がBotに通知されます。
また、各Organization名には各詳細ページへのリンクを付与している形式で出力されます。

※今回、Slackを投稿する部分で、attachmentsを使用していないので
元ネタに存在する、横棒は省略してます。
スクリーンショット 2020-03-25 14.52.20.png

感想は?

GAS+Slackは無料でBotを作って遊ぶには最高の環境ですね。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1