14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

仕事中でも株価を見るために株価チャートを投稿するSlack botを作ってみた

Last updated at Posted at 2017-10-18

株価チャートって見てて面白いですよね!(株やってないですが)

googleで 企業名 株価って検索すると
その企業の株価チャートを表示してくれるのに気づいたので、
puppeteerを使ってその部分のスクリーンショットを取得して
Slackに投稿してくれるBotを作ってみました

つくったもの

Github: https://github.com/tamanugi/slack_bot_stock_chart

スクリーンショット 2017-10-18 12.39.04.png スクリーンショット 2017-10-18 12.39.16.png

キャプチャのようにbotにメンションつけてメッセージ送ると
{メッセージ} 株価 でGoogle検索を実行して
出てきた株価の部分のスクリーンショットをslackにアップロードしてくれます。

また Google の株価チャートは期間指定ができるのですが、そちらも選択できるようにしています

つかったもの

  • botkit
  • puppeteer

中身とか

bot.js
const StockCapture = require('./lib/stock_capture.js') 

if (!process.env.token) {
  console.log('Error: Specify token in environment');
  process.exit(1);
}

var Botkit = require('botkit');
let fs = require('fs')

var controller = Botkit.slackbot({
  debug: false
});

var bot = controller.spawn({
  token: process.env.token
}).startRTM();

controller.hears(['(.*)'],['direct_message', 'direct_mention', 'mention'], function(bot, message) {
  let arg = message.match[1]
  let company, period;

  let match = arg.match(/(.*)(1日|5日|1か月|3か月|1年|5年|最長)$/)
  if(match) {
    company = match[1]
    period = match[2]
  }else{
    company = arg
  }

  StockCapture.capture(company, period, () => {
    bot.api.files.upload({
      file: fs.createReadStream('stock-chart.png'),
      filename: 'stock-chart.png',
      channels: message.channel
    },(err,res) => {
        if (err) console.log(err)
    })
  })

});

botkitを使ってファイルをアップロードする方法については
以前書いた自分の記事を参考にしました

参考: Botkitで画像ファイルをslackにアップロードする

lib/stock_capture.js
const puppeteer = require('puppeteer');

const periods = {
  '1日': '1d',
  '5日': '5d',
  '1か月': '1M',
  '3か月': '3M',
  '1年': '1Y',
  '5年': '5Y',
  '最長': '40Y',
}

const capture = async (company, period ,cb) => {
  const browser = await puppeteer.launch({headless: true});
  const page = await browser.newPage();

  const targetElementSelector = '#fac-ut'

  await page.goto('https://google.co.jp')
  await page.type('#lst-ib', `${company} 株価`)
  await page.click('#tsf > div.tsf-p > div.jsb > center > input[type="submit"]:nth-child(1)')
  await page.waitFor(targetElementSelector)

  if(period){
    const dataPeriod = periods[period]
    await page.click(`#fac-sbtns > ol > li[data-period='${dataPeriod}']`)
    await page.waitFor(1000)
  }

  const clip = await page.evaluate(s => {
    const el = document.querySelector(s)

    // エレメントの高さと位置を取得
    let { width, height, top: y, left: x } = el.getBoundingClientRect()

    // padding分調整
    width += 32
    height += 36
    x -= 16
    y += 4


    return { width, height, x , y}
  }, targetElementSelector)

  // スクリーンショットに位置と大きさを指定してclipする
  await page.screenshot({ clip, path: 'stock-chart.png' })

  cb()

  browser.close();
};

module.exports.capture = capture

株価を表示している部分は div#fac-ut になりますので
位置と大きさを取得してスクリーンショット取る際に引数に指定しています。

取得できる位置と大きさと実際に欲しい部分がずれていたのでそこは調整しています。(padding分だけずれた?)

puppeteerを使ってあるエレメントのスクリーンショットを取得する方法は
過去にまとめたので、そちらもご参考いただけると幸いです

Puppeteerを使って指定したDOMのみのスクリーンショットを取得する

まとめとか

puppeteerもbotkitもほんとにお手軽に使えるので
ちょっとしたChat Bot作る際に役立ちますね~~
もっと色々と作ってみようと思います

よーしこれで仕事中に株価ウォッチできるぞー

14
18
2

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
14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?