チャンネル上のすべての動画を取得するYouTubeAPI

217
Rajendra Dewani 2013-09-23 21:07.

YouTubeのチャンネル名別のビデオリストが必要です(APIを使用)。

以下のAPIを使用して、チャネルリスト(チャネル名のみ)を取得できます。

https://gdata.youtube.com/feeds/api/channels?v=2&q=tendulkar

以下はチャンネルの直接リンクです

https://www.youtube.com/channel/UCqAEtEr0A0Eo2IVcuWBfB9g

または

WWW.YouTube.com/channel/HC-8jgBP-4rlI

ここで、チャンネル>> UCqAEtEr0A0Eo2IVcuWBfB9gまたはHC-8jgBP-4rlIのビデオが必要です。

やってみた

https://gdata.youtube.com/feeds/api/videos?v=2&uploader=partner&User=UC7Xayrf2k0NZiz3S04WuDNQ https://gdata.youtube.com/feeds/api/videos?v=2&uploader=partner&q=UC7Xayrf2k0NZiz3S04WuDNQ

しかし、それは役に立ちません。

チャンネルに投稿されたすべての動画が必要です。チャンネルにアップロードされた動画は複数のユーザーからのものである可能性があるため、ユーザーパラメータを指定しても効果はないと思います...

13 answers

222
akshay 2013-12-27 20:00.

YouTube DataAPIを確認する必要があります。APIへのアクセス方法に関するドキュメントがあります。クライアントライブラリもあります。

自分でリクエストすることもできます。チャンネルから最新の動画を取得するURLの例を次に示します。

https://www.googleapis.com/youtube/v3/search?key={your_key_here}&channelId={channel_id_here}&part=snippet,id&order=date&maxResults=20

その後、JSONビデオIDと詳細が記載されたを受け取り、次のようにビデオURLを作成できます。

http://www.youtube.com/watch?v={video_id_here}
131
jambrose 2015-01-10 16:27.

まず、ユーザー/チャンネルからのアップロードを表すプレイリストのIDを取得する必要があります。

https://developers.google.com/youtube/v3/docs/channels/list#try-it

forUsername={username}paramを使用してユーザー名を指定mine=trueするか、独自のユーザー名を取得するように指定できます(最初に認証する必要があります)。part=contentDetailsプレイリストを表示するには、インクルードします。

GET https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername=jambrose42&key={YOUR_API_KEY}

結果"relatedPlaylists"には"likes""uploads"プレイリストが含まれます。その"upload"プレイリストIDを取得します。また、"id"は将来の参照用にチャネルIDであることに注意してください。

次に、その再生リスト内のビデオのリストを取得します。

https://developers.google.com/youtube/v3/docs/playlistItems/list#try-it

プレイリストIDをドロップするだけです!

GET https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&maxResults=50&playlistId=UUpRmvjdu3ixew5ahydZ67uA&key={YOUR_API_KEY}

92
virtualmic 2016-04-04 05:33.

これは、YouTubeAPIのチャンネル内のすべての動画を一覧表示する方法を示すGoogleDevelopersの動画v3です。

2つのステップがあります:

  1. チャネルをクエリして「アップロード」IDを取得します。例えばhttps://www.googleapis.com/youtube/v3/channels?id={channel Id}&key={API key}&part=contentDetails

  2. この「アップロード」IDを使用してPlaylistItemsにクエリを実行し、動画のリストを取得します。例えばhttps://www.googleapis.com/youtube/v3/playlistItems?playlistId={"uploads" Id}&key={API key}&part=snippet&maxResults=50

35
iOS 2019-03-20 02:50.

チャンネルリストを取得するには:

forUserNameでチャンネルリストを取得

https://www.googleapis.com/youtube/v3/channels?part=snippet,contentDetails,statistics&forUsername=Apple&key=

チャネルIDでチャネルリストを取得します。

https://www.googleapis.com/youtube/v3/channels/?part=snippet,contentDetails,statistics&id=UCE_M8A5yxnLfW0KghEeajjw&key=

チャネルセクションを取得します。

https://www.googleapis.com/youtube/v3/channelSections?part=snippet,contentDetails&channelId=UCE_M8A5yxnLfW0KghEeajjw&key=

プレイリストを取得するには:

チャンネルIDで再生リストを取得:

https://www.googleapis.com/youtube/v3/playlists?part=snippet,contentDetails&channelId=UCq-Fj5jknLsUf-MWSy4_brA&maxResults=50&key=

pageTokenを使用してチャンネルIDでプレイリストを取得します

https://www.googleapis.com/youtube/v3/playlists?part=snippet,contentDetails&channelId=UCq-Fj5jknLsUf-MWSy4_brA&maxResults=50&key=&pageToken = CDIQAA

プレイリストアイテムを取得するには:

