生成特定YouTube订阅的视频上传列表

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

Generating list of video uploads for a particular YouTube subscription

问题

以下是代码的翻译部分:

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.PlaylistItemListResponse;
import com.google.api.services.youtube.model.SubscriptionListResponse;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Collections;

public class ApiExample {
    private static final String CLIENT_SECRETS= "client_secret.json";
    private static final Collection<String> SCOPES =
            Collections.singletonList("https://www.googleapis.com/auth/youtube.readonly");

    private static final String APPLICATION_NAME = "Stack Overflow MRE";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    public static Credential authorize(final NetHttpTransport httpTransport) throws IOException {
        InputStream in = ApiExample.class.getResourceAsStream(CLIENT_SECRETS);
        GoogleClientSecrets clientSecrets =
                GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
        GoogleAuthorizationCodeFlow flow =
                new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
                        .build();
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
    }

    public static YouTube getService() throws GeneralSecurityException, IOException {
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        Credential credential = authorize(httpTransport);
        return new YouTube.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();
    }

    public static void main(String[] args)
            throws GeneralSecurityException, IOException {
        YouTube youtubeService = getService();
        YouTube.Subscriptions.List request = youtubeService.subscriptions()
                .list("snippet");
        SubscriptionListResponse response = request.setMine(true).setMaxResults(1L).execute();
        String channelId = response.getItems().get(0).getSnippet().getResourceId().getChannelId();

        YouTube.PlaylistItems.List playListRequest = youtubeService.playlistItems().list("snippet");
        PlaylistItemListResponse playlistResponse = playListRequest.setPlaylistId(channelId).execute();
        playlistResponse.getItems().forEach(System.out::println);
    }
}

这是您提供的代码的翻译部分,如果您有任何问题,请随时提问。

英文:

I am trying to generate a list of videos from a channel that I am subscribed to.

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.PlaylistItemListResponse;
import com.google.api.services.youtube.model.SubscriptionListResponse;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Collections;

public class ApiExample {
    private static final String CLIENT_SECRETS= &quot;client_secret.json&quot;;
    private static final Collection&lt;String&gt; SCOPES =
            Collections.singletonList(&quot;https://www.googleapis.com/auth/youtube.readonly&quot;);

    private static final String APPLICATION_NAME = &quot;Stack Overflow MRE&quot;;
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /**
     * Create an authorized Credential object.
     *
     * @return an authorized Credential object.
     * @throws IOException in the event that the client_secrets.json file is not found
     */
    public static Credential authorize(final NetHttpTransport httpTransport) throws IOException {
        // Load client secrets.
        InputStream in = ApiExample.class.getResourceAsStream(CLIENT_SECRETS);
        GoogleClientSecrets clientSecrets =
                GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow =
                new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
                        .build();
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize(&quot;user&quot;);
    }

    /**
     * Build and return an authorized API client service.
     *
     * @return an authorized API client service
     * @throws GeneralSecurityException, IOException
     */
    public static YouTube getService() throws GeneralSecurityException, IOException {
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        Credential credential = authorize(httpTransport);
        return new YouTube.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();
    }

    /**
     * Call function to create API service object. Define and
     * execute API request. Print API response.
     *
     * @throws GeneralSecurityException, IOException, GoogleJsonResponseException
     */
    public static void main(String[] args)
            throws GeneralSecurityException, IOException {
        YouTube youtubeService = getService();
        // Define and execute the API request
        YouTube.Subscriptions.List request = youtubeService.subscriptions()
                .list(&quot;snippet&quot;);
        SubscriptionListResponse response = request.setMine(true).setMaxResults(1L).execute();
        String channelId = response.getItems().get(0).getSnippet().getResourceId().getChannelId();

        YouTube.PlaylistItems.List playListRequest = youtubeService.playlistItems().list(&quot;snippet&quot;);
        PlaylistItemListResponse playlistResponse = playListRequest.setPlaylistId(channelId).execute();
        playlistResponse.getItems().forEach(System.out::println);
    }
}

I have read YouTube API to fetch all videos on a channel, however my question is a little different because I am trying to get the list of videos from a Subscription, rather than from a Channel.

I attempted to isolate the Channel ID in order to follow the instructions in the video from Google Developers about how to do this. I used String channelId = response.getItems().get(0).getSnippet().getResourceId().getChannelId();

However, when I run the above code, which should print out a list of videos from that Channel in JSON notation, I see this error instead:

Exception in thread &quot;main&quot; com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
&quot;code&quot; : 404,
&quot;errors&quot; : [ {
&quot;domain&quot; : &quot;youtube.playlistItem&quot;,
&quot;location&quot; : &quot;playlistId&quot;,
&quot;locationType&quot; : &quot;parameter&quot;,
&quot;message&quot; : &quot;The playlist identified with the request&#39;s &lt;code&gt;playlistId&lt;/code&gt; parameter cannot be found.&quot;,
&quot;reason&quot; : &quot;playlistNotFound&quot;
} ],
&quot;message&quot; : &quot;The playlist identified with the request&#39;s &lt;code&gt;playlistId&lt;/code&gt; parameter cannot be found.&quot;
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1067)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at ApiExample.main(ApiExample.java:93)

