首页 > 解决方案 > YouTube 数据 API 的问题:有时会崩溃并且无法正常工作

问题描述

我是后端开发人员,我想使用 YouTube 数据 API 来获取视频描述和标签,但是在使用这个 API 时,有时 API 没有响应。一段时间后,API 恢复正常并再次工作。如何解决这个问题?

youtubeClass.php

 <?php

class Youtube
{
    /**
     * @var string
     */
    protected $youtube_key; //pass in by constructor

    /**
     * @var string
     */
    protected $referer;

    /**
     * @var array
     */
    var $APIs = array(
        'videos.list' => 'https://www.googleapis.com/youtube/v3/videos',
        'search.list' => 'https://www.googleapis.com/youtube/v3/search',
        'channels.list' => 'https://www.googleapis.com/youtube/v3/channels',
        'playlists.list' => 'https://www.googleapis.com/youtube/v3/playlists',
        'playlistItems.list' => 'https://www.googleapis.com/youtube/v3/playlistItems',
        'activities' => 'https://www.googleapis.com/youtube/v3/activities',
    );

    /**
     * @var array
     */
    public $page_info = array();

    /**
     * Constructor
     * $youtube = new Youtube(array('key' => 'KEY HERE'))
     *
     * @param array $params
     * @throws \Exception
     */
    public function __construct($params = array())
    {
        if (!is_array($params)) {
            // throw new \InvalidArgumentException('The configuration options must be an array.');
        }

        if (!array_key_exists('key', $params)) {
            // throw new \InvalidArgumentException('Google API key is required, please visit http://code.google.com/apis/console');
        }
        $this->youtube_key = $params['key'];

        if (array_key_exists('referer', $params)) {
            $this->referer = $params['referer'];
        }
    }

    /**
     * @param $vId
     * @return \StdClass
     * @throws \Exception
     */
    public function getVideoInfo($vId)
    {
        $API_URL = $this->getApi('videos.list');
        $params = array(
            'id' => $vId,
            'key' => $this->youtube_key,
            'part' => 'id, snippet, contentDetails,status'
        );

        $apiData = $this->api_get($API_URL, $params);
        return $this->decodeSingle($apiData);
    }

    /**
     * @param $vIds
     * @return \StdClass
     * @throws \Exception
     */
    public function getVideosInfo($vIds)
    {
        $ids = is_array($vIds) ? implode(',', $vIds) : $vIds;
        $API_URL = $this->getApi('videos.list');
        $params = array(
            'id' => $ids,
            'part' => 'id, snippet, contentDetails, player, statistics, status'
        );

        $apiData = $this->api_get($API_URL, $params);
        return $this->decodeList($apiData);
    }


    /**
     * Parse a youtube URL to get the youtube Vid.
     * Support both full URL (www.youtube.com) and short URL (youtu.be)
     *
     * @param  string $youtube_url
     * @throws \Exception
     * @return string Video Id
     */
    public static function parseVIdFromURL($youtube_url)
    {
        if (strpos($youtube_url, 'youtube.com')) {
            $params = static::_parse_url_query($youtube_url);
            return $params['v'];
        } else if (strpos($youtube_url, 'youtu.be')) {
            $path = static::_parse_url_path($youtube_url);
            $vid = substr($path, 1);
            return $vid;
        } else {
            // throw new \Exception('The supplied URL does not look like a Youtube URL');
        }
    }

    /*
     *  Internally used Methods, set visibility to public to enable more flexibility
     */

    /**
     * @param $name
     * @return mixed
     */
    public function getApi($name)
    {
        return $this->APIs[$name];
    }

    public function searchAdvanced($params, $pageInfo = false)
    {
        $API_URL = $this->getApi('search.list');

        if (empty($params) || !isset($params['q'])) {
            // throw new \InvalidArgumentException('at least the Search query must be supplied');
        }

        $apiData = $this->api_get($API_URL, $params);
        if ($pageInfo) {
            return array(                
                'results' => $this->decodeList($apiData),
                'info'    => $this->page_info
            );
        } else {
            return $this->decodeList($apiData);
        }
    }