PlayListIdでPlaylistItemsリストを取得します。

https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=25&playlistId=PLHFlHpPjgk70Yv3kxQvkDEO5n5tMQia5I&key=

ビデオを入手するには:

ビデオIDでビデオリストを取得します:

https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=YxLCwfA1cLw&key=

複数の動画IDで動画リストを取得:

https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=YxLCwfA1cLw,Qgy6LaO3SB0,7yPJXGO2Dcw&key=

コメントリストを取得する

ビデオIDでコメントリストを取得:

https://www.googleapis.com/youtube/v3/commentThreads?part=snippet,replies&videoId=el **** kQak&key = A ********** k

チャネルIDごとにコメントリストを取得します

https://www.googleapis.com/youtube/v3/commentThreads?part=snippet,replies&channelId=U ***** Q&key = AI ******** k

allThreadsRelatedToChannelIdによるコメントリストの取得:

https://www.googleapis.com/youtube/v3/commentThreads?part=snippet,replies&allThreadsRelatedToChannelId=UC ***** ntcQ&key = AI ***** k

ここでは、すべてのAPIがGetアプローチです。

チャンネルIDに基づいて、すべての動画を直接取得するわけではありません。これが重要なポイントです。

統合の場合https://developers.google.com/youtube/v3/quickstart/ios?ver=swift

11
Stian 2017-11-15 06:32.

以下は、特別なパッケージを必要としないPythonの代替手段です。チャネルIDを指定すると、そのチャネルのビデオリンクのリストが返されます。それが機能するためにはAPIキーが必要であることに注意してください。

import urllib
import json

def get_all_video_in_channel(channel_id):
    api_key = YOUR API KEY

    base_video_url = 'https://www.youtube.com/watch?v='
    base_search_url = 'https://www.googleapis.com/youtube/v3/search?'

    first_url = base_search_url+'key={}&channelId={}&part=snippet,id&order=date&maxResults=25'.format(api_key, channel_id)

    video_links = []
    url = first_url
    while True:
        inp = urllib.urlopen(url)
        resp = json.load(inp)

        for i in resp['items']:
            if i['id']['kind'] == "youtube#video":
                video_links.append(base_video_url + i['id']['videoId'])

        try:
            next_page_token = resp['nextPageToken']
            url = first_url + '&pageToken={}'.format(next_page_token)
        except:
            break
    return video_links
8
Mihir Bhatt 2017-01-18 23:42.

チャンネルの下にあるすべての動画IDを返すコードは次のとおりです

<?php 
    $baseUrl = 'https://www.googleapis.com/youtube/v3/';
    // https://developers.google.com/youtube/v3/getting-started
    $apiKey = 'API_KEY';
    // If you don't know the channel ID see below
    $channelId = 'CHANNEL_ID';

    $params = [
        'id'=> $channelId,
        'part'=> 'contentDetails',
        'key'=> $apiKey
    ];
    $url = $baseUrl . 'channels?' . http_build_query($params);
    $json = json_decode(file_get_contents($url), true);

    $playlist = $json['items'][0]['contentDetails']['relatedPlaylists']['uploads'];

    $params = [
        'part'=> 'snippet',
        'playlistId' => $playlist,
        'maxResults'=> '50',
        'key'=> $apiKey
    ];
    $url = $baseUrl . 'playlistItems?' . http_build_query($params);
    $json = json_decode(file_get_contents($url), true);

    $videos = [];
    foreach($json['items'] as $video)
        $videos[] = $video['snippet']['resourceId']['videoId'];

    while(isset($json['nextPageToken'])){
        $nextUrl = $url . '&pageToken=' . $json['nextPageToken'];
        $json = json_decode(file_get_contents($nextUrl), true);
        foreach($json['items'] as $video)
            $videos[] = $video['snippet']['resourceId']['videoId'];
    }
    print_r($videos);

:ログイン後、https://www.youtube.com/account_advancedでチャンネルIDを取得でき ます。

7
sacred 2015-07-29 05:19.

たった3つのステップで:

  1. サブスクリプション:リスト-> https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&maxResults=50&mine=true&access_token= {oauth_token}

  2. チャンネル:リスト-> https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id= {channel_id}&key = {YOUR_API_KEY}

  3. プレイリストアイテム:リスト-> https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId= {playlist_id}&key = {YOUR_API_KEY}

6
Nagaraja 2014-01-28 01:12.

次のようにしてみてください。それはあなたを助けるかもしれません。

https://gdata.youtube.com/feeds/api/videos?author=cnn&v=2&orderby=updated&alt=jsonc&q=news

ここでは、チャンネル名を指定できる著者と、検索キーワードを指定できる「q」を指定します。

6
Nikhil VJ 2017-12-14 08:52.

