Laravel Zeroを使ったコンソールアプリ制作

お久しぶりです。kubotakです。
昨年のアドベントカレンダーは如何でしたでしょうか。
まだ見てないよ、という方はこちらから!

さて、弊社ではLaravel JP Conference 2019にシルバースポンサーとして参加しています。

また、弊社CTO竹澤がこのカンファレンスの実行委員長、そしてこの記事を書かせていただいているkubotakがスタッフとして参加しています。

今回はLaravelJP Conferenceのネームカードに利用する、Twitter画像を取得するコンソールアプリケーションをLaravel Zeroを利用して作っているという話を書きたいと思います。
当初はNode.jsでPuppeteerを使って作ろうかと思ったんですが、LaravelのカンファレンスということでPHPで、いや、Laravelで作ろうと思いLaravel Zeroを採用しました。

※ Webサイトクローリングについては対象のサイトの利用規約や節度を守って行いましょう。(参考

Laravel Zeroとは

Laravelのコンソールアプリ向けのマイクロフレームワークです。Laravelの名を冠してますがLaravel公式ではなく別のコミュニティが開発しています。
簡単にいうとLaravelアプリケーションでartisanコマンドを作成できる部分だけを抜き出したようなフレームワークになっているのでLaravelで開発経験がある場合は同じようにコンソールアプリケーションを作成することができます。

始め方は簡単です。
グローバルにLaravel Zero CLIを導入してもいいですし、

$ composer global require "laravel-zero/installer"
$ laravel-zero new laracon-console

composerからアプリを作成することもできます。

$ composer create-project --prefer-dist laravel-zero/laravel-zero laracon-console

これでスケルトンが完成です。

SplFileObjectを利用してTSVを配列で取得

Laravel JP ConferenceではPeatixでチケット販売を行っています。

購入時にアンケートを設けていて、Twitterアカウントをお持ちの方には入力してもらう様になっています。
このアンケートで入力された情報はPeatix管理画面よりTSV形式でダウンロードすることができます。
ですので、TSVを取得してTwitterアカウントを利用しTwitterページへアクセス、そして画像を取得するというフローになります。

ここで、PHP標準クラスのSplFileObjectを利用することで簡単にTSVを読み込むことができます。

use SplFileObject;

~~~
// そのまま読み込むと日本語が化けるのでエンコードを指定
setlocale(LC_ALL,'ja_JP.UTF-8');
$read_file_path = base_path("TSVファイルのパス");
// ファイルが存在するかどうか確認
if (!file_exists($read_file_path)) {
    throw new \ErrorException("${$read_file_path} is not exists");
}
$file = new SplFileObject($read_file_path, 'r');
// 空行無視はSKIP_EMPTYとREAD_AHEADを共に設定する
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::READ_AHEAD);
$file->setCsvControl("\t");

// TSVを一行づつ取得
foreach ($file as $key => $row)
{
    //
}

PHPの標準クラスを利用することで簡単にTSVを取得し、扱うことができました。

phpQueryでスクレイピング

Twitterのページからユーザーの画像取得する処理をphpQueryというライブラリを利用しました。
こちらはjQueryのような感覚でHTMLの特定の要素にアクセスできるphpライブラリです。

composerにもありますので以下から導入が可能です。

$ composer require electrolinux/phpquery

使い方は簡単。まずはfile_get_contentsで対象のページを取得しphpQuery::newDocumentに渡します。
そうすることでjQueryのようにHTML要素へアクセスできます。

use phpQuery;

$html = file_get_contents("twitterページのURL");
$src = phpQuery::newDocument($html)->find(".ProfileAvatar-image")->attr("src");

ここではHTMLからProfileAvatar-imageクラスのついたimgタグを取得し、そのattributeのsrc属性の内容、つまり画像のURLを取得しています。

このURLから、Intervention Imageというライブラリを利用して画像をリサイズして保存します。

$this->imageManager->make($src)->resize(500, 500, function (\Intervention\Image\Constraint $constraint) {
    $constraint->aspectRatio();
})->save(base_path("/storage/images/{$account->name()}.jpg"), 90);

$this->imageManagerにコンストラクトインジェクションでIntervention\Image\ImageManagerを注入しています。

これでTwitterページから画像を500x500pxで保存することができました。

最後に

Laravel Zeroを利用することでLaravelの知見を活かしてスムーズにコンソールアプリケーションを作成することができました。
現在コミュニティではノベルティなど鋭意準備中となりますので皆さんイベント当日を楽しみにしてください!
無事チケットは完売したそうですのでネームカードをお楽しみにしてください!
弊社アイスタイルでもシルバースポンサーとしてイベントを応援しています。

アイスタイルの緑髪担当 元デザイナーの中途4年目です PHPer, JSer 時々Gopher