tweepy で 動画 url 取得しようとしてハマった話

# はじめに
女優 松岡茉優の最新画像と動画が毎日自動で送られてくる LINE Bot の作成中に、tweepy から画像・動画URLを取得しようとして、ハマったので共有しておきます。

今振り返ればなかなかどんくさく無駄な時間を過ごしましたが、とりあえず記事にすればちょっとはあの無駄な時間も報われるだろ！！ってことで書きます。

![L.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569968/c9ce94f6-688d-4c24-625d-493f5f81dbe0.png)


# 元コード

```python:search_tweets.py
import os
import tweepy
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta

consumer_key = os.getenv('TWITTER_CONSUMER_KEY')
consumer_secret = os.getenv('TWITTER_CONSUMER_SECRET')
access_token = os.getenv('TWITTER_ACCESS_TOKEN')
access_token_secret = os.getenv('TWITTER_ACCESS_TOKEN_SECRET')
bearer_token = os.getenv('TWITTER_ACCESS_TOKEN_SECRET')


# twitter で松岡茉優関連のツイートを検索してURL取得
def search_tweets():
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    api = tweepy.API(auth)

    yesterday = datetime.strftime(datetime.today() - relativedelta(days=1), f"%Y-%m-%d")
    # リツイートを省く、いいね10以上、昨日〜今日、リツイート1以上、の画像と動画がある、の条件でtwitter検索
    q = f'#松岡茉優 OR 松岡茉優 filter:media exclude:retweets min_faves:10 since:{yesterday} min_retweets:1'

    # 問題となった部分
    tweets = tweepy.Cursor(api.search, q=q).items(20)

    contents = []
    for tweet in tweets:
        print(tweet.text)
        print(tweet.extended_entities)
        try:
            media = tweet.extended_entities['media']
            for m in media:
                print(m)
                preview = m['media_url_https']
                if m['type'] == 'video':
                    origin = [variant['url'] for variant in m['video_info']['variants'] if variant['content_type'] == 'video/mp4'][0]
                else:
                    origin = m['media_url_https']

                # LINE Bot で送信するために整形
                content = {'preview': preview, 'origin': origin, 'type': m['type']}
                contents.append(content)

            print('--------------------------------------------')
        except:
            print('Error')
            print('--------------------------------------------')
    return contents


if __name__ == "__main__":
    search_tweets()

```


**このコードで、画像・動画付きツイート両方のURLを取得できるはずだった。。。。。**

# 思ったように動画URLが取得できない

ツイートの検索はできるのだが、動画URL取得できるものとできないものがあることに気づく。

try 内でエラー起こってるかもな。。。


各 tweet を print してみると、 extended_entities がない tweet がちらほらあった。

```python
for tweet in tweets:
        print(tweet.text)
        # 原因の部分 
        # extened_entities がないので、ここでエラーが起こり except: へ行っていた。
        print(tweet.extended_entities)
        try:
            media = tweet.extended_entities['media']
``` 

調べたら記事がいっぱいあった。

140文字以上のツイートを取得する
https://qiita.com/hitsumabushi845/items/f7fd87106381fc65fc86

**ツイートとVideo URLが140文字を超えると、extended_entities がなくなるらしい。**

これに気づくのにめちゃくちゃ時間かかった。というか、調べれば一瞬で解決した。

## 解決方法

api.search の パラメーターに tweet_mode='extended' と include_entities=True を追加すれば解決する。

```python
tweets = tweepy.Cursor(api.search, q=q).items(20)
```


```python
tweets = tweepy.Cursor(api.search, q=q, 
    # ここで、省略された部分を拡張する
    tweet_mode='extended', # 省略されたツイートを全て取得
    include_entities=True).items(20) # 省略されたリンクを全て取得
```


# 動画のURLの取得はできたが、エラー吐いてる。。

```
AttributeError: 'Status' object has no attribute 'text'
```


どうやら、tweet_mode を extended にすると、 ツイート文のキー名が text から full_text　になるよう。

```python
for tweet in tweets:
        # text →　full_text
        # print(tweet.text)
        print(tweet.full_text)
        print(tweet.extended_entities)
        try:
            media = tweet.extended_entities['media']
``` 

# 修正後のコード

```python:search_tweets.py
import os
import tweepy
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta

consumer_key = os.getenv('TWITTER_CONSUMER_KEY')
consumer_secret = os.getenv('TWITTER_CONSUMER_SECRET')
access_token = os.getenv('TWITTER_ACCESS_TOKEN')
access_token_secret = os.getenv('TWITTER_ACCESS_TOKEN_SECRET')
bearer_token = os.getenv('TWITTER_ACCESS_TOKEN_SECRET')


# twitter で松岡茉優関連のツイートを検索してURL取得
def search_tweets():
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    api = tweepy.API(auth)

    yesterday = datetime.strftime(datetime.today() - relativedelta(days=1), f"%Y-%m-%d")
    # リツイートを省く、いいね10以上、昨日〜今日、リツイート1以上、の画像と動画がある、の条件でtwitter検索
    q = f'#松岡茉優 OR 松岡茉優 filter:media exclude:retweets min_faves:10 since:{yesterday} min_retweets:1'

    # 問題となった部分
    tweets = tweepy.Cursor(api.search, q=q).items(20)

    contents = []
    for tweet in tweets:
        print(tweet.full_text)
        print(tweet.extended_entities)
        try:
            media = tweet.extended_entities['media']
            for m in media:
                print(m)
                preview = m['media_url_https']
                if m['type'] == 'video':
                    origin = [variant['url'] for variant in m['video_info']
                              ['variants'] if variant['content_type'] == 'video/mp4'][0]
                else:
                    origin = m['media_url_https']

                # LINE Bot で送信するために整形
                content = {'preview': preview, 'origin': origin, 'type': m['type']}
                contents.append(content)

            print('--------------------------------------------')
        except:
            print('Error')
            print('--------------------------------------------')
    return contents


if __name__ == "__main__":
    search_tweets()

```

# おわりに

松岡茉優ファン（通称まゆらー）であり、毎日 Twitter のタイムラインを確認する時間がなくなってきた私にとって、この LINE Bot は我得でしかないのですが、よろしければこの記事をご覧になっている方でもし松岡茉優ファンいましたら 下記 QRコードで友達登録してくださ〜い！！！

よろしくお願いします！！



![L.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569968/c9ce94f6-688d-4c24-625d-493f5f81dbe0.png)

あと、この記事で間違ってる部分とか、もっとこうしたほうがいいよ、とかありましたら、どんどんコメントしてください！！

## 参考記事
【Python】tweepyでTwitterのツイートを検索して取得
https://vatchlog.com/tweepy-search/
140文字以上のツイートを取得する
https://qiita.com/hitsumabushi845/items/f7fd87106381fc65fc86
Python + tweepyにて、Video URLを取得する
https://thinkami.hatenablog.com/entry/2017/11/02/062226