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

Laravel5.7とTwitterOAuth(TwitterAPI)を使ってハッシュタグをAPI制限に掛かる事なくDBに突っ込むクーロンを作る

そろそろTwitterAPI分かってきたので、指定のハッシュタグを呟いたユーザーや投稿データを収集していく。

Laravel初めてみて何知れば良いかわからないって人やAPIって何??って人は今回の記事で勉強するのが丁度良いボリュームだと思うので、やってみてください( ◠‿◠ )

めんどくさいので配列のハッシュタグと画像関連は取得しませんが、一応説明だけあとで入れておきます。

仕様

  • Cronを走らせた時点から現在の最新ツイートまで取得し続ける
  • 現在から過去のツイートは初期取得時以外に取得しない(要望あれば別記事で両方する方法書くけどしんどい
  • ツイートに紐づいた画像や配列(複数)のハッシュタグは取得しない
  • RTは含まない

事前準備&環境

  • 前回の記事でLaravelのインストールとTwitterOAuthが使える状態になっている

まだのかたはこちら
Laravel5.7でTwitterOAuthを使って認証やらツイート取得やら

  • Laravel5.7
  • MySQL5.6

ハッシュタグのモデルとマイグレーションを作る

php artisan make:model Hashtag -m

これでdatabase/migrations2019_07_04_123456_create_hashtags_table.phpapp/Http/Hashtag.phpが作成されたはずなので、早速マイグレーションを設定する。

2019_07_04_123456_create_hashtags_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateHashtagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('hashtags', function (Blueprint $table) {
            $table->increments('id');
            $table->string('tweet_id')->comment('ツイートID');
            $table->string('text')->comment('ツイート内容');
            $table->dateTime('tweet_created_at')->comment('ツイート日時');
            $table->string('screen_name')->comment('@スクリーンネーム');
            $table->string('user_name')->comment('ユーザー名');
            $table->string('profile_image_url')->nullable()->comment('プロフィール画像');
            $table->string('profile_background_image_url')->nullable()->comment('プロフィール画像');
            $table->integer('friends_count')->comment('フォロー数');
            $table->integer('followers_count')->comment('フォロワー数');
            $table->integer('statuses_count')->comment('ツイート数');
            $table->integer('retweet_count')->comment('リツイート数');
            $table->integer('favorite_count')->comment('いいね数');
            $table->dateTime('acquired_at')->comment('取得した日時');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('hashtags');
    }
}

こんな感じでマイグレーションを通して、、

php artisan migrate

次はModel!と言いたいがCronから書いた方が分かりやすそうなので、また後で。

Cronを書いていく

言わずもがな、コマンド叩いて時間設定するだけでその時間に処理をしてくれる頼もしい味方

Cronファイルを作成する

GetHashtagCommandの部分はお好きな名前で

php artisan make:command GetHashtagCommand

これでapp/Console/Commands/GetHashtagCommand.phpが作成されるはずなので、早速書いていく。
初期はこのような感じになっているはず。

Hashtag
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class GetHashtagCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    //ここに設定した名前でコマンドを叩くとCronが走る
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */

    //Cronの説明的なやつ
    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()
    {
        //
    }
}

じゃあ実際に書いていくよー。
まずはuseでHashtagモデルを指定するよ

GetHashtagCommand.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
//追加
use App\Http\Hashtag;

コマンド名はとりあえずget:hashtagにしました。

Hashtag
protected $signature = 'get:hashtag';

ハッシュタグはあんまり思い浮かばないので、#駆け出しエンジニアとつながりたいとかにしておきます。
今回はRTを除くため-RTという条件を追加していますが、RTも収集するならハッシュタグだけを指定してください。

GetHashtagCommand.php
    public function handle()
    {
        //任意のハッシュタグを設定する
        $hashtag = "-RT #駆け出しエンジニアとつながりたい";

        //DBにデータがあるか確認
        $query = Hashtag::get();

        //初期データ
        if (!is_object($query)) {
            //DBから最大値を取得
            $max = $query->max('tweet_id');
            //tweet_idの最大値から+1してDBのデータと被らないようにする
            $since_id = $max +1;
        } else {
            $since_id = null;
        }

        //TwitterAPIでデータを取得
        $twitter_api = Hashtag::getHashtagLatestApi($hashtag, $since_id);

        //TwitterAPIからデータが返ってきているか確認
        if (is_object($twitter_api)) {
            //念の為ツイートデータが入ってるか確認
            if (isset($twitter_api->statuses)) {
                //ツイート保存する処理
                $twitter_store = Hashtag::hashtagStore($twitter_api);
            }
        }
    }