ここや他の場所で共有されている参考資料のおかげで、チャンネルのすべての動画を取得するために使用できるオンラインスクリプト/ツールを作成しました。

それはへのAPI呼び出しを組み合わせましたyoutube.channels.listplaylistItemsvideos。再帰関数を使用して、有効な応答を取得すると、非同期コールバックが次の反復を実行するようにします。

これは、一度に行われるリクエストの実際の数を制限するのにも役立ちます。そのため、YouTubeAPIルールに違反することを防ぎます。短縮されたスニペットと完全なコードへのリンクを共有します。次の50件の結果をフェッチするために、応答に含まれるnextPageToken値を使用することで、呼び出しあたり最大50件の結果を取得しました。

function getVideos(nextPageToken, vidsDone, params) {
    $.getJSON("https://www.googleapis.com/youtube/v3/playlistItems", {
        key: params.accessKey,
        part: "snippet",
        maxResults: 50,
        playlistId: params.playlistId,
        fields: "items(snippet(publishedAt, resourceId/videoId, title)), nextPageToken",
        pageToken: ( nextPageToken || '')
        },
        function(data) {
            // commands to process JSON variable, extract the 50 videos info

            if ( vidsDone < params.vidslimit) {

                // Recursive: the function is calling itself if
                // all videos haven't been loaded yet
                getVideos( data.nextPageToken, vidsDone, params);

            }
             else {
                 // Closing actions to do once we have listed the videos needed.
             }
    });
}

これにより、ID、タイトル、公開日など、ビデオの基本的なリストが取得されました。ただし、視聴回数や高評価など、各動画の詳細を取得するには、にAPI呼び出しを行う必要がありますvideos

