代码摘要:使用 YouTube API 并实现 OAuth 2.0 的脚本可以访问一个帐户,检索其喜欢的视频,并访问另一个帐户并使用该喜欢的视频列表在新帐户上喜欢它们。这看起来像是一个奇怪的项目,但我这周才开始使用 Python,这是我的第一个项目,它看起来很简单(我错了)
这是我代码的相关部分:
def likeVideos(videos,youtubeObject):
youtube = youtubeObject
videos = videos
numofVideosLiked = 0
numLikedVideos = 0
for video in videos:
numLikedVideos += 1
for video in videos:
newRequest = youtube.videos().getRating(
id=[video['id']]
)
newResponse = newRequest.execute()
if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
print(f"Already liked '{video['snippet']['title']}' or something went wrong...")
else:
likeRequest = youtube.videos().rate(
id=video['id'],
rating='like'
).execute()
numofVideosLiked += 1
print(f"Liking {video['snippet']['title']}...{numofVideosLiked}/{numLikedVideos}")
终端的输出显示我成功点赞了父账号的前194个视频,然后崩溃了:
Liking coding in c until my program is unsafe...191/354
Liking OVERDOSING ON TF2!!!...192/354
Liking JavaScript Fighting Game Tutorial with HTML Canvas...193/354
Liking DIY PCBs At Home (Single Sided Presensitized)...194/354
然而,孩子号只有30视频真正被点赞,并且是按5的随机间隔点赞的。 (具体来说,视频 1-5、31-35、68-72、106-110 等在第二个帐户上实际上 喜欢)我的理解是列表阅读是 5 组,所以你需要增加maxResults 参数就像我最初检索列表时所做的那样:
while True:
# Make API request
request = youtube.videos().list(
part='snippet',
myRating='like',
maxResults=50,
pageToken = next_page_token
)
response = request.execute()
# Add videos to list
videos += response['items']
next_page_token = response.get('nextPageToken')
if not next_page_token:
break
但是我不确定在实际调用 rate() 函数来喜欢视频时该怎么做,因为它的唯一参数是 id 和 rating.
我相信这个代码块是主要问题:
if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
print(f"Already liked '{video['snippet']['title']}' or something went wrong...")
else:
likeRequest = youtube.videos().rate(
id=video['id'],
rating='like'
).execute()
在某些视频已经被点赞并且点赞视频的方法似乎不准确后,当我多次运行脚本时,if 语句永远不会捕捉到已经被点赞的视频。
if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
只有在需要帮助解决我的问题时,才提供完整的源代码:
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import pickle
import os
# Make API request and build Youtube object
def getYoutubeObject(client_secret, path_to_pickled_file):
credentials = None
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl",
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/youtube.upload',
'https://www.googleapis.com/auth/youtubepartner',
'https://www.googleapis.com/auth/youtubepartner-channel-audit']
# path_to_pickled_file file stores user credentials
if os.path.exists(path_to_pickled_file):
print("Loading credentials of account from file...")
with open(path_to_pickled_file, 'rb') as token:
credentials = pickle.load(token)
# If there are no valid credentials, refresh token or log in
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
print("Refreshing access token for account...")
credentials.refresh(Request())
else:
print("Fetching new tokens for account...")
flow = InstalledAppFlow.from_client_secrets_file(
client_secret,
scopes=scopes
)
flow.run_local_server(
port=8080,
prompt="consent",
authorization_prompt_message=''
)
credentials = flow.credentials
# Save credentials for next use
with open(path_to_pickled_file, 'wb') as f:
print("Saving credentials of account for future use...")
pickle.dump(credentials, f)
api_name = 'youtube'
api_version = 'v3'
youtube = build(api_name, api_version, credentials=credentials)
return youtube
# Return list of liked videos
def getLikedVideos(youtubeObject):
youtube = youtubeObject
next_page_token = None
videos = []
# fields = "id, snippet(title)"
while True:
# Make API request
request = youtube.videos().list(
part='snippet',
myRating='like',
maxResults=50,
pageToken = next_page_token
)
response = request.execute()
# Add videos to list
videos += response['items']
next_page_token = response.get('nextPageToken')
if not next_page_token:
break
numLikedVideos = 0
for video in videos:
numLikedVideos += 1
print(f"You have {numLikedVideos} likes videos!")
input("Press Enter to continue...")
return videos
def likeVideos(videos,youtubeObject):
youtube = youtubeObject
videos = videos
numofVideosLiked = 0
numLikedVideos = 0
for video in videos:
numLikedVideos += 1
for video in videos:
newRequest = youtube.videos().getRating(
id=[video['id']]
)
newResponse = newRequest.execute()
if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
print(f"Already liked '{video['snippet']['title']}' or something went wrong...")
else:
likeRequest = youtube.videos().rate(
id=video['id'],
rating='like'
).execute()
numofVideosLiked += 1
print(f"Liking {video['snippet']['title']}...{numofVideosLiked}/{numLikedVideos}")
def main():
client_secret = 'client_secret.json'
path_to_pickled_file = 'token.pickle'
path_to_second_pickled_file = 'secondToken.pickle'
input("Press Enter to retrieve first Youtube object...")
youtube = getYoutubeObject(client_secret, path_to_pickled_file)
input("Press Enter to get liked videos...")
videos = getLikedVideos(youtube)
input("Press Enter to retrieve second Youtube object...")
newYtObj = getYoutubeObject(client_secret, path_to_second_pickled_file)
input("Press Enter to like videos...")
likeVideos(videos, newYtObj)
main()
我尝试使用 videos.rate 方法为列表(350 多个项目)中的所有视频点赞。但是,实际上只有 30 个最终被评分(从我喜欢的视频历史中按时间顺序排列的 5 个间隔。前 5 个被喜欢,然后 25 个视频之后它再次起作用并喜欢另外 5 个,等等)
使用
import time
,你可以像这样包含time.sleep(time_interval_in_seconds)
:
def likeVideos(videos,youtubeObject):
youtube = youtubeObject
videos = videos
numofVideosLiked = 0
numLikedVideos = 0
for video in videos:
numLikedVideos += 1
for video in videos:
newRequest = youtube.videos().getRating(
id=[video['id']]
)
newResponse = newRequest.execute()
if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
print(f"Already liked '{video['snippet']['title']}' or something went wrong...")
else:
likeRequest = youtube.videos().rate(
id=video['id'],
rating='like'
).execute()
numofVideosLiked += 1
print(f"Liking {video['snippet']['title']}...{numofVideosLiked}/{numLikedVideos}")
time.sleep(1.5)
问题不是代码。问题是 YouTube API 对您请求某些数据的速度有限制。