Home / Web / スクレイピング / Docker+Scrapy+Splash+Selenium+PostgreSQLでスクレイピング用コンテナを構築

機械学習の学習データをスクレイピングをするためのコンテナを構築したのでその手順を書きました。

GitHub – quark00/Scraping-Docker

Contribute to quark00/Scraping-Docker development by creating an account on GitHub.

JavaScriptのページをスクレイピングする場合は、SplashかSeleniumを使用して下さい。

環境構築

  1. ディレクトリを作成
  2. データベースの認証情報を設定
  3. Docker Composeを構築
  4. カスタムイメージを作成
  5. コンテナを起動
  6. データベースを確認
  7. Splashを設定

環境破棄・操作

ディレクトリを作成

Docker Composeを配置するディレクトリを作成します。

作成したディレクトリ名がDocker Composeのプロジェクト名となり、ネットワーク名とボリューム名の先頭文字として設定されます。

% mkdir my_scraping
% cd my_scraping

データベースの認証情報を設定

PostgreSQLコンテナのデータベースの認証情報の環境変数を.envに設定します。

環境変数を作成

docker-compose.ymlを作成するディレクトリと同じ場所に作成します。

% vi .env

.env

POSTGRES_DB=postgresdb
POSTGRES_USER=postgresuser
POSTGRES_PASSWORD=postgrespass

複数の.envを作成した場合、個々の.envに同名の環境変数名を設定すると競合してしまうので、必ず一意の環境変数名を付けるようにしてください。

docker-compose.ymlが配置されているディレクトリ内に.envを作成すると、Docker Compose実行時に自動的に.envの内容が読み込まれます。

Docker Composeを構築

Docker Composeの設定ファイルであるdocker-compose.ymlを作成し、同時起動させる下記コンテナの起動設定を行います。

ベースイメージ

% vi docker-compose.yml

docker-compose.yml

version: '3.9'

services:
  postgresql:
    image: postgres:14.1-bullseye
    container_name: my_postgresql
    networks:
      - net
    ports:
      - 5432:5432
    volumes:
      - db_volume:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

  splash:
    depends_on:
      - postgresql
    image: scrapinghub/splash:3.5
    container_name: my_splash
    networks:
      - net
    ports:
      - 8050:8050

  scrapy:
    depends_on:
      - splash
    build: 
      context: .
      dockerfile: Dockerfile
    image: scrapy:2.6.1
    container_name: my_scrapy
    networks:
      - net
    volumes:
      - $PWD/app:/usr/src/app
    tty: true

networks:
  net:

volumes:
  db_volume:

ComposeFileの設定を確認

% docker-compose config
networks:
  net: {}
services:
  postgresql:
    container_name: my_postgresql
    environment:
      POSTGRES_DB: postgresdb
      POSTGRES_PASSWORD: postgrespass
      POSTGRES_USER: postgresuser
    image: postgres:14.1-bullseye
    networks:
      net: null
    ports:
    - published: 5432
      target: 5432
    volumes:
    - db_volume:/var/lib/postgresql/data:rw
  scrapy:
    build:
      context: /Users/my_scraping
      dockerfile: Dockerfile
    container_name: my_scrapy
    depends_on:
      splash:
        condition: service_started
    image: scrapy:2.6.1
    networks:
      net: null
    tty: true
    volumes:
    - /Users/my_scraping/app:/usr/src/app:rw
  splash:
    container_name: my_splash
    depends_on:
      postgresql:
        condition: service_started
    image: scrapinghub/splash:3.5
    networks:
      net: null
    ports:
    - published: 8050
      target: 8050
version: '3.9'
volumes:
  db_volume: {}

カスタムイメージを作成

ベースイメージのPythonイメージに、Dockerfileに記載した設定でカスタマイズしたScrapyイメージを作成します。

DockerfileにはSeleniumで使用するGoogle ChromeとChromeドライバーのインストール、requirements.txtで指定したパッケージをpipでインストールする処理を記述しています。

Dockerfileを作成

docker-compose.ymlと同じディレクトリ内に作成します。

% vi Dockerfile

Dockerfile

FROM python:3.8.12-bullseye

WORKDIR /usr/src/app

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

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

ADD https://chromedriver.storage.googleapis.com/99.0.4844.51/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

COPY requirements.txt ./
RUN pip install --upgrade pip && pip install --no-cache-dir -r ./requirements.txt

カスタムイメージにインストールするパッケージを指定

イメージ作成時にインストールするパッケージをrequirements.txtに指定します。指定するパッケージは下記になります。

  • Scrapy:スクレイピング・クローリングをするフレームワーク
  • Scrapy-Splash:ScrapyでJavaScriptをスクレイピングするライブラリ(Splashサーバーに接続して使う)
  • Selenium:JavaScriptをスクレイピングするライブラリ
  • python-dotenv:Pythonで環境変数を扱うライブラリ
  • psycopg2:PythonでPostgreSQLを扱うライブラリ

docker-compose.ymlと同じディレクトリ内に作成します。

% vi requirements.txt

requirements.txt

scrapy==2.6.1
scrapy-splash==0.8.0
selenium==4.1.3
python-dotenv==0.19.2
psycopg2==2.9.3 

コンテナを起動

イメージをビルドしてすべてのコンテナを起動します。

docker-compose.ymlが置かれているディレクトリ上で実行します。

% docker-compose up -d --build
Creating network "my_scraping_net" with the default driver
Creating volume "my_scraping_db_volume" with default driver
Building scrapy
[+] Building 28.8s (14/14) FINISHED
 => [internal] load build definition from Dockerfile                       0.0s
 => => transferring dockerfile: 831B                                       0.0s
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/python:3.8.12-bullseye  2.1s
 => [1/8] FROM docker.io/library/python:3.8.12-bullseye@sha256:53cb515206  0.0s
 => [internal] load build context                                          0.0s
 => => transferring context: 271B                                          0.0s
 => https://chromedriver.storage.googleapis.com/99.0.4844.51/chromedriver  0.1s
 => CACHED [2/8] WORKDIR /usr/src/app                                      0.0s
 => CACHED [3/8] RUN apt-get update && apt-get install -y unzip            0.0s
 => CACHED [4/8] RUN wget -q -O - https://dl-ssl.google.com/linux/linux_s  0.0s
 => CACHED [5/8] ADD https://chromedriver.storage.googleapis.com/99.0.484  0.0s
 => CACHED [6/8] RUN cd /opt/chrome/ &&     unzip chromedriver_linux64.zi  0.0s
 => [7/8] COPY requirements.txt ./                                         0.0s
 => [8/8] RUN pip install --upgrade pip && pip install --no-cache-dir -r  25.3s
 => exporting to image                                                     1.1s
 => => exporting layers                                                    1.1s
 => => writing image sha256:5f87d975817d1590cb720221ea293d24c0d560dd2d4b2  0.0s
 => => naming to docker.io/library/scrapy:2.6.1                            0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Creating my_postgresql ... done
Creating my_splash     ... done
Creating my_scrapy     ... done

稼働中のコンテナを確認

% docker-compose ps
    Name                   Command               State           Ports
-------------------------------------------------------------------------------
my_postgresql   docker-entrypoint.sh postgres    Up      0.0.0.0:5432->5432/tcp
my_scrapy       python3                          Up
my_splash       python3 /app/bin/splash -- ...   Up      0.0.0.0:8050->8050/tcp

イメージを確認

% docker-compose images
  Container         Repository            Tag          Image Id       Size
----------------------------------------------------------------------------
my_postgresql   postgres             14.1-bullseye   da2cb49d7a8d   374 MB
my_scrapy       scrapy               2.6.1           c4bb14565272   1.623 GB
my_splash       scrapinghub/splash   3.5             93cac3cba2d3   1.888 GB

ネットワークを確認

% docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
4a133cbc34e8   bridge            bridge    local
69b09e935fcd   host              host      local
b9591855ac06   my_scraping_net   bridge    local
f70f9b9aa9f8   none              null      local

ボリュームを確認

% docker volume ls
DRIVER    VOLUME NAME
local     my_scraping_db_volume

コンテナに入る

docker-compose.ymlに設定されている サービス名を指定してコンテナに入ります。

% docker-compose exec scrapy bash

Chromeを確認

# google-chrome -version
Google Chrome 99.0.4844.74

ChromeDriverを確認