Evidently, I have not correctly isolated the Channel ID, or else I have misunderstood the video. What is the correct way to get the videos from a YouTube subscription?

Edit

The following change in my main method worked:

public static void main(String[] args)
            throws GeneralSecurityException, IOException {
    YouTube youtubeService = getService();
    // Define and execute the API request
    YouTube.Subscriptions.List request = youtubeService.subscriptions()
            .list(&quot;snippet&quot;)
    SubscriptionListResponse response = request.setMine(true).setMaxResults(1L).execute();
    String channelId = response.getItems().get(0).getSnippet().getResourceId().getChannelId();

    YouTube.Channels.List channelRequest = youtubeService.channels().list(&quot;contentDetails&quot;);
    ChannelListResponse channelResponse = channelRequest.setId(channelId).execute();
    String playListID = channelResponse.getItems().get(0).getContentDetails().getRelatedPlaylists().getUploads();

    YouTube.PlaylistItems.List playListRequest = youtubeService.playlistItems().list(&quot;snippet&quot;);
    PlaylistItemListResponse playlistResponse = playListRequest.setPlaylistId(playListID).execute();
    playlistResponse.getItems().forEach(System.out::println);
}

答案1

得分: 3

问题出在您上面的代码中,归结为以下文档条目:

playlistId(字符串)

playlistId参数指定要检索播放列表项的播放列表的唯一ID。请注意,即使这是一个可选参数,检索播放列表项的每个请求都必须为id参数或playlistId参数之一指定一个值。

现在应该明白了:playlistId是播放列表的ID,因此不能是频道的ID。

但是要列出特定频道(通过其ID标识)的所有已上传视频,需要执行以下操作:

调用带有参数playlistId设置为该频道上传播放列表的ID的PlaylistItems.list API端点。

可以通过调用带有参数id设置为您的频道ID的Channels.list端点来轻松获取后者的ID。

然后可以在端点的JSON响应中找到上传播放列表ID,作为以下属性的值:

items[0].contentDetails.relatedPlaylists.uploads

转换为Java代码,此属性路径将变为以下一系列getter链,最终以getUploads结束:

.getItems().get(0).getContentDetails().getRelatedPlaylists().getUploads()

请注意,对于给定的频道,您只需要获取一次上传播放列表ID,然后随意使用它。

通常,频道ID及其对应的上传播放列表ID由s/^UC([0-9a-zA-Z_-]{22})$/UU\1/关联起来。

英文:

The problem with your code above boils down to the following doc entry:

> playlistId (string)
>
> The playlistId parameter specifies the unique ID of the playlist for which you want to retrieve playlist items. Note that even though this is an optional parameter, every request to retrieve playlist items must specify a value for either the id parameter or the playlistId parameter.

Things should come into light by now: playlistId is the ID of a playlist, hence cannot be the ID of a channel.

But for listing all uploaded videos of a given channel (identified by its ID), one has to do the following:

Invoke the PlaylistItems.list API endpoint queried with the parameter playlistId set to the ID of that channel's uploads playlist.

This latter ID may very easily be obtained by invoking the Channels.list endpoint queried with the parameter id set to your channel's ID.

The uploads playlist ID is then to be found within the endpoint's JSON response as value of the property:

items[0].contentDetails.relatedPlaylists.uploads.

Translated to Java, this property path would become the following chain of getters, ending with getUploads:

.getItems().get(0).getContentDetails().getRelatedPlaylists().getUploads().

Note that for a given channel, you need to obtain the uploads playlist ID only once, then use it as many times as you wish.

Usually, a channel ID and its corresponding uploads playlist ID are related by s/^UC([0-9a-zA-Z_-]{22})$/UU\1/.

huangapple
  • 本文由 发表于 2020年10月1日 01:06:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/64142472.html
匿名

发表评论

匿名网友

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

确定