あきゆりのぶろぐ

SixTONESを中心にJr.への愛を叫ぶ

ISLAND TV更新通知botの作り方(考え方)

 今回はオタクブログにはふさわしくない技術屋としての話になるが、できる限りITに見識が薄い人でも読めるように噛み砕いて、2019年3月4日から4月19日に私が何をして、ISLAND TVの更新通知botを作っていたのか説明していく。

 

 事の発端は

この自分のツイートである。最初はほんの思いつきだった。

 ここから16時間後、

ツイート機能以外はほぼ完成まで持ってくることに成功した。

 

 まずはここまでにやったことをざっくり説明していこうと思う。

 

0、プログラミング

 使用言語はPythonスクレイピングにはBeautifulsoup4というライブラリ(ツールのようなもの)を使用した。詳しい仕組みについては後述。ちなみにスクレイピングとは「ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと」(出典:Wikipedia)である。ISLAND TVの動画にはURLの末尾に必ず数字のIDが付いているので、これを利用して新しいIDの動画がアップロードされているのか確認したのである。

 

1、Googleアカウント取得

 メールアドレスが後述の作業を行うためには必要であり、諸般のセキュリティリスクを考えると現在使用中のものと兼用は考えられなかったので、新規取得した。

 

2、Herokuアカウント取得

 書いたプログラムを定期的に実行するためのクラウドサーバ。最小単位が10分に一度の実行だったので、後半は一日一回プログラムを起動して、プログラム内で時間を調整して30秒に一回程度の新規アップロードチェックを可能にした。

 

3、Twitterアカウント取得

 今回の最終目的がTwitterで、最速で新規アップロード動画をツイートすることだったので、専用アカウントを開設。また、プログラムを通してツイートを行うためにはTwitter APIというものの申請(英語)が必要だったので、こちらも併せて申請を行う。今回の場合は12時間も経たずに申請許可が降りた。

 

 以上を3月4日に行ってプロトタイプを完成させたのちに、アップデートを重ね、公式の更新通知アカウントが出現するまで(4月19日)最速を目指して、主にプログラムの改定を行っていた。

 

 以下に最終版のコメントを入れたコードを記す。コード読むのだるい人はオレンジの文字で書いてある日本語のコメントを見てほしい。

 

# -*- coding: utf-8 -*-

import json, config

from requests_oauthlib import OAuth1Session

import smtplibfrom email.mime.text

import MIMETextfrom email.utils

import formatdateimport time

import sysimport urllib

from bs4 import BeautifulSoup


#動画サイト更新確認スクレイピング&ツイートプログラム

#author: Akiyuri

#create date: 2019-03-04

 
#Twitter二段階認証情報をconfigファイルから取得

CK = config.CONSUMER_KEY

CS = config.CONSUMER_SECRET

AT = config.ACCESS_TOKEN

ATS = config.ACCESS_TOKEN_SECRET

#Twitterにログイン

twitter = OAuth1Session(CK, CS, AT, ATS)


#Tweet関数

def tweet(msg):

     url = "https://api.twitter.com/1.1/statuses/update.json"

     #ツイートテキストをセット

     params = {"status" : msg}

 

  #postリクエスト送信=ツイート

     res = twitter.post(url, params = params) 

 

  if res.status_code == 200: #ツイート成功ログ

          print("Success.")

     else: #ツイート失敗ログ

          print("Failed. : %d"% res.status_code)

 

#新着動画検索パート
url = "https://j-island.net/movie/play/id/"

lastId = 0

beforeLast = 0

idList = []


#1分ごとに毎日18時間と少し稼働させたい:60/1 * 18 + 10 = 490

for i in range(490): 


    #現在ID9以上の動画が存在している

    movieId = 1

 

    #抜け番も5つ程度現時点で存在する、発見のたびに加算

    movieNotFound = 0

 

    #20以上抜け番(動画未アップロード)を確認したらその時間の確認を終了

    while movieNotFound < 20:

 

       #スクレイピングURL生成

       movieUrl = url + str(movieId)

       #スクレイピング開始       

       html = urllib.urlopen(movieUrl)

       soup = BeautifulSoup(html)

       pageTitle = "ISLAND TV"

 

       #稀に通信エラーでページ読み込みが間に合わない事例があるが、無視する

       if soup.find("title") is None:

    pass

  else:

              #日本語標準出力はACIIと認識されてしまうのでエンコード

              #タイトル文字化け対策

              pageTitle = soup.find("title").text.encode('utf-8')

 

              #動画ページが正式に存在するID

              #動画が存在しないページのタイトルが[ISLAND TV]

              if pageTitle != "ISLAND TV"

                  #動画のタイトル取得

                  movieTitle = soup.find("div", attrs={'class': 'movieplay-infomation__title-title'}).text.encode('utf-8')

 

            #一度めのループで生成したIDリストに存在=ツイート済み動画

            if movieId in idList:

                   #もうこの動画はツイートした古い動画だから無視

                   print str("True because old movie id is " + str(movieId))

                   pass

 

            #初回ループ or 初回ループで生成したIDリストに存在しない

            else:

                   #新しい動画だ!ツイートだ!

                   print str("False because new movie id is " + str(movieId))

                   print str(movieId) + ":" + str(movieTitle) + ":" + movieUrl

 

            #初回ループではなく、初回ループで生成したIDリストに存在しない=新着動画

            if i != 0:

                  #Tweet処理

                  tweetMsg = movieTitle + " " + movieUrl tweet(tweetMsg)

 

            #初回ループ

            else:

                  print "already tweet!"

            BODY += str(movieId)

    idList.append(movieId)

            lastId = movieId

 

      #動画ページが存在しないID

      else:

            movieNotFound += 1

            pass

      movieId += 1

 

      #サーバ攻撃とみなされないためにスリープ

      time.sleep(1)

 

      #とりあえず最後の動画IDまでこの時間帯の確認を終えたよメッセージ 

      print u"end of check. time is " + str(i) + ". Last Id is " + str(lastId)

     #1分スリープ

     time.sleep(60)

 

#1日分の処理を終了した時に出力 

print u"Ploglam is over. Please run next time."

 

 以上を毎日午前7時に起動して、午前0時過ぎまで稼働させていた。

 読んでくださった方はお分かりかと思うが、最終的には約1分に一回更新を確認できるように調整していた。

 

 公式の更新通知ができてからは、フォロワーを全解除し、自分用に眺めるためにアカウントは使っていたが、この度凍結したので正式にこのプロジェクトは終了である。

 

 初期はバグや事故(1分で100ツイートとか自動化の数値を間違えてやらかした)が多く、見守ってくださった方にはハラハラさせてしまったが、最後の方には安定稼働となっていたので、自身の技術に自信を持つきっかけとなった一件だった。

 

 当時を見守って、応援してくださった方全てに心より御礼申し上げます。

 

 

 

 

 

 

 

 実はこのプログラムというかbotを構成したことが評価されて、転職先が決まったので、人生は偶然だし、わからないことの連続を乗り越えて連関していくと実感している。

 ものづくりって楽しいんだよ、と伝える仕事をこの夏から始める。


ジャニーズJr.ランキング

 にほんブログ村 芸能ブログ ジャニーズJr.へ
にほんブログ村