dockerを使ったselenium環境とstreamlit環境の構築方法を解説していきます
この記事を読むとわかること・・
- dockerを使ったselenium環境の構築方法
- dockerを使ったstreamlit環境の構築方法
- vncの使い方
VNC :パソコンを離れたところから操作するときに使用するソフト
dockerのインストール方法が知りたい方はこちら
dockerの基本的な使い方やdocker-compose.ymlの使い方が知りたい方はこちら
環境
解説をする前に私が使用している環境を書いておきます
- MacBook Pro : (13-inch, 2020, Four Thunderbolt 3 ports)
- プロセッサ:2 GHz クアッドコアIntel Core i5
- メモリ:16GB
- docker version:20.10.17
- python version:3.9.5
dockerでの環境構築方法についてざっくり解説
今回実装する内容をざっくり説明すると・・・
docker上でseleniumを使ってスクレイピングした内容を
streamlitでweb上に公開するって感じです
今回は実装するために2つのdockerコンテナを作成します
用意するコンテナは以下の2つ
- seleniumを使用するためのコンテナ(docker-seleniumを使用)
- streamlitを使用するためのコンテナ(自分で作成)
1つ目はdocker-seleniumのdockerイメージを使って構築します
詳細はgithubを確認してください
docker-seleniumのイメージには
- どのブラウザを使用するのか(chrome, edge, firefox)
- どのOSで使用するのか
- デバック機能を必要とするのか
など用途によって使用するイメージが変わります
私の場合は、
デバック(スクレイピングができているのか確認作業)が
したかったので『standalone-chrome-debug』の
dockerイメージを利用しました
『standalone-chrome-debug』のイメージを使用するとVNCも使用できます
VNCというのは離れたところからパソコンを
遠隔操作することができるソフトのことですが、
これを使用するとseleniumでブラウザ操作をする様子が
確認できるので、エラーが生じた際にも原因を特定することが簡単になります
VNCを使用すると以下のような感じでスクレイピングをしている様子がわかります
スクレイピングしているwebページはこちらです(netkeiba.com)
デバックが必要ない方は『standalone-chrome』イメージで十分です
2つ目のコンテナはstreamlitを使えるようにするためのコンテナです
フォルダ・ファイル構成
今回はdockerを使ってstreamlit環境と
seleniumによるスクレイピングができる環境を構築していきます
細かい説明をする前に今回使用するフォルダ構成とファイルを載せておきます
フォルダ構成
root
├── requirements.txt # インストールするパッケージを記載
└── docker-compose.yml
└── sample-streamlit
└── Dockerfile
└── streamlit-app
└── app.py
docker-compose.yml
version: '3'
services:
selenium:
container_name: selenium-chrome
image: selenium/standalone-chrome-debug:3.141.59-20210929
ports:
- 4444:4444
- 5900:5900
shm_size: "2gb"
sample-streamlit:
container_name: sample-streamlit-server
build:
context: .
dockerfile: ./sample-streamlit/Dockerfile
ports:
- 8501:8501
image: sample-streamlit:1.0
tty: true
2つのコンテナの設定をそれぞれ記載しています
4444 :seleniumのポート番号
5900:VNCのポート番号
8501:streamlitのポート番号
Dockerfile
# ベースイメージ
FROM python:3.8
# 環境変数を設定
ENV PYTHONIOENCODING utf-8
# app/ディレクトリを作成
WORKDIR /app
# パッケージをインストールする準備
RUN apt update
RUN apt install -y
RUN apt install -y python3-pip
RUN pip install --upgrade pip
# requirements.txtをコンテナ側にコピー
COPY requirements.txt .
# requirements.txtに記載されたパッケージをインストールする
RUN python3.8 -m pip install -r requirements.txt
# ローカル側のstreamlit-appディレクトリ配下にあるファイルをコンテナ側のappディレクトリにコピー
COPY ./sample-streamlit/streamlit-app/ /app
8501はstreamlitのポート番号です
docker-compose.ymlに記載しているstreamlit用のポート番号を
コンテナ側にも渡しておく必要があるため記載しています
streamlit公式にdockerを使用したstreamlitの使い方が記載されています
公式に8501のポート番号を使用すると記載されています
requirements.txt
streamlit
webdriver-manager
selenium
例ではパッケージのバージョンは指定していませんが
バージョン名の後にバージョンを指定することができます
バージョンを指定しない場合は最新のバージョンがインストールされます
app.py
# coding:utf-8
# 必要なパッケージのインストール
from selenium import webdriver
from selenium.webdriver import ChromeOptions, Chrome
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import streamlit as st
import os
import sys
import pickle
# pathの設定(スクレイピングしてきたデータを保存するディレクトリpathを取得)
FILE_PATH_FIT_DATA = '/'.join(os.path.abspath(__file__).split('/')[:-1])
sys.path.append(FILE_PATH_FIT_DATA)
def load_pickle(file_path, file_name):
"""
pickleファイルをloadする関数
"""
with open("{}/{}".format(file_path, file_name), 'rb') as f:
return pickle.load(f)
def save_pickle(file_path, file_name, var_name):
"""
pickleファイルをsaveする関数
"""
with open("{}/{}".format(file_path, file_name), 'wb') as f:
pickle.dump(var_name, f)
def main():
# "is_horse_name_view"のkeyが存在しない場合に実行する(=1度しか実行されない)
# st.sessionstateに格納する変数は再読み込みされても保持される
if "is_horse_name_view" not in st.session_state:
st.session_state["is_horse_name_view"] = None
# ボタンを押すとスクレイピングを開始する
press_button = st.button("スクレイピング開始")
# ボタンが押されたときに実行される
if press_button:
# スクレイピングした馬名を表示する信号をONにする
st.session_state["is_horse_name_view"] = True
# スクレイピングをするためのoptionsを設定(今回は特に設定はなし)
options = ChromeOptions()
# ドライバーを作成
driver = webdriver.Remote(command_executor="http://selenium:4444/wd/hub", options=options)
# サイトに接続
url = "https://race.netkeiba.com/race/result.html?race_id=202206040401&rf=race_list"
driver.get(url)
# サイトの馬名が記載されている element を取得する
horse_name_class_list = driver.find_elements(By.CLASS_NAME, "Horse_Name")
# 馬名を抽出してlistに格納する
horse_name_list = [horse_name.text for horse_name in horse_name_class_list]
# 取得した馬名を格納したlistをpickleファイル形式で保存
save_pickle(FILE_PATH_FIT_DATA, "horse_name_list.pickle", horse_name_list)
# ブラウザを閉じる
driver.close()
# st.session_stateを定義しておくことでページが更新されても
# スクレイピング開始ボタンが押されない限り馬名のradioは表示され続ける
if st.session_state["is_horse_name_view"]:
# 上で保存した馬名listを読み込む
horse_name_list = load_pickle(FILE_PATH_FIT_DATA, "horse_name_list.pickle")
# 取得した馬名をradioで表示する
st.radio('出場する馬の一覧', (horse_name_list))
if __name__ == '__main__':
main()
長くてすみません・・・
やっていることは単純です
app.pyの内容を簡単に説明すると・・・
- netkeiba.comの競馬情報サイトのある日のレースに出場する馬名を取得(selenium)
- 取得した馬名をpickleファイルに保存
- Webページ上に馬名を表示する(streamlit)
といった内容になっています
今回は実用的なファイルではなく
とりあえずseleniumでスクレイピングして
その結果をstreamlitで作成したwebページに表示する
ってことを実装しただけのファイルになります
ローカルとdockerでseleniumを使用するときの違い
ローカルとdockerでseleniumを使用するときは
以下の違いがあるので注意してください
ローカルでseleniumを使用する場合
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
docker上でseleniumを使用する場合
driver = webdriver.Remote(command_executor="http://selenium:4444/wd/hub", options=options)
ファイル構成は以上になります
コンテナ作成手順
今回はdocker-compose.ymlでdockerイメージ・dockerコンテナを
作成していきます
docker-compose.ymlの使い方がわからない方はこちらを参考にしてください
ディレクトリの移動
まず、ターミナルを起動してrootディレクトリ(docker-compose.ymlが直下にあるディレクトリ)まで移動します
$ pwd # 現在のディレクトリの確認
(実行結果)
/Users/username/root # rootディレクトリにいることを確認
dockerイメージの作成
$ docker-compose build
(実行結果)
略(いろいろインストールしてるよーって表示される)
最初にbuildするときはかなりの時間がかかるので気長に待ちましょう
私の場合は2分程度かかりました
dockerコンテナの起動
$ docker-compose up -d
(実行結果)
⠿ Container sample-streamlit-server Started
⠿ Container selenium-chrome Started
dockerイメージの確認
REPOSITORY TAG IMAGE ID CREATED SIZE
sample-streamlit 1.0 e31b70e88d56 3 minutes ago 1.43GB
selenium/standalone-chrome-debug 3.141.59-20210929 aaf43463c572 12 months ago 1.11GB
dockerコンテナの確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2319cddf970c selenium/standalone-chrome-debug:3.141.59-20210929 "/opt/bin/entry_poin…" 3 minutes ago Up 3 minutes 0.0.0.0:4444->4444/tcp, 0.0.0.0:5900->5900/tcp selenium-chrome
da6c20a2ba64 sample-streamlit:1.0 "python3" 3 minutes ago Up 3 minutes 0.0.0.0:8501->8501/tcp sample-streamlit-server
イメージ・コンテナが作成されているのがわかります
コンテナの中に入る
$ docker-compose exec sample-streamlit bash
(使い方)
docker-compose exec [イメージ名] bash
(実行結果)
root@da6c20a2ba64:/app# ←ターミナルの表記が切り替わるとコンテナの中に入ったことがわかる
コンテナ内のプログラムの実行
root@da6c20a2ba64:/app streamlit run app.py
(使い方)
streamlit run [ファイル名] → ファイル名で指定したファイルがstreamlit上で実行される
(実行結果)
You can now view your Streamlit app in your browser.
Network URL: http://172.18.0.2:8501
External URL: http://58.183.119.78:8501
safariかchromeを開いて
http://localhost:8501で検索をすると
app.pyに記載した内容がwebページ上に表示されます
『スクレイピング開始』ボタンを押すと・・・
スクレイピングが開始されて
競馬サイトのある日のレースに出馬する馬名が表示さます
これが表示されたらseleniumによるスクレイピングができたことがわかります
streamlitの終了
ターミナル上で『Control』+『c』で終了できます
コンテナを抜ける
ターミナル上で『Contorol』+『q』+『p』を同時に押すことで抜けることができます
コンテナを停止
$ docker stop selenium-chrome
(実行結果)
selenium-chrome
$ docker stop sample-streamlit-server
(実行結果)
sample-streamlit-server
コンテナを停止・削除
docker-compose.ymlを使用している場合は
下のコマンドでコンテナの停止・削除が同時にできます
# コンテナ停止・削除
$ docker-compose down
コンテナ・イメージの削除
# コンテナを削除
$ docker rm [コンテナ名] # コンテナ名を指定してコンテナを削除
(実行結果)
[コンテナ名]
# イメージを削除
# docker rmi [イメージ名] # イメージ名を指定してイメージを削除
(実行結果)
[イメージ名]
それぞれ不要なコンテナ・イメージを削除してください
これでdockerを使用したselenium環境・streamlit環境を実装することができました
VNCの使い方
最後にvncの使い方を説明しておきます
vncを使用することで、seleniumでスクレイピングしているときの状況を
確認することができます
ローカルでseleniumでスクレイピングする場合
『headless』オプションをつけていなければ
スクレイピング状況が確認できますが
今回のようにdockerを使ってstreamlit上でスクレイピングする場合は
vncを使わなければスクレイピング状況が確認できません
それではvncの起動方法を解説します
今回はMacでのVNCの使い方を解説するので
windowsの方は下のページでわかりやすく解説している方が
おられましたので、そちらを参考にしてみてください
Macの場合はVNCは標準でインストールされています
Finderを開く
まずFinderを開きます
左上の『移動』から『サーバーへ接続』を選択します
サーバー接続
接続するサーバーを選択する画面が表示されるので
『vnc://localhost:5900』と入力します
このとき『5900』はdocker-compose.ymlの
ポートフォアディングで設定する数字と
同じ値にしておく必要があります
今回の場合はdocker-compose.ymlファイルで設定した
『5900』としています
サーバーを入力後に『接続』を選択します
パスワードの入力
次にパスワードを入力する画面が表示されるので
パスワードを入力します
パスワード入力後に『サインイン』を選択します
VNCの起動
VNCが起動します
あとは、dockerコンテナを起動してapp.pyを実行し
スクレイピングを実行するとVNC画面にスクレイピングしている
様子が表示されて確認をすることができます
Macには別途VNCをインストールする必要がないため
簡単な手順でスクレイピング状況の確認をすることができます
これでdockerを使用してスクレイピングとstreamlitが
使用できるようになりましたので
皆さんも自分の作りたいwebアプリをサクッと作ってみてください
ohenziblogはプログラミングを独学で始めるための徹底ガイドを目指しています