0
0

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.

Webサイトのスクリーンショット取得、CLIのやつと、WEB APIで取得できるコンテナとを作ってみた

Last updated at Posted at 2019-09-24

概要

このエントリでは、Webサイトのスクリーンショットを以下2つの方法で取得するための仕組みを作ってみたので、ご紹介します。

  • CLI
  • WEB API

ざくっと動かす方法と、作りの上で気づいたところについて記載します。

対象

  • GoogleChrome/Pupeteer (=ヘッドレスで動作できてスクリプトから操作できる素敵なブラウザを操るためのプロジェクト)は知っているし大体使い方イメージできるので、あとは動いている何かを使いたい方
  • チャットサービスなどでURLを貼り付けると、そのすぐ下あたりにWebのサムネイルとちょっとした説明なんかが出てくるけれども、あれ作るとしたらどうやるんだっけ、と思ったことがある方

前提

  • CLIとして使いたいときは、新し目の、macOS(MojaveとかHigh Sierra)/Linux(で、新し目のNodeとChromiumを動かすのに不自由しないもの)/Windows(10 Proでは試しました。7でもいけると思いますが試してません)が使えること
  • コンテナとして使いたいときは、Dockerコンテナを動かす環境があること

以下を前提としています

  • Node 10.x系の新しいもの
  • npm 5.2以降 (npxを使わないのであれば古くても問題ないです)

関連サイト

TL;DR

CLI

インストール

git clone https://github.com/hrkt/take-ss-pupeteer
nom install

実行

npx ./src/take-ss -o example.com.png http://www.example.com

数秒後、実行したカレントディレクトリ以下に、example.com.pngというPNGファイルができているはずです。

v0.1.1でのオプションは以下の通り。ブラウザの表示は、サムネイル

Usage: take-ss [options]

Options:
  -v, --version                     output the version number
  -vw, --viewport-width <int>       Viewport(width) of the screenshot (default: 1200)
  -vh, --viewport-height <int>      Viewport(height) of the screenshot (default: 800)
  -o, --output-filename <filename>  filename of the screenshot (default: "out.png")
  -j, --output-as-json              output result as JSON, base64 encoded image and meta data (default: false)
  -h, --help                        output usage information

WEB API

起動

docker run -p 8080:8080 hrkt/take-ss-pupeteer:latest

curlでアクセス

curl "http://localhost:8080/api/takess?http://www.example.com"

出力

数秒後、以下のようなJSONが返却されます。

{"base64Img": "xxxxxxxxxx(base64にエンコードされた文字列)===",
"description":"(METAタグ内のdescription)",
"title":"TITLEタグ内のタイトル"
}

base64Imgは、HTML内で下記のように用いるイメージです。

<img src="data:image/png;base64,(ここに貼り付け)">

補足

サーバで動くときには、レスポンスとしてJSONイメージを返すだけとし、サーバ条に画像ファイルを作る機能は動かないようにしています。(Dockerfileから環境変数を渡して、スクリプト内でファイル保存モードを無効化)

(なんちゃって記事ではありますが、万が一そのまま使ってしまう場合を恐れ、一応、ファイルで膨れ上がったり、イヂワルなファイル名で目的外のファイルを上書きしたりはしにくいようにしてます)

各論: CLI

前提

  • ヘッドレスでWebをキャプチャする方法はいろいろありますが、2019年の時点で開発元が手厚くて筋が良さそうなPupeteerを使っています。
  • Pupeteerは、Nodeで動かす前提だったので、Nodeを使っています。

使ったもの

  • CLIとして動かすため、コマンドラインのオプション処理が必要ですが、Commander.jsを使いました。必要なだけの機能が見通しよく提供されていることと、検索してみてパッとみた感じ、使われてそうなものだったので。

作り

  • ソースを見ていただければわかりますが、1つのJavaScriptスクリプトで作ってあり、そんなたいしたことはしていません。
  • PupeteerのTutorialと比べると、以下のいくつかのところでは工夫しました。

brwoserオブジェクトは、try-catch-finallyでcloseするようにしてます。
これは、実際使ってみると様々な理由でブラウザがクラッシュしますが、その時もそこそこ礼儀正しく終了できるようにするためです。

} finally {
     await browser.close()
}

Pupeteerをlaunchするときに、Chromiumのオプションをいくつか渡しますが、エントリ執筆時点では、下記のようなものを渡しています。最後の「'--disable-dev-shm-usage'」は、とあるバージョンまではコンテナ内で動かしていると共有メモリが足りなくて落ちちゃっているケースもあったんだけれども、それはファイルとして作ることにして回避することにする、というオプションです。(コンテナでなく普通に手元OSで動かす分には出会わないと思います)

args: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage']

各論: REST風コンテナ

どうせだったら、コマンドラインで動かすだけでなく API的に動いてもいいよね、という発想の元、筆者の別エントリの「コマンドをサクッとREST風にHTTPで呼び出すサンプルをpandocに使ってコンテナを作ってみた」を使いました。

基本的な話は上記エントリに書いた通りなのですが、コンテナ内でPupeteerを動かすため、以下を実施しています。

とりあえずDockerのベースを使う

FROM hrkt/command-as-a-service:latest

基本的には、このコンテナをFROMにするだけで、任意のパスのコマンドをREST API風に呼び出せます。

AlpineでChromiumを動かすため、いろいろ入れる。

これは、Pupeteerサイトにある「Troubleshooting」で開設されているものをそのまま使ってます。
(pupeteerパッケージが自動で落としてくれたり、pupeteer-coreパッケージと自分でapk add chromiumしたものでは、2019年9月時点ではうまくいきませんでした。)


RUN apk add --no-cache \
      udev \
      chromium \
      nss \
      freetype \
      freetype-dev \
      harfbuzz \
      ca-certificates \
      ttf-freefont \
      nodejs \
      yarn \
      nodejs-npm

上記だけだと、日本語フォントが豆腐になってしまうので、noto(=no-豆腐)フォントを入れる。

これは、「Dockerを使ってHeadless Chromeを動かしてみる」の内容を使わせていただいてます。



RUN mkdir /noto
ADD https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip /noto

WORKDIR /noto

RUN unzip NotoSansCJKjp-hinted.zip && \
    mkdir -p /usr/share/fonts/noto && \
    cp *.otf /usr/share/fonts/noto && \
    chmod 644 -R /usr/share/fonts/noto/ && \
    fc-cache -fv

RUN rm -rf /noto

まとめ

Webサイトのスクリーンショットを撮るための、CLIのツールと、それをなんちゃってWEB APIにするための方法についてご紹介しました。

所感

Pupeteer、サイトのTutorialの内容だけ見るとお手軽感満載で最高ですが、ちょっと動かしてみて、コンテナに入れてみて、手近のサイトいくつかを動かしてみるだけでも、いくつか工夫することがありました。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?