// Looping through an array of video id's
function fetchViddetails(i) {
    $.getJSON("https://www.googleapis.com/youtube/v3/videos", {
        key: document.getElementById("accesskey").value,
        part: "snippet,statistics",
        id: vidsList[i]
        }, function(data) {

            // Commands to process JSON variable, extract the video
            // information and push it to a global array
            if (i < vidsList.length - 1) {
                fetchViddetails(i+1) // Recursive: calls itself if the
                                     //            list isn't over.
            }
});

参照してくださいここで完全なコード、そしてここでライブバージョンを。(編集:githubリンクを修正)
編集:依存関係:JQuery、Papa.parse

4
xjcl 2017-06-14 14:00.

この質問に答える誰もが原因に問題があるので、500ビデオの制限を、ここで使用して、代替ソリューションですyoutube_dlをしてPythonの3が。また、APIキーは必要ありません

  1. youtube_dlをインストールします。 sudo pip3 install youtube-dl
  2. YouTubeからチャンネルIDを取得するにはどうすればよいですか?。IDはUCで始まります。チャネルのCをアップロードのU(つまり、UU ...)に置き換えます。これはアップロードプレイリストです。
  3. youtube-dlのプレイリストダウンローダー機能を使用します。理想的には、デフォルトであるプレイリスト内のすべてのビデオをダウンロードするのではなく、メタデータのみをダウンロードする必要があります。

例(警告-数十分かかります):

import youtube_dl, pickle

             # UCVTyTA7-g9nopHeHbeuvpRA is the channel id (1517+ videos)
PLAYLIST_ID = 'UUVTyTA7-g9nopHeHbeuvpRA'  # Late Night with Seth Meyers

with youtube_dl.YoutubeDL({'ignoreerrors': True}) as ydl:

    playd = ydl.extract_info(PLAYLIST_ID, download=False)

    with open('playlist.pickle', 'wb') as f:
        pickle.dump(playd, f, pickle.HIGHEST_PROTOCOL)

    vids = [vid for vid in playd['entries'] if 'A Closer Look' in vid['title']]
    print(sum('Trump' in vid['title'] for vid in vids), '/', len(vids))
2
Als 2013-10-11 06:11.

非推奨のAPIバージョン2を使用すると、(チャネルUCqAEtEr0A0Eo2IVcuWBfB9gの)アップロードのURLは次のようになります。

https://gdata.youtube.com/feeds/users/UCqAEtEr0A0Eo2IVcuWBfB9g/uploads

APIバージョン3があります。

2
Glastis 2017-05-23 22:17.

最近、チャンネルからすべての動画を取得する必要がありました。YouTubeデベロッパーのドキュメントによると、https//developers.google.com/youtube/v3/docs/playlistItems/list

function playlistItemsListByPlaylistId($service, $part, $params) {
    $params = array_filter($params);
    $response = $service->playlistItems->listPlaylistItems(
        $part,
        $params
    );

    print_r($response);
}

playlistItemsListByPlaylistId($service,
    'snippet,contentDetails',
    array('maxResults' => 25, 'playlistId' => 'id of "uploads" playlist'));

$serviceあなたのGoogle_Service_YouTubeオブジェクトはどこにありますか。

そのため、チャンネルから情報を取得して、チャンネルによってアップロードされたすべての動画が実際に含まれている「アップロード」再生リストを取得する必要があります:https//developers.google.com/youtube/v3/docs/channels/list

このAPIを初めて使用する場合は、コードサンプルをデフォルトのスニペットから完全なサンプルに変更することを強くお勧めします。

したがって、チャンネルからすべての動画を取得するための基本的なコードは次のようになります。

class YouTube
{
    const       DEV_KEY = 'YOUR_DEVELOPPER_KEY';
    private     $client;
    private     $youtube;
    private     $lastChannel;

    public function __construct()
    {
        $this->client = new Google_Client();
        $this->client->setDeveloperKey(self::DEV_KEY);
        $this->youtube = new Google_Service_YouTube($this->client);
        $this->lastChannel = false;
    }

    public function getChannelInfoFromName($channel_name)
    {
        if ($this->lastChannel && $this->lastChannel['modelData']['items'][0]['snippet']['title'] == $channel_name)
        {
            return $this->lastChannel;
        }
        $this->lastChannel = $this->youtube->channels->listChannels('snippet, contentDetails, statistics', array(
            'forUsername' => $channel_name,
        ));
        return ($this->lastChannel);
    }

    public function getVideosFromChannelName($channel_name, $max_result = 5)
    {
        $this->getChannelInfoFromName($channel_name);
        $params = [
            'playlistId' => $this->lastChannel['modelData']['items'][0]['contentDetails']['relatedPlaylists']['uploads'],
            'maxResults'=> $max_result,
        ];
        return ($this->youtube->playlistItems->listPlaylistItems('snippet,contentDetails', $params));
    }
}

$yt = new YouTube();
echo '<pre>' . print_r($yt->getVideosFromChannelName('CHANNEL_NAME'), true) . '</pre>';
1
Ananth 2019-04-14 22:55.

Pythonのサンプルソリューション。この動画からのヘルプ:動画 他の多くの回答と同様に、アップロードIDは最初にチャンネルIDから取得されます。

urllib.requestをインポートします
jsonをインポートする

key = "YOUR_YOUTUBE_API_v3_BROWSER_KEY"

#チャンネルのリスト:チャンネルIDまたはユーザー名を貼り付けるかどうかを記載します-「id」または「forUsername」
ytids = [["bbcnews"、 "forUsername"]、["UCjq4pjKj9X4W9i7UnYShpVg"、 "id"]]

newstitles = []
ytidsのytid、ytparamの場合:
    urld = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails&"+ytparam+"="+ytid+"&key="+key
    urllib.request.urlopen(urld)をurlとして使用:
        datad = json.loads(url.read())
    uploadsdet = datad ['items']
    #チャンネルIDからアップロードIDを取得
    uploadid = uploadsdet [0] ['contentDetails'] ['relatedPlaylists'] ['uploads']

    #retrieveリスト
    urld = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&maxResults=50&playlistId="+uploadid+"&key="+key
    urllib.request.urlopen(urld)をurlとして使用:
        datad = json.loads(url.read())

    datad ['items']のデータの場合:
        ntitle =データ['スニペット'] ['タイトル']
        nlink = data ['contentDetails'] ['videoId']
        newstitles.append([nlink、ntitle])

リンクの場合、ニュースタイトルのタイトル:
    印刷(リンク、タイトル)

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

世界最小のマルチツールを15ドルでキーチェーンに追加

世界最小のマルチツールを15ドルでキーチェーンに追加

爪| $ 15 | マルボロ&ケインザクロー| $ 15 | Malboro&Kane世界最小のマルチツールであるTheClawをたった15ドルで手に入れましょう。男の子と一緒に冷たいものを割って開けたり、ネジを締めたり、Amazonパッケージを細断したりする場合でも、この悪い男の子はこれまでで最も便利な製品の1つです。

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンとしてのガル・ガドット。WaywardPinesは正式に終了しました。

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

人が2つのマッチを接着するように導くものは何ですか?何があなたをマッチに打ち続け、構造が湾曲していることを発見するのですか?42,000のボールを作るまで、試合を続けなければならない理由は何ですか?しかし、何よりも、これほど魅力的なショーである可能性はどのようにありますか?私はあなたをだますつもりはありません、次に私たちがあなたに残すのは、あなたや私のような人が自由な時間を過ごすことを決定するビデオですボールを作るために必要な試合数を確認します(答えは42です。

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

写真:AP先月、カリフォルニアの地元新聞が1,900万件以上の有権者記録をオンラインで公開しました。Gizmodoは今週、明らかなランサムウェア攻撃中にレコードが侵害されたことを確認しました。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language