    /**
     * Decode the response from youtube, extract the single resource object.
     * (Don't use this to decode the response containing list of objects)
     *
     * @param  string $apiData the api response from youtube
     * @throws \Exception
     * @return \StdClass  an Youtube resource object
     */
    public function decodeSingle(&$apiData)
    {
        $resObj = json_decode($apiData);
        if (isset($resObj->error)) {
            $msg = "Error " . $resObj->error->code . " " . $resObj->error->message;
            if (isset($resObj->error->errors[0])) {
                $msg .= " : " . $resObj->error->errors[0]->reason;
            }
            // throw new \Exception($msg,$resObj->error->code);
        } else {           
            $itemsArray = $resObj->items;
            if (!is_array($itemsArray) || count($itemsArray) == 0) {
                return false;
            } else {
                return $itemsArray[0];
            }
        }
    }
    /**
     * Queries a single video 
     * @param $video
     * @return \Array
    **/ 
    public function Single($id = false) {
    if($id){
return $this->vMake($this->getVideoInfo($id));
    }       
    }
    /**
     * Returns a basic video array
     * @param $video
     * @return \Array
    **/ 
    public function vMake($video) {     
        $v = array();
        $v['videoid'] = $v['id'] =  $video->id;
        $v['url'] = 'https://www.youtube.com/watch?v='.$video->id;
        $v['thumb'] = $v['thumbnail'] = $video->snippet->thumbnails->medium->url;
        $v['title'] = htmlentities($video->snippet->title, ENT_QUOTES, "UTF-8");
        $v['description'] = htmlentities($video->snippet->description, ENT_QUOTES, "UTF-8");
        $v['duration'] = $this->getDurationSeconds($video->contentDetails->duration);
        $v['ptime'] = $video->contentDetails->duration;  
        $v['privacy'] = $video->status->privacyStatus;
        $v['embeddable'] = (bool)$video->status->embeddable;
        $v['ytChannelID'] = $video->snippet->channelId;
        $v['author'] = $v['ytChannelTitle'] = $video->snippet->channelTitle;
        $v['ytPublished'] = $video->snippet->publishedAt;       
      return $v;
    }
   /**
     * Decodes PT*M*S to seconds
     * @param $duration
     * @return \String
    **/  
    public function getDurationSeconds($duration){
    preg_match_all('/[0-9]+[HMS]/',$duration,$matches);
    $duration=0;
    foreach($matches as $match){    
        foreach($match as $portion){        
            $unite=substr($portion,strlen($portion)-1);
            switch($unite){
                case 'H':{  
                    $duration +=    substr($portion,0,strlen($portion)-1)*60*60;            
                }break;             
                case 'M':{                  
                    $duration +=substr($portion,0,strlen($portion)-1)*60;           
                }break;             
                case 'S':{                  
                    $duration +=    substr($portion,0,strlen($portion)-1);          
                }break;
            }
        }
    }
     return $duration -1;
    /* seems to add +1 to actual duration */
    }
    /**
     * Decode the response from youtube, extract the list of resource objects
     *
     * @param  string $apiData response string from youtube
     * @throws \Exception
     * @return array Array of StdClass objects
     */
    public function decodeList(&$apiData)
    {
        $resObj = json_decode($apiData);
        if (isset($resObj->error)) {
            $msg = "Error " . $resObj->error->code . " " . $resObj->error->message;
            if (isset($resObj->error->errors[0])) {
                $msg .= " : " . $resObj->error->errors[0]->reason;
            }
            // throw new \Exception($msg,$resObj->error->code);
        } else {
             $this->page_info = array(
                'resultsPerPage' => $resObj->pageInfo->resultsPerPage,
                'totalResults'   => $resObj->pageInfo->totalResults,
                'kind'           => $resObj->kind,
                'etag'           => $resObj->etag,
                'prevPageToken'  => NULL,
                'nextPageToken'  => NULL
            );
            if(isset($resObj->prevPageToken)){
                $this->page_info['prevPageToken'] = $resObj->prevPageToken;
            }
            if(isset($resObj->nextPageToken)){
                $this->page_info['nextPageToken'] = $resObj->nextPageToken;
            }

            $itemsArray = $resObj->items;
            if (!is_array($itemsArray) || count($itemsArray) == 0) {
                return false;
            } else {
                return $itemsArray;
            }
        }
    }

