1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel 9 × TwitterOAuth】Twitter API v2 searchで取得したツイートをHTMLタグ化して表示

Posted at

oEmbed APIを利用する方法は追って更新します。

こんにちは、現在エンジニアを目指して勉強中の一般男性です。

Twitter API触ってみようと思って
キーワード検索でツイートを取得してHTMLとして表示するところまで
なんとか実装できたので、メモを残しておきます。

自分と同じ初学者の方向けに参考になると幸いです。
また、先輩エンジニアの皆さん、こうすればもっと良くなる
ということがあれば、ぜひコメントいただけると嬉しいです!

前提

今回は、TwitterAPIからツイートを取得して、HTMLとして表示するまでを目指します。

ツイートを埋め込むHTMLタグを用意するためには、
対象のツイートのURL情報が必要です。

まずは、個別のツイートのURLがどのように構成されているかを確認しましょう。

https://twitter.com/ユーザーネーム/status/ツイートID
<!-- ユーザーネームは @username の username にあたる部分 -->

ということで、検索の部分ではツイートIDとユーザーネームの取得を目指します。

環境

・macOS Monterey 12.6
・PHP 8.1.13
・Laravel 9.3.12
・Docker 20.10.2
・Laravel Sail

・composer 2.4.4
・abraham/twitteroauth 5.0.0
・Twitter API v2

Twitter APIキーの申請とTwitterOAuthのインストール

この投稿では扱いませんので、こちらの記事などをご参考ください。

ちなみに、Twitter APIの申請には数日~長いと1,2週間 という
情報をちらほら見かけましたが、自分の場合は一瞬で通りました。(2023/1 時点)

申請と並行して、composer経由でTwitterOAuthを入れておきましょう。

composer require abraham/twitteroauth

Search Tweets

キーワード検索

.envとconfigの設定

ますは取得したキーを.envにセットします。

.env
TWITTER_API_KEY = yourKey
TWITTER_API_SECRET = yourSecretKey
TWITTER_BEARER_TOKEN = yourBearerToken

次にconfig/twitter.php経由で.envの値を使えるように設定

config/twitter.php
<?php

// 第二引数は.envから値を引っ張ってこれなかった時に使われる値
return [
    'api_key' => env('TWITTER_API_KEY', ''),
    'secret_key' => env('TWITTER_API_SECRET', ''),
    'bearer_token' => env('TWITTER_BEARER_TOKEN', ''),
];

両ファイルが正しくセットされているのに値が使えない場合には、
キャッシュを疑ってみるといいかもしれません。

キャッシュクリアのコマンド貼っておきます。

ルーティング設定

こちらも忘れずに。
今回は/tweetにアクセスするとツイート取得が始まるようにしておきます。

routes/web.php
Route::get('/tweet', [App\Http\Controllers\TwitterController::class, 'getTweet']);

コントローラー作成

私はサービスプロバイダーなどの構成を理解しきれていない部分もあり、
今回はコントローラーに処理を書きました。

TwitterController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

// これの記載は不要。私と同じ初学者の方はご注意
// require "vendor/autoload.php";

use Abraham\TwitterOAuth\TwitterOAuth;

class Twittercontroller extends Controller
{
  public function getTweet() {

    $connect = new TwitterOAuth(
                        //config.twitterの'api_key'。中身はenv('TWITTER_API_KEY')
                        config('twitter.api_key'),
                        config('twitter.secret_key'),
                        null,
                        config('twitter.bearer_token')
                      );

    // Twitter APIの v2を指定
    $connect->setApiVersion('2');

    // リツイートを除く「キーワード」を含むツイートを検索
    $query = 'キーワード -is:retweet';

    $params = [
       'query' => $query,
       // 他にも取得件数やいつ以降のツイートに絞るなど、複数の設定が可能
     ];

    $result = $connect->get('tweets/search/recent', $params);
    dd($result);
  }
}

これでキーワード検索が可能になります。
最低限の内容になっていますので、
より詳しく知りたい方は以下の公式ドキュメント(英語)を参照ください。

検索クエリ(キーワード等)の設定について
検索パラメータの設定について

取得結果

取得できるデータも見ておきましょう。
edit_history_tweet_idsidtextがワンセットです。
アカウント名なども、パラメータで設定すれば取得できます。

{#355 ▼ // app/Http/Controllers/TwitterController.php:29
  +"data": array:10 [▶]
  +"meta": {#356 ▶}
}

ここでは2件のツイートしか表示しませんが、
取得するデータ件数はデフォルトでは10件です。

{#355 ▼ // app/Http/Controllers/TwitterController.php:29
  +"data": array:10 [▼
    0 => {#330 ▼
      +"edit_history_tweet_ids": array:1 [▼
        0 => "1615584040480043008"
      ]
      +"id": "1615584040480043008"
      +"text": "いまどきの女の子200人への調査結果! 1位になったキーワードは「一緒にいるとほっとする」で155人。2位は「かわいいね」(108人)、3位は「話しやすい」(58人)という結果になった。参考になればRT"
    }
    1 => {#346 ▼
      +"edit_history_tweet_ids": array:1 [▼
        0 => "1615584027326529537"
      ]
      +"id": "1615584027326529537"
      +"text": """
        ・力を合わせてレオンとジルーを封じる
        ナポリ戦のレベルに戻るには?ここでインザーギの2つ目のキーワードであるチームが登場する。「チームメイトのために皆がもっと走らなければならない。絶対的な価値を持つ攻撃者と対峙するのだから、チームワークを発揮しなければならない。守備は皆次第だ。」 https://t.co/RAu16KGPpB
        """
    }
  ]
  +"meta": {#356 ▼
    +"newest_id": "1615584040480043008"
    +"oldest_id": "1615583203518996480"
    +"result_count": 10
    +"next_token": "b26v89c19zqg8o3fqk41gdjqoqm3frmpfztnb2fzziph9"
  }
}

ユーザー情報の取得

前述のツイート検索でツイートidは取得できました。
追加で、ユーザーネームを取得できるよう
パラメータに変更を加えていきます。

expansionsとuser.fieldsパラメータの追加

TwitterControllerを修正します。

TwitterController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Abraham\TwitterOAuth\TwitterOAuth;

class Twittercontroller extends Controller
{
  public function getTweet() {

    $connect = new TwitterOAuth(
                        config('twitter.api_key'),
                        config('twitter.secret_key'),
                        null,
                        config('twitter.bearer_token')
                      );

    $connect->setApiVersion('2');
    $query = 'キーワード -is:retweet';
    $params = [
       "query" => $query,

       // 以下を追加
       "expansions" => "author_id",
       // ここは書いても書かなくても良い
       "user.fields" => "",
     ];

    $result = $connect->get('tweets/search/recent', $params);

ユーザー情報を取得する際にはuser.fieldsを追加します。
ただ、user.fieldsパラメータは単体では機能しません。

パラメータexpansionsauthor_idを指定することで、
idに紐づいたユーザー情報を取得することができるようになるので
忘れずに指定します。

以下公式の抜粋です。
(記載の通り、author_id以外にも紐付けられるものがあります)

You must also pass one of the user expansions to return the desired user fields:
expansions=author_id
expansions=entities.mentions.username
expansions=in_reply_to_user_id
expansions=referenced_tweets.id.author_id

また、user.fieldsはデフォルトでidnameusernameを返すので、
user.fieldsには何も指定していません。
他のデータ(プロフ文など)が欲しい方は指定すればOKです。

取得結果

ツイートに付随するユーザー情報は、一見含まれていないように見えます。
が、includesに含まれてます。
laravelddでは確認できませんでしたが
print_rしてあげたら出てきました。。

取得したデータは以下のような構造(サンプルです。ddでは見えません。)

// $resultの中身

{#355 ▼ // app/Http/Controllers/TwitterController.php:29
  +"data": array:10 [▶]
  +"includes": [users] => array
  +"meta": {#356 ▶}
}
// $result->includes->users[0]の値

stdClass Object
(
    [id] => id
    [name] => 名前
    [username] => @username の username
)

これで、ツイートのURL生成に必要な
ツイートid、ユーザーネームが取得できました。

ツイートのHTMLタグ化

HTMLタグを取得する2つの方法

さて、データを取得できたので、HTML化していくのですが、
そもそも方法としては2通りあります。

・HTMLテンプレを使う
TwitterAPIoEmbed APIを使う(更新中)

スクリーンショット 2023-01-18 19.06.08.png
ということで進めていきましょう。

HTMLタグテンプレの利用

以下のHTMLを埋め込むことで、Twitter投稿を表示できます。

<blockquote class="twitter-tweet">
   <a href="(埋め込みたいツイートのURL)"></a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

URL生成

Search APIで取得したデータをforeachで回し、URLを生成します。
for文も試したのですが、たまにキーが存在しないとエラーになることがあり、
下記のforeachが確実でした。

TwitterController.php
    $result = $connect->get('tweets/search/recent', $params);

    // ここからURL生成
    $base_url = 'https://twitter.com/';

    foreach ($result->data as $data) {
      foreach ($result->includes->users as $user) {
        if ($data->author_id === $user->id) {
          $urls[] = $base_url . $user->username . '/status/'. $data->id;
        }
      }
    }

テンプレに埋め込む

生成したhtmlを変数に格納してビューに渡せば、表示することができます。

twitter.html
<!-- laravelプロジェクトなので、本当はtwitter.blade.php -->
@foreach($urls as $url)
  <blockquote class="twitter-tweet">
     <a href="{{ $url }}"></a>
  </blockquote>
  <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
@endforeach

ただこの方法、10件表示するだけでもめちゃくちゃ重かったのでご注意ください、、

oEmbed API

このAPIを利用するためには、APIのプラン?を
デフォルトのessentialからelevatedへアップデートする
申請をしなければいけないようです。

elevatedの説明は以下

Higher levels of access to the Twitter API for free with an approved application.

Developer Portalから申請ができますが、
このタイミングで色々な入力項目が発生します

How will you use the Twitter API or Twitter Data?

ここから先は、申請が通ったタイミングで記載しようと思います。
今回はここまで。

参考

公式

Search↓

oEmbed↓

Twitter Publish↓

TwitterOAuth↓

その他

(こちらはだいぶ古いです)

おまけ

実際に情報を集めてみてわかったんですが
自分が求めていた情報(観光地情報)は
Twitterで集めるには微妙だった、、

かといって、Instagram APIでの投稿取得も
ハッシュタグに紐づいているみたいで、ちょっと不便そう。

ということで、イメージしていた機能は一旦ペンディングにしました。笑
最初のリサーチはちゃんとやっておかないとですね★

.

にしても、Twitter APIは公式ドキュメントが英語、
かつv1 とv2 の情報が錯綜していたりと
GoogleMaps APIに比べて苦労した感覚があります。

落ち着いたら英語の勉強もしたいな。。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?