🫥
Laravel(&Docker)でシンプルにクローラー処理を作ってみる※Mac M1
なぜ作ろうと思ったか?
Laravel使ったクローラー処理であんまり参考になるものがないなぁ(特にDockerまわりで)と思っていたのでやってみる。正直PHPでクローリング処理を実装するのもどうなんだろうなぁとおもいつつ、自社でPHP使うことも多いのでまぁいいか。
あとはmac m1 dockerでchromeが動かないのでchromiumでどうにかしたかったってのもある。
とりあえずまずはLaravelのインストール
※ mac m1で動くことを前提にしてます。
Laravel9を使うため、mac上にphp(8.2以上)、composerをインストール
brew install php
brew install composer
PHPへのパスを追加しておくこと(.zshrcとか)
export PATH="/opt/homebrew/opt/php/bin:$PATH"
export PATH="/opt/homebrew/opt/php/sbin:$PATH"
次にLaravelをインストール
composer create-project "laravel/laravel=9.*" crawler
次にdocker環境を構築していく
※ 自社のディレクトリ構成になっているので適宜読み替えてください。
app
docker
└ dev
└ app
└ Dockerfile
└ chromium
└ Dockerfile
└ docker-compose.yml
dev/app/Dockerfile
FROM php:8.2-fpm
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"]
COPY --from=composer:2.4 /usr/bin/composer /usr/bin/composer
RUN apt-get update && \
apt-get -y install git wget vim libicu-dev libzip-dev libonig-dev libcurl4-openssl-dev pkg-config procps && \
apt-get -y install locales locales-all task-japanese && \
apt-get -y install fonts-ipafont fonts-ipaexfont && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
mkdir /var/run/php-fpm && \
mkdir /var/log/php && \
docker-php-ext-install intl pdo_mysql zip && \
docker-php-ext-install curl && \
composer config -g process-timeout 3600 && \
composer config -g repos.packagist composer https://repo.packagist.org
# timezone environment
RUN echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8 && \
dpkg-reconfigure locales && \
/usr/sbin/update-locale LANG=ja_JP.UTF-8
ENV TZ Asia/Tokyo
ENV LANG ja_JP.UTF-8
ENV LANGUAGE "ja_JP:jp"
ENV LC_ALL ja_JP.UTF-8
# composer environment
# ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_NO_INTERACTION 1
COPY ./php.ini /usr/local/etc/php/php.ini
WORKDIR /project
dev/chromium/Dockerfile
FROM seleniarm/standalone-chromium
dev/docker-compose.yml
version: '3.9'
services:
app:
image: crawler
container_name: crawler
build:
context: ./app
volumes:
- ../../.:/project
networks:
- crawler-network
chromium:
image: crawler.chromium
container_name: crawler.chromium
hostname: selenium
build:
context: ./chromium
ports:
- 4444:4444
- 5900:5900
- 7900:7900
networks:
- crawler-network
networks:
crawler-network:
name: crawler-network
ビルドと立ち上げ
cd crawler/docker/dev
docker compose build
docker compose up -d
立ち上がったらサンプルでスクリーンショットが取れるかどうか確認
まずphp-webdriverをインストール
docker compose exec -it app bash
composer require php-webdriver/webdriver
サンプルバッチを作成
php artisan make:command SeleniumBatch
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Chrome\ChromeDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Interactions\WebDriverActions;
use Facebook\WebDriver\WebDriverDimension;
class SeleniumBatch extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'batch:selenium-sample';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$driverPath = "http://selenium:4444/wd/hub";
$options = new ChromeOptions();
$options->addArguments([
"disable-infobars",
"--headless",
"window-size=1920,1600",
]);
$capabilities = DesiredCapabilities::chrome();
$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);
$driver = RemoteWebDriver::create($driverPath, $capabilities);
$driver->get("https://www.google.co.jp/");
$driver->wait(2)->until(WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::name("q")));
$element = $driver->findElement(WebDriverBy::name("q"))->sendKeys("うっかりさん 困った時の備忘録")->submit();
$driver->wait(3)->until(WebDriverExpectedCondition::titleContains("うっかりさん"));
$file = __DIR__."/sample.png";
$driver->takeScreenshot($file);
$driver->quit();
return Command::SUCCESS;
}
}
実行してみる
php artisan batch:selenium-sample
sample.pngができてGoogleの検索画面が取得できれいればOK!
さいごに
ほぼコピペでクローラー処理ができるかと思います。
RubyとかPythonは結構でてくるのですが、PHP系がほとんどなかった(古かったり、LaraDuskしかなかったり)なのでちょっと書いてみました。
ECSもこれで行けると思うので本番化してみてまた悩んだら記事にしてみようと思います。
参考サイト)
Discussion