はじめに
毎週複数の同じ検索ワードで検索しては、再生リストに追加してYoutube動画を見ていました。
それが面倒になり、自動化できないかプログラミングしてみました。
環境
- python 3.9.7
- vscode
- youtube api v3
- windows 10
仕様
- 7日以内にアップロードされた動画を対象とする
- 各検索ワードに対して、関連度が高い1つの動画を再生リストに追加する
- すでに再生リストに含まれる動画は重複しないようにする
- APIの認証の通し方はhttps://dev.classmethod.jp/articles/oauth2-youtube-data-api/ を参考にした
流れ
- youtubeの認証を通す
- 7日前の日付を取得する
- 検索ワードで検索結果を取得する
- すでに再生リストに含まれるかチェックする
- 検索された動画を再生リストに追加する
つまづいたところ
- oauth2clientが非推奨のためか、利用できなかった
- CLIENT_SECRETS_FILEは、実行ファイルと同じディレクトリに入れておく
- 検索結果を出す個数はmaxResultsで指定する。
- 今回の場合、1個にした。
コード
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
API_SERVICE_NAME = "youtube"
API_VERSION = "v3"
SCOPES = ["https://www.googleapis.com/auth/youtube"]
CLIENT_SECRETS_FILE = 'client_secret_no_fairu_namae.json'
PLAYLIST_ID = "Pureirisuto no id dayo"
KEYWORD_ARRAY =[]
KEYWORD_ARRAY.append('乃木坂')
KEYWORD_ARRAY.append('日向坂')
KEYWORD_ARRAY.append('櫻坂')
# https://dev.classmethod.jp/articles/oauth2client-is-deprecated/ より引用
def get_authenticated_service():
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRETS_FILE, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return build(API_SERVICE_NAME, API_VERSION, credentials=creds)
def searchVideosByKeywords(youtube,keywords,strLastWeek):
videoIdArray = []
for keyword in keywords:
searchResponse = youtube.search().list(
q=keyword,part='snippet',
type='video',
regionCode='jp',
maxResults=1,
publishedAfter=strLastWeek,
).execute()
sr = searchResponse['items'][0]
snippetInfo = sr['snippet']
title = snippetInfo['title']
channelTitle = snippetInfo['channelTitle']
videoIdArray.append(sr['id']['videoId'])
return videoIdArray
def insertVideosIntoPlaylist(youtube,playlistItem_list_response,videoIdArray):
videoAlready = []
for item in playlistItem_list_response["items"]:
videoAlready.append(item["snippet"]["resourceId"]["videoId"])
for id in videoIdArray:
if id not in videoAlready:
playlistItem_insert_response = youtube.playlistItems().insert(
part="snippet,status",
body=dict(
snippet=dict(
playlistId=PLAYLIST_ID,
resourceId=dict(
videoId=id,
kind="youtube#video",
)
)
)
).execute()
def main():
youtube = get_authenticated_service()
dtNow = datetime.datetime.now()
dtLastWeek = dtNow - datetime.timedelta(days=7)
strLastWeek = dtLastWeek.strftime(f'%Y-%m-%dT%H:%M:%SZ')
videoIdArray = searchVideosByKeywords(youtube,KEYWORD_ARRAY,strLastWeek)
playlistItem_list_response = youtube.playlistItems().list(
part="snippet",
playlistId=PLAYLIST_ID,
maxResults = 50,
).execute()
insertVideosIntoPlaylist(youtube,playlistItem_list_response,videoIdArray)
print("done")
if __name__ == "__main__":
main()
終わりに
これで、動画の収集がはかどりますね!