@memo

ゆるくインプット、ゆるくアウトプット

Node, Puppeteer, Dockerでスクレイピングしてみる

こんにちは。asatoです。

スクレイピングというテクニックがあります。
Webサイトなどを解析してほしい情報を自動的に入手したりできるやつです。勉強がてらやってみたのでまとめです。

スクレイピングを悪用してはいけないです。サイトには負荷がかかります。利用規約で禁止しているサービスもあります。ご利用は計画的に。

なにする?

今回は自作プロダクト「spaces.bz」を題材に、Google検索で「spaces.bz」を検索してトップに表示されているかどうかをチェックするプログラムを組んでみようと思います。

f:id:at946:20220210152423p:plain

トップに出てきたら嬉しいですが、毎日手でやるのは面倒ですよね♪

アーキテクチャ

今回はNodeを使います。理由は僕が使い慣れているからです。
あと、Dockerも使います。理由は僕がローカルに色々入れたくないからです。
あと、画面操作やデータの取得はpuppeteerを使います。理由は前使ったことがあるからです。

あんまり理由がいい加減でごめんなさい。そんなに特殊な選択はしてないのでね。

一応バージョン情報。

  • docker: 20.10.8
  • node: 17.4.0
  • puppeteer: 13.3.0

ローカルに入っているのはdockerだけです。あとはこれから入れてきますよー。

おおまかな手順

  1. puppeteerを動かすnodeコンテナをつくる
  2. スクレイピングのコードを書く

puppeteerを動かすnodeコンテナをつくる

Dockerfiledocker-compose.ymlを作成します。

# Dockerfile
FROM node

WORKDIR /app
VOLUME /app/node_modules

RUN apt-get update \
    && apt-get install -y wget gnupg \
    && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
    && apt-get update \
    && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
      --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

RUN yarn add puppeteer

CMD ["node", "index.js"]
# docker-compose.yml
version: "3"

services:
  app:
    build: .
    volumes:
      - .:/app

Dockerfileの中でpuppeteerいれちゃいます。

DockerfileRUN apt-get ~のところでchromeをインストールしてますね。 puppeteerのトラブルシューティングにかかれていますが、これをしないとpuppeteerがdockerコンテナの中でうまく動けません。

これでビルドしておけば、とりあえず環境の準備は完成です(≧∇≦)b

$ docker compose build

スクレイピングのコードを書く

環境が整ったのでスクレイピングのコードを書いてみます。

Dockerfileで起動時にnode index.jsのコマンドを実行するようにしているので、index.jsにコードを書いていきます。

# index.js
const puppeteer = require('puppeteer')

!(async() => {
  const browser = await puppeteer.launch({
    args: [
      '--no-sandbox',
      '--disable-dev-shm-usage'
    ]
  })
  const page = await browser.newPage()

  // googleのトップページにアクセス
  await page.goto('https://google.com/')
  // 検索フォームに'spaces.bz'と入力
  await page.type('input.gLFyf.gsfi', 'twitter spaces')
  // Enterキーを押下
  await page.keyboard.press('Enter')
  
  // 検索結果が表示されるまで待つ
  await page.waitForSelector('cite.iUh30.tjvcx')
  // 検索結果トップのURLを取得
  const topUrl = await page.$eval('cite.iUh30.tjvcx', el => el.innerText)

  // 検索結果トップが自分のサイトならOKメッセージ、違えばそのサイトのURLをコンソールに出力
  if (topUrl === 'https://spaces.bz') {
    console.log('spaces.bzは検索トップに表示されています🎉')
  } else {
    console.log(`検索トップは「${topUrl}」です...`)
  }
  
  browser.close()
})()

シンプルですね!コメントアウトも入れたので、それぞれの処理のイメージを掴んでもらえると嬉しいです。

具体的なpuppeteerの使い方は公式を御覧ください!色々できます。

さて、これを実行してみると...

$ docker compose up
spaces.bzは検索トップに表示されています🎉

いえーい(≧∇≦)/

試しに検索キーワードを「twitter spaces」にしてみると...

$ docker compose up
検索トップは「https://help.twitter.com › ヘルプセンター › ツイート」です...

ぬーん(´・ω・`)

おわり

はい!Nodeでスクレイピングできました!

puppeteerも入っているのでUI操作も可ですね。

優しいスクレイピングライフを!