よくわからないエンジニア

よく分からないエンジニアの日々の記録

よくわからないエンジニア

Twitterで特定ユーザーのgif動画を取得する ※berryjack改良

突然ですが海外に行ってました。
ブログの更新が滞りましたが、5月は先行して記事書いてたので良しとします。
それはさておき、以前に作ったバファローズポンタのスクリプトですが、動画だった場合にメディアファイルを落とせないことに気がついたので、改良します。

www.unknownengineer.net

目次

事の発端

ポンタからのつぶやきを心待ちにしている我が友人からLINEでメッセージが届く。

「試合が終わったのにポンタ画像が届かない」

確認してみると、試合終了から時間がだいぶ経過しているのに、試合結果もポンタの勝敗画像も届いていない。過去に何度かプロセスを落としていたせいで通知が来なかった事があったので、サーバにログインしてみたが、該当プロセスは問題なく動いている。
そもそも、お前が人力で監視しているのにこの機能は本当に必要なのだろうか?と存在意義に疑問を持った所で、原因が判明した。
その日のバファローズポンタのつぶやきは画像ではなく動画だった。
原因は分かったので、とりあえず対策してみる事にした。

berryjackの挙動を確認

まずはberryjackの挙動が分からないと失敗の理由が分からないので、大人しくシェルスクリプトを見ながら、挙動を確認する。
今回使っていない箇所は省きます。画像ファイルのURLを取得しているのはberryjackのget_media_url関数のようです。見やすいようにバラします。

# Get posted media
function get_media_url()
{
  id=$1
  orig=$2
  cookie_opt=
  if [ "$3" != "" ]; then
    cookie_opt="--keep-session-cookies --load-cookies $3"
  fi
  dir=$4
  force=$5
  tmp=/tmp/$$.media
  param=
  cxt_id_prev=

ここまでは引数受取だけだから無視。

  while :; do
    skip=0
    url="https://twitter.com/i/profiles/show/$id/media_timeline$param"
    wget $cookie_opt -O - -q "$url" | escape | decode > $tmp

ここの処理でjsonを取得して、整形している模様。escapeとdecodeはcommon.shで定義している関数。中身は以下。

# Decode Unicode escaped string to UTF-8 string
function decode()
{
  sed -e 's/\\u\(....\)/\&#x\1;/g' | nkf --numchar-input
}
export -f decode

# Escape charactor
function escape()
{
  sed -e 's/\\"/"/g' -e 's/\\\//\//g' -e 's/\\n/\n/g'
}
export -f escape

実際にwgetでjsonを取得してみる。

# wget -O - -q https://twitter.com/i/profiles/show/bs_ponta/media_timeline | sed -e 's/\\"/"/g' -e 's/\\\//\//g' -e 's/\\n/\n/g' | sed -e 's/\\u\(....\)/\&#x\1;/g' | nkf --numchar-input > /tmp/test.media
# cat /tmp/test.media
<中略>
        <div class="js-tweet-text-container">
  <p class="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text" lang="ja" data-aria-label-part="0">見据えるのは、勝利qqq。
 <a href="/hashtag/bs2017?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>bs2017</b></a> <a href="/hashtag/NPB?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>NPB</b></a> <a href="/hashtag/%E3%82%AA%E3%83%AA%E3%83%83%E3%82%AF%E3%82%B9?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>オリック
ス</b></a> <a href="/hashtag/%E3%83%90%E3%83%95%E3%82%A1%E3%83%AD%E3%83%BC%E3%82%BA?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>バファローズ</b></a> <a href="/hashtag/%E3%83%90%E3%83%95%E3%82%A1%E3%83%AD%E3%83%BC%E3%82%BA%E3%83%9D%E3%83%B3%E3%82%BF?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>バファローズポンタ</b></a><a href="https://t.co/7xY7Ty5KDy" class="twitter-timeline-link u-hidden" data-pre-embedded="true" dir="ltr" >pic.twitter.com/7xY7Ty5KDy</a></p>
</div>





            <div class="AdaptiveMediaOuterContainer">
    <div class="AdaptiveMedia


        is-square



        "
      >
      <div class="AdaptiveMedia-container">
          <div class="AdaptiveMedia-singlePhoto">
    <div class="AdaptiveMedia-photoContainer js-adaptive-photo "
  data-image-url="https://pbs.twimg.com/media/DBXxhK5UIAEXNZy.jpg"


  data-element-context="platform_photo_card">
  <img data-aria-label-part src="https://pbs.twimg.com/media/DBXxhK5UIAEXNZy.jpg" alt=""
>
</div>


</div>


      </div>
    </div>
  </div>

おお、扱いやすそうですね。

問題点

で、ここからが問題点のようですね。

    # video
    for line in $(grep 'middot' $tmp | sed -e 's/.*href="//g' -e 's/".*$//g')
    do
      stat=$(echo "$line" | cut -d'/' -f3)
      vcurl="https://twitter.com/i/videos/$stat"
      video=$(wget $cooke_opt -q -O - $vcurl | escape | decode | grep -Eo 'https://video[^&]*')
      exist "$dir" "$video"
      # if [ $? -ne 0 ]; then
      #   skip=1
      # fi
    done

berryjack自体には元々videoに対応しているようですが、twitterの実装が変わってこのままでは動かない模様。
このままだとfor文の条件に入らず、mp4の取得に至らないですね。
動画の場合に必要な情報は以下の部分ですね。

style="padding-bottom: 55.55555555555556%; background-image:url('https://pbs.twimg.com/tweet_video_thumb/DBUfJ1ZUMAEzDAG.jpg')">

なのでまずはこの箇所の情報を整形したjsonファイルから抜き出します。

#grep -Eo 'https://pbs\.twimg\.com/tweet_video_thumb/[a-zA-Z0-9_\-]+\.(jpg|png)' $tmp | sort | uniq
https://pbs.twimg.com/tweet_video_thumb/DBUfJ1ZUMAEzDAG.jpg
https://pbs.twimg.com/tweet_video_thumb/DBEwLOcUMAAeyUe.jpg

しかしこのままだと画像しか取得できません。メディアファイルのIDを取得したら、これを動画の保存先に向くように置換します。uniqの後ろにパイプで以下を繋げます。

sed -e "s/pbs.twimg.com\/tweet_video_thumb/video.twimg.com\/tweet_video/" |sed -e "s/jpg/mp4/"

これで動画のURLを取得出来ました。後はスクリプトの形式をあわせます。

    # video
    for video in $(grep -Eo 'https://pbs\.twimg\.com/tweet_video_thumb/[a-zA-Z0-9_\-]+\.(jpg|png)' $tmp |sort |uniq |sed -e "s/pbs.twimg.com\/tweet_video_thumb/video.twimg.com\/tweet_video/" |sed -e "s/jpg/mp4/")
    do
      exist "$dir" "$video"
    done

これでとりあえずgif動画は拾えるようになりました。
git見たら未解決になってるから、pullリクエスト送ったら承認してくれるかなぁ?

残りの課題

これでとりあえず動画は取得出来ますが、残念ながらline notifyでは動画が投稿出来ません。
なので少し面倒ではありますが、おとなしくLINE BOTでも作ろうと思います。それでは。