💨

denoでスクレイピングしてslackに投げる

2021/05/05に公開

GWにdenoで何か作るという目標を立てていたので簡単ですが、slack botを作成しました。

denoのセットアップ

https://zenn.dev/azukiazusa/articles/804439f5afabe7#サーバーのセットアップ

azukiazusaさんの記事を参考にHello World!がサーバーで返せれば問題無いです。

完成品

https://github.com/CA-22-engineers/github_trending_repo

slackのチャンネルにテキストを飛ばす

slackのTokenの作成、botの招待

まずはtokenをとってきます
こちらの記事の通りにすればとってこれるはずです。
きちんとTokenが使えるかまで確認し、チャンネルにbotを招待してください。

コード

こちらのコードを参考にしました。
あんまり依存したく無いので書き換えました。
https://deno.land/x/simple_slackbot@v0.0.1/src

connect_slack.ts
export const sendMessage = async(token: string, channel: string, text: string) => {
  const response = await fetch('https://slack.com/api/chat.postMessage', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': `Bearer ${token}`,
    },
    body: JSON.stringify({
      channel,
      text,
      as_user: true,
    }),
  });
  return response;
}
index.ts
import { sendMessage } from './connect_slack.ts';
import 'https://deno.land/x/dotenv/load.ts';

const slacktoken = Deno.env.get('SLACK_TOKEN')
if (slacktoken) {
  await sendMessage(slacktoken, '#チャンネル名', 'hello world!');
}

特別なことはしていないです、とってきたslack_token

.env
SLACK_TOKEN={とってきたslack_token}

こんな感じで.envに入れてあげて

$ deno run --allow-net --allow-read --allow-env index.ts

を実行すると指定したチャンネルにhello world!と送信されるはずです。

スクレイピングでデータをとってくる

今回はgithubのトレンドにあるリポジトリをとってくることにしました。
https://github.com/trending

コード

https://scrapingant.com/blog/deno-web-scraping

参考にしました。

github.ts
import { DOMParser } from 'https://deno.land/x/deno_dom/deno-dom-wasm.ts';

const url = 'https://github.com/trending';

let url_list: string[] = [];
const url_prefix = 'https://github.com/'
const res = await fetch(url);
const html = await res.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
const ref = doc?.querySelector('#js-pjax-container>.position-relative>.Box');

export const scrapingRepo = (): string[] => {
  const repositories = ref?.querySelectorAll('div>.Box-row>h1>a');
  if (repositories) {
    for(const repositoty of repositories) {
      url_list.push(url_prefix + repositoty.textContent.replace('\n\n', '').replace(/\s+/g, '').trim())
    }
  }
  return url_list
}

もう少し良い取り方あると思いますが、こんな感じでリポジトリのurlを配列で返してきています。

blocksで送りたいのでsendMessage関数の引数を変更します。
block kitsについてはPLAIDの記事がわかりやすかったです。

connect_slack.ts
export const sendMessage = async(token: string, channel: string, blocks: any) {}
slack.ts
import { sendMessage } from './connect_slack.ts';
import { scrapingRepo } from './github.ts';
import 'https://deno.land/x/dotenv/load.ts';

const array = await scrapingRepo()
const slacktoken = Deno.env.get('SLACK_TOKEN')
if (slacktoken) {
  for (let i = 0; i < 10; i++) {
    await sendMessage(slacktoken, '#bot_test',
    [
      {
        'type': 'context',
        'elements': [
          {
            'type': 'mrkdwn',
            'text': `No.${i+1} / ${array[i]}`
          }
        ]
      },
    ]
    );
  }
}

これでもう一度実行してみてslackに送信されていれば大丈夫です。

デプロイ

せっかくなのでデプロイしたいと思います。
deno deployというのがありますが、スケジューラーを使用したいので今回はherokuにデプロイしたいと思います。

https://qiita.com/chibato/items/839e13ab09428dc1481c

この記事の通りに変更を行ってプッシュし

https://qiita.com/Taro_man/items/2eab3e3acad88c5b759e

この記事の通りにスケジューラーを設定すれば完成です。
git触ったことがあれば問題無いと思います。

最後に

deno初めて使ってみましたが、ts触ったことある人であれば問題なく書くことができると思います。

node_modulesが無いことやtsが初めから使えるのはとても体験がよく、後発の言語なので標準でdeno_lintなどもあるのでこれからも使っていきたいと思いました。

間違っているところありましたら、教えていただけるとありがたいです。

Discussion