Cronで呼び出されるメソッドを記述したモデル

Hashtag.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Hashtag extends Model
{
    //created_atとupdated_atは使わないのでfalseにしておく
    public $timestamps = false;

    //最新のツイートを取得する
    public static function getHashtagLatestApi(string $hashtag, int $since_id = null)
    {
        //TwitterAPIを呼び出してデータを取得する
        $twitter_api = \Twitter::get("search/tweets", [
            'q' => $hashtag,
            'count' => 100,
            'since_id' => $since_id
        ]);

        return $twitter_api;   
    }

    //ツイートオブジェクトを形成してDBに保存する
    public static function hashtagStore(object $twitter_api)
    {
        //ステータス情報の取得
        $statuses = $twitter_api->statuses;

        if (is_array($statuses)) {
            //ステータス情報のカウント
            $status_count = count($statuses);

            for ($i = 0; $i < $status_count; $i++) {
                //インスタンスを作成
                $hashtag = new Hashtag;
                //取得したツイート情報を変数に格納
                $status = $statuses[$i];

                //ツイート情報
                $hashtag->tweet_id = $status->id;
                $hashtag->text = $status->text;
                $hashtag->tweet_created_at = date('Y-m-d H:i:s', strtotime($status->created_at));
                //ツイートしたユーザーの情報
                $hashtag->screen_name = $status->user->screen_name;
                $hashtag->user_name = $status->user->name;
                $hashtag->profile_image_url = $status->user->profile_image_url;
                $hashtag->profile_background_image_url = $status->user->profile_background_image_url;
                $hashtag->friends_count = $status->user->friends_count;
                $hashtag->followers_count = $status->user->followers_count;
                $hashtag->statuses_count = $status->user->statuses_count;
                $hashtag->retweet_count = $status->retweet_count;
                $hashtag->favorite_count = $status->favorite_count;
                $hashtag->acquired_at = now();
                //DBへ保存する
                $hashtag->save();
            }
        }
    }
}

ここでツイートに付属する画像や配列のハッシュタグもツイート情報に付属しているので、
条件分岐でごにょごにょして保存してください。

Cronのスケジュールを作成する

では収集して保存する処理までは一通り終わったので、実際にcronで指定した日付毎に、処理を走らせるスケジュールを登録しましょう!( ◠‿◠ )

app/Console/Karnel.phpを開いてください。

初期状態はこのようになっていると思います。

Karnel.php
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')
        //          ->hourly();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

設定するところをコメントアウトで説明します。

Karnel.php
    //ここに実行したいcronを指定します。
    protected $commands = [
        \App\Console\Commands\GetHashtagCommand::class,
    ];
Karnel.php
    //ここで実行するコマンドと走らせる時間を設定する
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('get:hashtag')->everyFiveMinutes();
    }

ちなみに今回は5分に1回cronを実行するようにしているので、時間はお好きなようにどうぞ!

Cronスケジュールオプション 説明
->everyMinute(); 毎分タスク実行
->everyFiveMinutes(); 5分毎にタスク実行
->everyTenMinutes(); 10分毎にタスク実行
->everyThirtyMinutes(); 30分毎にタスク実行
->hourly(); 毎時タスク実行
->hourlyAt(17); 一時間ごと、毎時17分にタスク実行

参考サイト

Laravelでバッチ処理(Cron)を実行する

これで完了。

早速先ほど設定した実行コマンドを叩いてCronを走らせてみる。

php artisan 'get:hashtag'

取得できました!!
これで5分に1回100件ずつ勝手に取得するようになりました。

最後に

今回は最新ツイートを取得する方法を書きましたが、需要があれば過去のハッシュタグを収集する方法やリツイートを同じ様に収集する方法も書こうかなーっと思ってます。

とりあえず終わり。

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
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