LoginSignup
0
3

More than 3 years have passed since last update.

Seleniumで好きな画像を生成できるプログラムを作る

Last updated at Posted at 2020-09-15

はじめに

最近、個人的な趣味で地震の震度分布図を作画してツイートするプログラムを作成したのですが、そこで使った画像生成が他のものでも使えるのではないかということで備忘録として書こうかと思います。

原理

PythonのSeleniumと呼ばれるフレームワークは、Webアプリなどのテストをするものなんですが動的サイトのスクレイピングなどにも用いられています。
レンダリングは、Google ChromeのヘッドレスプラウザというCUIベースで動くChromeでレンダリングしています。

その、Seleniumにはスクリーンショットの機能があるためローカルサーバーを立てそこに必要な情報をGETしてあげることで好きな画像をHTML/CSSで作成することが可能です。

必要なもの

  • Python

  • Selenium

一応、SeleniumはRubyやJSにもあるみたいです。
Webページをキャプチャするためのフレームワーク。
pipでのインストール方法は以下

pip install selenium
  • Docker

WindowsやMacなどにすでにChromeが入っている場合はなくてもいいのですが、VPS上で実行する際などではChromeをDocker内に入れることで実行します。

  • ローカルサーバー

Node.js、DenoなどでもOK。今回はPythonのフレームワークのFlsakを使用します。

作る

今回作ったソースコードは、ここにおいてあります。

Webサーバーを作る

今回はFlaskで作成し、Docker composeでコンテナとしてまとめます。そのため、Pythonのモジュールはpipenvで管理しようかと思います。

以下を入力してPipenvをインストールし、Flaskをインストールします。

pip install pipenv
pipenv --python 3.8
pipenv install flask

更に、たりないファイルなどを追加して以下のようにします。
ディレクトリ構成は以下です。

server
   ├── Dockerfile
   ├── Pipfile
   ├── Pipfile.lock
   ├── run.py
   ├── static
   │  └── css
   │     └── style.css
   └── templates
      └── index.html

run.pyindex.htmlstyle.cssは自分の好きなように作ってください。
今回は、URLパラメータでGETした文字列を画面に表示するだけにします。

Dockerfileは以下のように記述します。出力ポートは5000になっていますが任意で大丈夫だと思います。

Dockerfile
FROM python:3.8

COPY run.py /run.py
COPY templates /templates
COPY static /static
COPY Pipfile /Pipfile
COPY Pipfile.lock /Pipfile.lock

RUN pip install pipenv
RUN pipenv install --system --deploy

EXPOSE 5000

pipenv shell && python run.pyを試してみて、ブラウザなどで正常に表示できたらOKです。

キャプチャ部分を作る

先程つくったserverディレクトリの上部に生成用のプログラムファイルなどを作成します。
ディレクトリはこのようにします。

.
├── docker-compose.yml
├── Dockerfile
├── images
├── main.py
├── Pipfile
├── Pipfile.lock
├── README.md
└── server

pipenvでインストールするモジュールはSeleniumです。

pipenv install selenium

画像生成のDockerfileは以下のようにします。こちらは、Google Chromeも一緒にインストールする必要があります。

Dockerfile
FROM python:3.8

COPY main.py /main.py
COPY Pipfile /Pipfile
COPY Pipfile.lock /Pipfile.lock

RUN apt-get update && apt-get install -y unzip

#install google-chrome, vim
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add && \
    echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list && \
    apt-get update && \
    apt-get install -y google-chrome-stable
RUN apt-get install -y vim

#install ChromeDriver
ADD https://chromedriver.storage.googleapis.com/84.0.4147.30/chromedriver_linux64.zip /opt/chrome/
RUN cd /opt/chrome/ && \
    unzip chromedriver_linux64.zip

ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/chrome

RUN pip install pipenv
RUN pipenv install --system --deploy

ADD https://chromedriver.storage.googleapis.com/84.0.4147.30/chromedriver_linux64.zip /opt/chrome/は現在のChromeのバージョンのリンクが必要です

から、現在のバージョンのリンクを貼り付けます。

さらに、サーバーのコンテナとこのコンテナをつなげるためdocker-compose.ymlを作成します。

docker-compose.yml
version:  '3'
services:
    server:
        container_name: server
        build:
            context: server
            dockerfile: Dockerfile
        ports:
            - '5000:5000'
        tty: true
        # restart: always
        command: python3 run.py
    main:
        container_name: main
        build: .
        tty: true
        # restart: always
        links:
            - server
        volumes:
            - ./images/:/images/
        command: python3 main.py

ここで重要なのは生成した画像をDocker外で使用する場合はその保存するディレクトリをvolumesに指定してあげる必要があります。

main.pyはSeleniumのキャプチャ方法として調べるとたくさん出てきますが、今回はこのように作成します。

main.py
import os

from selenium import webdriver


def main():
    image_save_path = os.path.join('images', 'image.png')

    text = 'Hello'

    captcha(image_save_path, text)


def captcha(image_save_path: str, text: str) -> None:
    url = f'http://server:5000/?text={text}'

    options = webdriver.ChromeOptions()

    options.add_argument('--headless')
    options.add_argument('--no-sandbox')

    driver = webdriver.Chrome(options=options)

    driver.set_window_size(1920, 1080)
    driver.execute_script("document.body.style.zoom='100%'")
    driver.get(url)
    driver.implicitly_wait(3)
    driver.save_screenshot(image_save_path)
    driver.quit()


if __name__ == "__main__":
    main()

動かしてみる

docker-compose up

を入力してみて実際にimagesディレクトリに画像が生成されていたら成功です。

ソースコード: https://github.com/yuto51942/image-generate

最後に

私が最近趣味で作ったEarthquake-alertにも同じようにして画像生成しているのでぜひ見てみてください。なんならStarも欲しいです。

他の方法でも画像を生成できるかもしれませんが、自分の中ではこの方法が一番自由に色々な画像を生成することができるのではと思います。ぜひ試してみてください。

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