Help us understand the problem. What is going on with this article?

LaravelでスクレイピングしたデータをSeederに逆生成してみた話

やりたい事

  • 某サイトからスクレイピングしてきたデータをDBに保存。
    ※某サイトからは許可を得ている。
  • ローカルの開発環境でもある程度、テストデータとして、Seederは用意しておきたい。
  • PHPUnitを実行する時にテストデータを作っておきたい。

導入方法

スクリーンショット 2019-12-24 0.19.32.png

1.fabpot/goutteをインストール

$ composer require fabpot/goutte

2.スクレイピングするバッチを作成

<?php

namespace App\Console\Commands;

use App\Entity\Article;
use Goutte\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

/**
 * Class ScrapingCommand
 * @package App\Console\Commands
 */
class ScrapingCommand extends Command
{

    /**
     * スクレイピング先のURL
     */
    const SCRAPING_URL = 'http://example.com';

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:scraping_command';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {

        //インスタンス生成
        $client = new Client();

        //取得とDOM構築
        $crawler = $client->request('GET', self::SCRAPING_URL);

        //要素の取得
        $tr = $crawler->filter('table tr')->each(function($element){
            echo $element->text()."\n";
        });

        // 以下略

        // 取得したデータをArticleエンティティに設定 ※例なので、ざっくり書いてます。
        $article = new Article();
        // 本当は良い感じに取得したデータをエンティティに詰める
        $article->title = $tr;
        // 以下略

        DB::beginTransaction();
        try {
            $article->save();
            DB::commit();

        } catch (\Exception $exception) {
            Log::error('記事の更新に失敗しました', [
                'exception' => $exception->getMessage(),
                'file' => __FILE__,
                'method' => __FUNCTION__,
                'line' => __LINE__
            ]);
            DB::rollBack();
        }

        Log::notice('スクレイピングバッチの実行が成功しました。');
    }
}

3.orangehill/iseedをインストール

https://github.com/orangehill/iseed

$ composer require --dev "orangehill/iseed"

を実行。

config/app.phpにProviderの設定を追加

'providers' => [

        /*
         * データベースからLaravelのSeederを逆生成する
         */
        Orangehill\Iseed\IseedServiceProvider::class
    ],

4.下記のコマンドを実行すればテーブルの内容に応じたSeederクラスが生成される。

$ php artisan iseed {table_name} 

を実行。

5.Seederクラス生成後のイメージ

<?php

use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        \DB::table('articles')->delete();

        \DB::table('articles')->insert([
                0 => [
                    'id' => 1,
                    'title' => 'タイトル',
                    'descrition' => '記事の説明文',
                    'category' => 'Tech',
                ],
                1 => [
                    'id' => 2,
                    'title' => 'タイトル',
                    'descrition' => '記事の説明文',
                    'category' => 'Tech',
                ],
                2 => [
                    'id' => 3,
                    'title' => 'タイトル',
                    'descrition' => '記事の説明文',
                    'category' => 'Tech',
                ]
            ]
        );
    }
}

使ってみた感想

  • けっこうコマンドの実行時間も短いし、良かった
  • データ量が多いとファイルサイズが大きくなってしまうので、上手くfor文とかで重複データはコードで簡潔にまとめてもらえたら尚嬉しい!
  • お客さんがマスタデータを提供していない or APIが存在せず、自分でデータを取得しなければいけない案件には向いてそう!

参考記事

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした