tl;dr
TwitterGemを使うときの返り値のクラスは、基本的にEnumerable
をincludeしているので雑にto_h
しちゃって取るのが楽そうです。
この記事のスコープ
TwitterGemを介してTwitterAPIを叩き、ツイートの取得を行うところまで。個人的に詰まったポイントがあったのでそこも併せて共有できたらなと思って書きました。
TwitterGemとは
RubyでTwitterAPIを操作できるようになるgemです。リポジトリはここから
APIを叩くためにはTwitter社に対して申請をする必要がありますが、その具体的な方法については本記事では割愛します。
英語で利用目的などを書かないといけないためウッとなりますが、Google翻訳を駆使しながら書いたガバガバ英語でもapproveされたので、構える必要はないと思ってます。
インストール
普通に
gem install twitter
するか、Gemfileに書いて
bundle
しましょう。
READMEにはサポートされているRubyバージョンとして、2.3 ~ 2.5 が挙げられていますが、筆者の環境では2.6.3でも問題なく動作しています。きっと。
準備
まずはrequireしましょう
require 'twitter'
次にAPIを叩く用のclientを生成します
class Twitter
def initialize
@client = Twitter::REST::Client.new |config|
config.consumer_key = "consumer_key"
config.consumer_secret = "consumer_secret"
config.access_token = "access_token"
config.access_token_secret = "access_token_secret"
end
end
end
それぞれキーを突っ込んであげてください。
これで準備完了です。簡単ですね。
使い方
Rubyで簡単なTwitter クライアントをつくる をぜひ参照しましょう。私もお世話になりました。リンク先の記事では
- タイムラインの取得
- リプライの取得
- 特定のリストのタイムラインを取得
- ツイート
を紹介しています。
本記事では
- ユーザの詳細情報の取得
- ツイートごとの詳細情報の取得
これらを紹介するとともにハマったポイントについてご紹介できればと思っています。
Twitterユーザの詳細情報を取得
リストを指定しユーザを取得する
list_members
というメソッドに、ユーザ名とリスト名を与えてあげることで取得することができます。この結果は、TwitterClient::Cursor
クラスのインスタンスとして返ってきます。こいつはEnumerable
をincludeしているのでArrayやHashと同様にeach
を使ってごにょごにょできます。便利です。
[1] pry(#<TwitterClient>)> @client.list_members('twitterのユーザ名', 'リスト名').class
=> Twitter::Cursor
[2] pry(#<TwitterClient>)> @client.list_members('twitterのユーザ名', 'リスト名').class.include?(Enumerable)
=> true
コード例
class Twitter
def initialize
...
end
# リストに属しているユーザをArrayとして取得する
def fetch_list_users
list_members('twitterのユーザ名', 'リスト名').each_with_object([]) do |user, arr|
arr << member
end
end
end
Twitter::User
サンプルとして
https://twitter.com/hurugisuko ( 私の好きなネットの古着屋さん ) を使いました。
[1] pry(#<TwitterClient>)> user = list_members('twitterのユーザ名', 'リスト名').first
=> #<Twitter::User id=1111913399225450496>
# ユーザの名前を取ってくる
[2] pry(#<TwitterClient>)> user.name
=> "古着屋 Hurugisuko"
# プロフURL
[3] pry(#<TwitterClient>)> user.url
=> #<Addressable::URI:0x3fd4935192c4 URI:https://twitter.com/hurugisuko>
# AddressableからURLへ変換
[4] pry(#<TwitterClient>)> user.url.to_s
=> "https://twitter.com/hurugisuko"
# プロフィール画像を取ってくる
[5] pry(#<TwitterClient>)> user.profile_image_url_https
=> #<Addressable::URI:0x3fd491727798 URI:https://pbs.twimg.com/profile_images/1113260900587147264/xVaQa0Lc_normal.jpg>
# URLだけ抽出
[6] pry(#<TwitterClient>)> user.profile_image_url_https.to_s
=> "https://pbs.twimg.com/profile_images/1113260900587147264/xVaQa0Lc_normal.jpg"
# 自己紹介情報を取ってくる
[7] pry(#<TwitterClient>)> user.description
=> "若い世代に向け、「お金をかけないオシャレ」「唯一無二のスタイル」をコンセプトに幅広く古着を販売しています。 Hurugisukoは2人の人間で管理・運営を行っています。「生活に小さな彩りを添える」がコンセプトのハンドメイド作品たちはこちらから→@hurugisukohh"
色々取れますね。
ハマったところ
この赤枠部分のURLどうやって取るんだろうってところ。 `user.url`はtwitterのURLに飛んでしまうし。。 ### 解決方法 ``` user.to_h[:url] => "https://t.co/fiupN9eIDi" ``` URLを叩くとメルカリの画面へ遷移できているかと思います。 `Twitter::User`クラスに対して、to_hでhash化してキーを与えることで取得しています。 メソッドとして定義されているものと、to_hとキーで取ってくる2つのパターンがある、ということが大事なポイントです。 # ツイートごとの詳細な情報 ## 特定のユーザのツイートを取ってくる `user_timeline`というメソッドに、`user_id(Twitter::User#id)`を与えてあげることでそのユーザのツイート(デフォルトで20件)取得することができます。[1] pry(#<TwitterClient>)> @client.user_timeline(twitter_user_id)
=> [#<Twitter::Tweet id=1198931529931427840>,
...
]
コード例
class Twitter
def initialize
...
end
# 特定のユーザのツイートを取ってくる
def tweets(account)
@client.user_timeline(account, opt)
end
end
def opt
{ count: 10 }
end
end
このメソッドにはオプションを渡すことができて、例えば@client.user_timeline(twitter_user_id, count: 10)
とすれば、10件のツイートを取ってきてくれます。
他のオプションについてはrubydocが参考になるかと思います。
Twitter::Tweet
[1] pry(#<TwitterClient>)> t = @client.user_timeline(account, count: 10).first
=> #<Twitter::Tweet id=1200744305482031107>
# ツイート内容の取得
[2] pry(#<TwitterClient>)> t.text
=> "coming soon...\n\n☑︎12/1(日) 23時発売開始‼︎\nhttps://t.co/aVf7vUNRIT https://t.co/b77r7AvC0i"
# メディアの取得
[3] pry(#<TwitterClient>)> t.media
=> [#<Twitter::Media::Photo id=1200744297571602434>,
#<Twitter::Media::Photo id=1200744297567375362>,
#<Twitter::Media::Photo id=1200744297693237250>,
#<Twitter::Media::Photo id=1200744297575804928>]
# 画像のURLを取得
[4] pry(#<TwitterClient>)> t.media.first.media_url_https
=> #<Addressable::URI:0x3fe8da8c19d4 URI:https://pbs.twimg.com/media/EKnmk6rU0AIbZuV.jpg>
[5] pry(#<TwitterClient>)> t.media.first.media_url_https.to_s
=> "https://pbs.twimg.com/media/EKnmk6rU0AIbZuV.jpg"
こちらも同様に色々できます。
困ったところ
たまにTwitter:Tweet#text
で全文を取得できないケースがあります。(...
として省略されている)
調べると、twitterAPIの仕様変更があって、長いつぶやきは省略されてしまうそう。ref: アップデートの情報
とりあえず雑にto_h
すると、:truncated
というキーがあり、textが省略されているツイートは、ここがtrueになっていました。
さらに調べると、truncated
がtrueになっているツイートでは、前述したTwitter:Tweet#media
で画像情報も取得することができませんでした。これは困った。
[1] pry(#<TwitterClient>)> tweet.text
=> "【 yutori online store new arrival 】\n☑︎12/1(日)23時新商品入荷‼︎\n\nいよいよ12月に突入です☃️‼️\n\n12月最初の入荷は使いやすいブルゾンからセーター&スウェットを多めにピックアップ… https://t.co/waU8pfXuo1"
[2] pry(#<TwitterClient>)> tweet.to_h[:truncated]
=> true
[3] pry(#<TwitterClient>)> tweet.media
=> []
[4] pry(#<TwitterClient>)> tweet.id
=> 1200755654043918336
解決方法
user_timeline
へのオプションとして、{ tweet_mode: 'extended' }
を渡すことで、長いツイートでも全文および画像の取得ができました。ただし、ツイートの全文取得はインターフェースが変わるので注意が必要です。
# { tweet_mode: 'extended' } を指定してuser_timelineを叩く
# tweet.idは上記の[4]と同じ
[1] pry(#<TwitterClient>)> tweet.id
=> 1200755654043918336
[2] pry(#<TwitterClient>)> tweet.to_h[:truncated]
=> false
# Twitter#Tweet#full_text は定義されていないのでto_h経由で取得する
[3] pry(#<TwitterClient>)> t.to_h[:full_text]
=> "【 yutori online store new arrival 】\n☑︎12/1(日)23時新商品入荷‼︎\n\nいよいよ12月に突入です☃️‼️\n\n12月最初の入荷は使いやすいブルゾンからセーター&スウェットを多めにピックアップ🔥\n\nお気に入りのアウターに合わせる1着を是非見つけて下さい💕\n\n良ければリツイート宜しくお願い致します🙇♂️✨ https://t.co/8LKvQ35PJu"
[4] pry(#<TwitterClient>)> t.media
=> [#<Twitter::Media::Photo id=1200755645940502531>,
#<Twitter::Media::Photo id=1200755645936357377>,
#<Twitter::Media::Photo id=1200755645944696832>,
#<Twitter::Media::Photo id=1200755646204760064>]
結論 (再掲)
TwitterGemを使うときの返り値のクラスは、基本的にEnumerable
をincludeしているので雑にto_h
しちゃって取るのが楽そうです。