【问题标题】:Get all youtube videos from a channel (some videos are missing)从频道获取所有 youtube 视频(缺少一些视频)
【发布时间】:2014-10-29 17:31:59
【问题描述】:

我正在为 Youtube 使用 v3 Google API:

$url = 'https://www.googleapis.com/youtube/v3/search?part=id&channelId=' . $channelID . '&maxResults=50&order=date&key=' . $API_key;

我已经设置了一个脚本,它应该给我来自给定频道 ID 的所有视频。对于某些频道,我得到所有视频,对于一些缺少的视频(与直接在 Youtube 中显示的视频数量相比),对于更大的频道,我得到一个最大值。 488 个视频的结果,尽管还有更多。

pageToken 是一个奇怪的东西。例如,一个频道有 955 个视频。我得到 18 页,每页 50 个项目(即 900 个视频)。其中一些是播放列表,但如果我减去 23 个播放列表,我仍然有 877 个视频。如果我删除重复项,我只有 488 个结果! JSON 输出中的 totalResults 显示了 975 个结果!?

这是我的递归函数:

function fetchAllVideos($parsed_json){
    $foundIds = array();
    if($parsed_json != ''){
        $foundIds = getVideoIds($parsed_json);
        $nextPageToken = getNextPageToken($parsed_json);
        $prevPageToken = getPrevPageToken($parsed_json);

        if($nextPageToken != ''){
            $new_parsed_json = getNextPage($nextPageToken);
            $foundIds = array_merge($foundIds, fetchAllVideos($new_parsed_json));
        }
        if($prevPageToken != ''){
            $new_parsed_json = getNextPage($prevPageToken);
            $foundIds = array_merge($foundIds, fetchAllVideos($new_parsed_json));
        }
    }

    return $foundIds;
}

我用$videoIds = fetchAllVideos($parsed_json); 调用它,$parsed_json 是我检索到的第一个 URL 的结果。你能在这里看到错误吗?

有人知道直接在 Youtube 上显示的视频数量是如何计算的吗?有没有人设法获得与 Youtube 中的数字相对应的完整列表?

【问题讨论】:

    标签: php recursion youtube google-api


    【解决方案1】:

    https://gdata.youtube.com/feeds/api/users/USERNAME_HERE/uploads?max-results=50&alt=json&start-index=1 成功了。这是一个 JSON 提要,您必须在其中循环直到获得少于 50 个结果。

    编辑:

    这应该是我使用的脚本:

    ini_set('max_execution_time', 900);
    
    function getVideos($channel){
        $ids = array();
        $start_index = 1;
        $still_have_results = true;
    
        if($channel == ""){
            return false;   
        }
    
        $url = 'https://gdata.youtube.com/feeds/api/users/' . $channel . '/uploads?max-results=50&alt=json&start-index=' . $start_index;
        $json = file_get_contents($url);
        $obj = json_decode($json);
    
        while($still_have_results){
            foreach($obj->feed->entry as $video){
                $video_url = $video->id->{'$t'};
                $last_pos = strrpos($video_url, '/');
                $video_id = substr($video_url, $last_pos+1, strlen($video_url) - $last_pos);
                array_push($ids, $video_id);
            }
            $number_of_items = count($obj->feed->entry);
            $start_index += count($obj->feed->entry);
            if($number_of_items < 50) {
                $still_have_results = false;
            }
    
            $url = 'https://gdata.youtube.com/feeds/api/users/' . $channel . '/uploads?max-results=50&alt=json&start-index=' . $start_index;
            $json = file_get_contents($url);
            $obj = json_decode($json);
        }
    
        return $ids;    
    }
    
    $videoIds = getVideos('youtube');
    echo '<pre>';
    print_r($videoIds);
    echo '</pre>';
    

    现在我做了一个测试,但我没有收集到 100% 的视频。不过,这是我想出的最佳选择。

    【讨论】:

    • 我给了你赞成票,但无论如何你都应该发布决赛。你不知道什么时候它可能对某人有用。
    • @Random:现在我添加了我使用的脚本。
    【解决方案2】:

    此脚本一次选择一个 60 天的时间段并为其检索结果,然后将其添加到现有数据数组中。通过这样做,允许的视频数量没有限制,尽管可能需要一些时间来搜索包含数千个视频的更大的 YouTube 频道。确保您设置了 API_KEY、时区、用户名、开始日期(应该在频道上的第一个视频之前开始)和时间段(默认设置为 60 * 60 * 24 * 60,即 60 天,以秒为单位。这需要如果视频的频率在 60 天内高于约 50 则更低。)(5184000 秒)。

    *所有这些都在脚本中注释。

    date_default_timezone_set("TIMEZONE"); 
    
    //youtube api key
    $API_KEY = "YOUR API KEY";
    
    function search($searchTerm,$url){
        $url = $url . urlencode($searchTerm);
    
        $result = file_get_contents($url);
    
        if($result !== false){
            return json_decode($result, true);
        }
    
        return false;
    }
    
    function get_user_channel_id($user){
        global $API_KEY;
        $url = 'https://www.googleapis.com/youtube/v3/channels?key=' . $API_KEY . '&part=id&forUsername=';
        return search($user,$url)['items'][0]['id'];
    }
    
    function push_data($searchResults){
        global $data;
        foreach($searchResults['items'] as $item){
            $data[] = $item;
        }
        return $data;
    }
    
    function get_url_for_utc_period($channelId, $utc){
        //get the API_KEY
        global $API_KEY;
        //youtube specifies the DateTime to be formatted as RFC 3339 formatted date-time value (1970-01-01T00:00:00Z)
        $publishedAfter = date("Y-m-d\TH:i:sP",strval($utc));
        //within a 60 day period
        $publishedBefore_ = $utc + (60 * 60 * 24 * 60);
        $publishedBefore = date("Y-m-d\TH:i:sP",$publishedBefore_);
        //develop the URL with the API_KEY, channelId, and the time period specified by publishedBefore & publishedAfter
        $url = 'https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&key=' . $API_KEY . '&maxResults=50&channelId=' . $channelId . '&publishedAfter=' . urlencode($publishedAfter) . '&publishedBefore=' . urlencode($publishedBefore);
    
        return array("url"=>$url,"utc"=>$publishedBefore_);
    }
    //the date that the loop will begin with, have this just before the first videos on the channel.
    //this is just an example date
    $start_date = "2013-1-1";
    $utc = strtotime($start_date);
    $username = "CHANNEL USERNAME NOT CHANNEL ID";
    //get the channel id for the username
    $channelId = get_user_channel_id($username);
    
    while($utc < time()){
        $url_utc = get_url_for_utc_period($channelId, $utc);
        $searchResults = search("", $url_utc['url']);
        $data = push_data($searchResults);
        $utc += 60 * 60 * 24 * 60;
    }
    print "<pre>";
    print_r($data);
    print "</pre>";
    
    //check that all of the videos have been accounted for (cross-reference this with what it says on their youtube channel)
    print count($data);
    

    【讨论】:

    • 谢谢,让我能够非常快速地获取一堆视频!
    猜你喜欢
    • 2016-05-13
    • 2021-03-14
    • 2015-09-02
    • 1970-01-01
    • 2017-11-21
    • 2011-09-13
    • 2016-03-12
    • 1970-01-01
    • 2016-03-01
    相关资源
    最近更新 更多