YouTube API的videos.rate方法只能为一些视频评分。

huangapple go评论65阅读模式
英文:

YouTube API videos.rate method only rates some 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=]
        )

        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}")

如果您需要进一步的帮助,请随时提出您的问题。

英文:

Code summary: Script that uses YouTube API and implements OAuth 2.0 to get access to one account, retrieve its liked videos, and get access to another account and use that list of liked videos to like them on the new account. It may seem like a weird project but I just started using Python this week and this is my first project and it seemed easy enough (I was wrong)

This is the relevant part of my code:

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=]
        )

        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}")

The output in the terminal indicated that I successfully liked my first 194 videos from the parent account before it broke down:

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

However, the child account only had 30 videos actually liked, and they were done in random intervals of 5. (To be specific, videos 1-5, 31-35, 68-72, 106-110, etc were actually liked on the second account) My understanding is that reading from lists is in groups of 5 so you need to increase the maxResults parameter like I did here when retrieving the list initially:

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

But I am not sure what to do when actually calling the rate() function to like the videos because its only parameters are id and rating.

I believe this code block is the main problem:

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()

The if statement never catches already-liked videos when I run the script multiple times after some videos were already liked and the method of liking the videos doesn't seem to be accurate.

  • Is it possible Youtube limits how fast you can like videos? Is there a workaround?
  • What is a better way to check if the videos are already liked other than this code snippet?: if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):

Here is the full source code only if it's necessary to help with my question:

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=]
        )

        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()

I tried liking all videos within a list (350+ items) using the videos.rate method. But, only 30 ended up actually being rated (In intervals of 5 chronologically from my liked video history. The first 5 were liked, then 25 videos later it worked again and liked 5 more, etc)

答案1

得分: 2

使用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=]
        )

        newResponse = newRequest.execute()

        if 'rating' in newResponse and (newResponse['rating'] == 'like' or newResponse['rating'] == 'unspecified'):
            print(f"已经喜欢 '{video['snippet']['title']}' 或发生了错误...")
        else:
            likeRequest = youtube.videos().rate(
                id=video['id'],
                rating='like'
            ).execute()

            numofVideosLiked += 1
            print(f"喜欢 {video['snippet']['title']}...{numofVideosLiked}/{numLikedVideos}")
            time.sleep(1.5)

问题不在于代码,而在于YouTube API 对于请求某些数据的速度限制。

英文:

Using import time, you can include time.sleep(time_interval_in_seconds) like such:

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=]
        )

        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)

The issue is not the code. The issue is the limit the YouTube API has on how fast you can request certain data.

huangapple
  • 本文由 发表于 2023年3月9日 14:50:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75681277.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定