# chromedriver --version
ChromeDriver 99.0.4844.51 (d537ec02474b5afe23684e7963d538896c63ac77-refs/branch-heads/4844@{#875})

ChromeとChromeDriverは同じバージョンで組み合わせないと動作しないので、それぞれに適切なバージョンをインストールしてください。

  • 例えばChromeのバージョンが 99.xxxなら 、ChromeDriverのバージョンも 99.xxxに合わせてください。

データベースを確認

ユーザー名とデータベース名を別の名前に変更した場合はユーザー名と同名のデータベースは作成されず、ユーザー名だけではログインできないので、ユーザー名とデータベース名を一緒に指定してログインしてください。

% docker-compose exec postgresql psql -U postgresuser postgresdb
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.
​
# l
                                       List of databases
    Name    |    Owner     | Encoding |  Collate   |   Ctype    |       Access p
rivileges
------------+--------------+----------+------------+------------+---------------
----------------
 postgres   | postgresuser | UTF8     | en_US.utf8 | en_US.utf8 |
 postgresdb | postgresuser | UTF8     | en_US.utf8 | en_US.utf8 |
 template0  | postgresuser | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgresuse
r              +
            |              |          |            |            | postgresuser=C
Tc/postgresuser
 template1  | postgresuser | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgresuse
r              +
            |              |          |            |            | postgresuser=C
Tc/postgresuser
(4 rows)

Splashを設定

Scrapyプロジェクトを作成

appディレクトリが無い場合はDocker Compose起動時に自動生成されます。

# cd app
# scrapy startproject my_project
# scrapy genspider my_project example.com
Created spider 'my_project' using template 'basic'
# cd my_project/my_project
# scrapy genspider my_spider example.com
Created spider 'my_spider' using template 'basic' in module:
  my_project.spiders.my_spider

settings.pyにSplashの設定を追加

SPIDER_MIDDLEWARES = {
   'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
​
DOWNLOADER_MIDDLEWARES = {
   'scrapy_splash.SplashCookiesMiddleware': 723,
   'scrapy_splash.SplashMiddleware': 725,
   'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
​
SPLASH_URL = 'http://splash:8050'
​
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

Docker ComposeではDockerネットワークが作成され、サービス名をホスト名としてコンテナ間でアクセスすることができるため、http://splash:8050でScrapyコンテナからSplashコンテナにアクセスすることができます。

すべてのコンテナを破棄

すべてのコンテナが破棄され、ネットワークも破棄されますが、イメージとボリュームは残ります。

% docker-compose down
Stopping my_scrapy     ... done
Stopping my_splash     ... done
Stopping my_postgresql ... done
Removing my_scrapy     ... done

すべてのイメージを削除

イメージを確認

% docker-compose images
  Container         Repository            Tag          Image Id       Size
----------------------------------------------------------------------------
my_postgresql   postgres             14.1-bullseye   da2cb49d7a8d   374 MB
my_scrapy       scrapy               2.6.1           c4bb14565272   1.623 GB
my_splash       scrapinghub/splash   3.5             93cac3cba2d3   1.888 GB

イメージを削除

% docker rmi c4bb14565272 da2cb49d7a8d 93cac3cba2d3
Untagged: scrapy:2.6.1
Deleted: sha256:c4bb14565272cce160cce9231b87c719227460160fbe80758d8d58687f3c0246
Untagged: postgres:14.1-bullseye
Untagged: postgres@sha256:3162a6ead070474b27289f09eac4c865e75f93847a2d7098f718ee5a721637c4
Deleted: sha256:da2cb49d7a8d1416cfc2ec6fb47b60112b3a2f276bcf7439ef18e7c505b83fc6
Deleted: sha256:3795b5d9b02f6ed378c29aac7f63cc955e48116f30bdc12bea9f02d47ac17b71
Deleted: sha256:d9cf9b69fade01903aee2e9d3d79be9283b15d928c6abf09cf094bd2fcf04b34
Deleted: sha256:e255c198c90fdf9ea2670f2da636b070f9ab79456118029a4c66e7f965ef835d
Deleted: sha256:15ef1d65041e3a265de67365a7e426a66a5b49e174b3dcfbb709e689f23530fe
Deleted: sha256:25a012251e866e7fbeb177d221b598d1eb4908446c3a79b9a2d7b3db243829a6
Deleted: sha256:7bff8e0a47f8f8c36996e7870c0fc26f79ddbbc4df0ce1e87bbaad2b921f1dc3
Deleted: sha256:52bd960d6ad2eea8e806acbf4f7d548cffd23620c5e6b4e2f1ed137b40ecf2c4
Deleted: sha256:9d9057073e73e8603debcc13e62f285ad68fa2c012ac140313c3e389c747b6d8
Deleted: sha256:b3af311bc5a72ad1a3aaae8eda53013616cea637603c1706078fd4cb07804b98
Deleted: sha256:9418cfad81731d3b3cbc99d29eaf02bc3a041eeb9edf90199f278ed03dd2f65b
Deleted: sha256:c6a68b552b98db291efc74024707c5eaa2337b7870fbfe4bb2ee631a6db3a43e
Deleted: sha256:91b43708591e86683a3868c8787c00512250ec1766d74b054db24b4746883b0b
Deleted: sha256:7d0ebbe3f5d26c1b5ec4d5dbb6fe3205d7061f9735080b0162d550530328abd6
Untagged: scrapinghub/splash:3.5
Untagged: scrapinghub/splash@sha256:c8f1036efd24dff8a688d5ccfcc4378120c447274caa832f090d9864d0bb598f
Deleted: sha256:93cac3cba2d3e2ffec01aaf317835498deee26259dd8f74ea97d22491247a5d4
Deleted: sha256:a314ef7a76396b490568c659f2c9711692dd7b350df8928f4b57ff3aa0227ac7
Deleted: sha256:2c1ee1f3fb3d801c51a744489c40e9897a19533fbd0ad46e460974a325ae1d88
Deleted: sha256:a19c0aa88e7fb877e3642c552cbd345f7ce6899acd350a655eb447d80dbdad35
Deleted: sha256:1ce9af445dedd12fffab01989bd3a3ff81ff8f41dd56511f7b4fc9c21c5e57c7
Deleted: sha256:37b2a3647011fd577ef0caa868b79f01d8c987e796b35a969d985799f7b149ab
Deleted: sha256:1fdc945756ddcb75e565dd0fb4f35fea39f07061a2f0128acc4b86381b55daf6
Deleted: sha256:8a50f368d132f50c272b7c3d0a88b81ab0dccb332d7954658b6caa23cd0dab3d
Deleted: sha256:e7f3b8ff98bb5a70f3e8049f23b1ad33d09fad6720046fd07873f5b2fe192152
Deleted: sha256:78b456e877dedddeeea89b402ad4dc30be663d5b2e852d38efd2bdc1f057d4a4
Deleted: sha256:dc73b9e1bf453db497f1dded1f1effb05944f244887243a27b687ed76b7c0c32
Deleted: sha256:a6a2a2b169c98ed4d887d4830d0f9f8c229784f3260465d312819e1385fb7504
Deleted: sha256:0878c576667efa863d30c60f8093c9411418249e5bf220a15801668604958f5a
Deleted: sha256:fb40c8cad6920f8e2c03cb24730201d3f3ddec9c612ba8c3dd556a720ef9b027
Deleted: sha256:f9052a79fb53c80f811c3824cf9de046f45dcf7b2762ab0f87d1dd8fb697a3d5
Deleted: sha256:2121c2630e0dcfc590ac186cd13328d34ca4253fd0cfc2d1c6e0901c8fd8e8e8
Deleted: sha256:1f8beba7e5f0a447e70d43e6bf371ccc20cbbb89888f03734fecaadf81c94bb9
Deleted: sha256:de24b0a7f0fd3790d5e158ee70fe72467f6b67c43ac2d6cb8e38843601463004
Deleted: sha256:83ff38e178cdf701f61a041c4948b6639a37e976201e7e47ac0fba4d96d5d640
Deleted: sha256:55c47d04539b7ef70aea066de6ab076f15062dd96238f97072aad99bef7e0913
Deleted: sha256:1e5d5ef34c270ec5a9d24b7a60a53d9bf71c835c22000acf1bb3b915befe3519
Deleted: sha256:39dbebdb3c89237b38501ae2d4b7a8e85576e8d1b1407abba66b90899a8aab4f
Deleted: sha256:6a51f500a462f053f5b68cbde550ae052c863b88101cfd69c9b6db0ce388dfd7
Deleted: sha256:28a6cdeed6dd92b5eec9b21b71b0ff3e93754313adc77ce5f2288b4e59e53568
Deleted: sha256:48ba0c6fdf4b069aad7a1eb6299dee017ef75b929a87ed63bc9226dee2cd50e8
Deleted: sha256:4d5330c8d5056fdfb6f2e32b225452de71517794a80e3ef998440e184d2e80cb
Deleted: sha256:3a9fa6b9e7ae21b704ed61109b612970f2b21449cd53e3154ed8800e2aefee0d
Deleted: sha256:7ef3687765828a9cb2645925f27febbac21a5adece69e8437c26184a897b6ec7

ボリュームを削除

ボリュームを確認

% docker volume ls
DRIVER    VOLUME NAME
local     my_scraping_db_volume

ボリュームを削除

% docker volume rm my_scraping_db_volume
my_scraping_db_volume

ボリュームを削除するとボリューム内のデータベースも削除されるので、データベースを保持する場合はボリュームのバックアップをとってから削除してください。

データベースの認証情報を変更

データベースの認証情報はボリューム内に保存されているので、認証情報を変更する場合は下記のいずれかの方法で変更してください。

  1. PostgreSQLコンテナ内に入り、データベースの認証情報を.env内で変更したものと同じものに変更する。
  2. ボリュームを削除し、.env内の認証情報を変更後Docker Composeを再度ビルドして変更する。

参考

Docker

Python

Scrapy

Splash

Selenium

PostgreSQL