    /**
     * Using CURL to issue a GET request
     *
     * @param $url
     * @param $params
     * @return mixed
     * @throws \Exception
     */
    public function api_get($url, $params)
    {
        //set the youtube key
        $params['key'] = $this->youtube_key;

        //boilerplates for CURL
        $tuCurl = curl_init();
        curl_setopt($tuCurl, CURLOPT_URL, $url . (strpos($url, '?') === false ? '?' : '') . http_build_query($params));
        if (strpos($url, 'https') === false) {
            curl_setopt($tuCurl, CURLOPT_PORT, 80);
        } else {
            curl_setopt($tuCurl, CURLOPT_PORT, 443);
        }
        if ($this->referer !== null) {
            curl_setopt($tuCurl, CURLOPT_REFERER, $this->referer);
        }
        curl_setopt($tuCurl, CURLOPT_RETURNTRANSFER, 1);
        $tuData = curl_exec($tuCurl);
        if (curl_errno($tuCurl)) {
            // throw new \Exception('Curl Error : ' . curl_error($tuCurl));
        }
        return $tuData;
    }

    /**
     * Parse the input url string and return just the path part
     *
     * @param  string $url the URL
     * @return string      the path string
     */
    public static function _parse_url_path($url)
    {
        $array = parse_url($url);
        return $array['path'];
    }

    /**
     * Parse the input url string and return an array of query params
     * 
     * @param  string $url the URL
     * @return array      array of query params
     */
    public static function _parse_url_query($url)
    {
        $array = parse_url($url);
        $query = $array['query'];

        $queryParts = explode('&', $query);

        $params = array();
        foreach ($queryParts as $param) {
            $item = explode('=', $param);
            $params[$item[0]] = empty($item[1]) ? '' : $item[1];
        }
        return $params;
    }
}

index.php

<?php

if($_POST['q']){

 include("./youtubeClass.php");

    $youtube = new Youtube(array('key' => 'YOUTUBETOKEN'));
    $params = array(
        'q'             => $_POST['q'],
        'type'          => $_POST['type'],
        'part'          => $_POST['part'],
        'videoEmbeddable' => $_POST['videoEmbeddable'],
        'maxResults'    => $_POST['maxResults'],
        'pageToken'    =>$_POST['pageToken']
    );
    $ytVideos = $youtube->searchAdvanced($params,true);
    $videos = array();
    foreach($ytVideos['results'] as $vd){
      $video = $youtube->Single($vd->id->videoId);
        $videoInf = array(
            "title" => $video['title'],
            "description" => $video['description'],
            "id" => $video['id'],
            "duration" => $video['duration'],
            "author" => $video['author']
        );
        
        // $videos[] = $videoInf;
        array_push($videos,$videoInf);
    }
    $videos = json_encode($videos);
    print_r($videos);
    
}else{
    echo '';
}

以及要调用的第三个文件index.phpcallApi.php

$ch = curl_init('http://www.sample.com/youtube/index.php');
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);

            // execute!
            $response = curl_exec($ch);

            // close the connection, release resources used
            curl_close($ch);

            // do anything you want with your response
            $response = json_decode($response);
            var_dump($response);

$responseNULL

标签: youtubeyoutube-apiyoutube-data-api

解决方案


推荐阅读