4
1

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 3 years have passed since last update.

おにぎり万太郎Advent Calendar 2019

Day 1

TwitterGemを使うときは困ったらとりあえずto_hするべし

Last updated at Posted at 2019-11-30

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"

色々取れますね。

ハマったところ

古着屋 Hurugisuko(@hurugisuko)さん : Twitter 2019-11-22 09-21-57.png この赤枠部分の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件)取得することができます。
.irb
[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

.irb
[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で画像情報も取得することができませんでした。これは困った。

.irb
[1] pry(#<TwitterClient>)> tweet.text
=> "【 yutori online store new arrival 】\n☑︎12/1(日)23時新商品入荷‼︎\n\nいよいよ12月に突入です☃️‼️\n\n12月最初の入荷は使いやすいブルゾンからセーター&amp;スウェットを多めにピックアップ… 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' } を渡すことで、長いツイートでも全文および画像の取得ができました。ただし、ツイートの全文取得はインターフェースが変わるので注意が必要です。

.irb
# { 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月最初の入荷は使いやすいブルゾンからセーター&amp;スウェットを多めにピックアップ🔥\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しちゃって取るのが楽そうです。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?