【问题标题】:youtube api v3 page tokensyoutube api v3 页面令牌
【发布时间】:2014-11-13 03:11:13
【问题描述】:

我正在使用搜索 api 并使用 nextpagetoken 对结果进行分页。 但我无法以这种方式检索所有结果。我只能从大约 455000 个结果中得到 500 个结果。

这是获取搜索结果的 java 代码:

youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() {public void initialize(HttpRequest request) throws IOException {}           }).setApplicationName("youtube-search").build();

YouTube.Search.List search = youtube.search().list("id,snippet");
String apiKey = properties.getProperty("youtube.apikey");
search.setKey(apiKey);
search.setType("video");
search.setMaxResults(50);
search.setQ(queryTerm);
boolean allResultsRead = false;
while (! allResultsRead){
SearchListResponse searchResponse = search.execute();
System.out.println("Printed " +  searchResponse.getPageInfo().getResultsPerPage() + " out of " + searchResponse.getPageInfo().getTotalResults() + ". Current page token: " + search.getPageToken() + "Next page token: " + searchResponse.getNextPageToken() + ". Prev page token" + searchResponse.getPrevPageToken());
if (searchResponse.getNextPageToken() == null)
{
    allResultsRead = true;                          
    search = youtube.search().list("id,snippet");
    search.setKey(apiKey);
    search.setType("video");
    search.setMaxResults(50);
}
else
{
   search.setPageToken(searchResponse.getNextPageToken());
}}

输出是

Printed 50 out of 455085. Current page token: null Next page token: CDIQAA. Prev page token null
Printed 50 out of 454983. Current page token: CDIQAA Next page token: CGQQAA. Prev page token CDIQAQ
Printed 50 out of 455081. Current page token: CGQQAA Next page token: CJYBEAA. Prev page token CGQQAQ
Printed 50 out of 454981. Current page token: CJYBEAA Next page token: CMgBEAA. Prev page token CJYBEAE
Printed 50 out of 455081. Current page token: CMgBEAA Next page token: CPoBEAA. Prev page token CMgBEAE
Printed 50 out of 454981. Current page token: CPoBEAA Next page token: CKwCEAA. Prev page token CPoBEAE
Printed 50 out of 455081. Current page token: CKwCEAA Next page token: CN4CEAA. Prev page token CKwCEAE
Printed 50 out of 454980. Current page token: CN4CEAA Next page token: CJADEAA. Prev page token CN4CEAE
Printed 50 out of 455081. Current page token: CJADEAA Next page token: CMIDEAA. Prev page token CJADEAE
Printed 50 out of 455081. Current page token: CMIDEAA Next page token: null. Prev page token CMIDEAE

while 循环经过 10 次迭代后,因为下一页标记为空而退出。

我是 Yotube API 的新手,不知道我在这里做错了什么。我有两个问题: 1. 我如何获得所有结果? 2、为什么第3页的前一页token和第2页的当前token不一样?

任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: youtube youtube-api


    【解决方案1】:

    您正在体验预期的内容;使用 nextPageToken,最多只能得到 500 个结果。如果你有兴趣了解它是如何产生的,你可以阅读这个帖子:

    https://code.google.com/p/gdata-issues/issues/detail?id=4282

    但作为该主题的总结,它基本上归结为这样一个事实,即 YouTube 上有如此多的数据,搜索算法与大多数人认为的完全不同。这不仅仅是对字段中的内容进行简单的数据库搜索,还有大量的信号正在被处理以使结果相关,并且在大约 500 个结果之后,算法开始失去使结果有价值的能力.

    帮助我理解这一点的一件事是,意识到当 YouTube 谈论搜索时,他们谈论的是概率而不是匹配,因此根据您的参数,根据它们出现的可能性对结果进行排序与您的查询相关。然后,当您进行分页时,您最终会到达一个点,从统计学上讲,相关概率足够低,以至于在计算上不值得让这些结果返回。所以 500 是决定的限制。

    (另请注意,“结果”的数量不是匹配的近似值,它是潜在匹配的近似值,但是当您开始检索它们时,许多可能的匹配被抛弃,因为根本不相关......所以这个数字并不真正意味着人们认为它是什么。谷歌搜索也是如此。)

    您可能想知道为什么 YouTube 搜索以这种方式运行,而不是进行更传统的字符串/数据匹配;有这么多的搜索量,如果他们要对每个查询的所有数据进行完整的搜索,你一次要等待几分钟,如果不是更多的话。这真的是一个技术奇迹,如果你想一想,当算法在预测、概率等方面发挥作用时,它们如何能够为前 500 个案例获得如此相关的结果。

    关于您的第二个问题,页面标记并不代表一组唯一的结果,而是代表一种算法状态,因此是指向您的查询、查询进度和查询方向的指针...因此,例如,迭代 3 被迭代 2 的 nextPageToken 和迭代 4 的 prevPageToken 引用,但这两个标记略有不同,因此它们可以指示它们来自的方向。

    【讨论】:

    • 搜索页面和概率参数有效。但我想知道为什么他们将其扩展到所有其他页面 - cmets、频道视频、观看历史记录?通过 API 的最后一个 pageToken(至少在最近的更改之前,当页面令牌仍采用“CDIQAA”到“CJ-NBhAA”的格式时)允许您查看多达 100,049 个项目。超出此范围的任何内容,您都需要抓取网站以获取数据,因为 API 会告诉您,如果您尝试更高,则令牌无效。我觉得很奇怪。
    【解决方案2】:

    我明白了,你没有在 setFields 中包含“nextPageToken”。

    例如:

    public class ABC {
    private YouTube youtube;
    private YouTube.Search.List query;
    
    public static final String KEY = "YOUR API KEY";
    
    public YoutubeConnector(Context context) {
        youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), new HttpRequestInitializer() {
            @Override
            public void initialize(HttpRequest httpRequest) throws IOException {
            }
        }).setApplicationName(context.getString(R.string.app_name)).build();
    
        try {
            query = youtube.search().list("id,snippet");
            query.setMaxResults(Long.parseLong("10"));
            query.setKey(KEY);
            query.setType("video");
            query.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url),nextPageToken");
        } catch (IOException e) {
            Log.d("YC", "Could not initialize: " + e.getMessage());
        }
    }
    
    public List<VideoItem> search(String keywords) {
        query.setQ(keywords);
            try {
                List<VideoItem> items = new ArrayList<VideoItem>();
                String nextToken = "";
                int i = 0;
                do {
                    query.setPageToken(nextToken);
                    SearchListResponse response = query.execute();
                    List<SearchResult> results = response.getItems();
                    for (SearchResult result : results) {
                        VideoItem item = new VideoItem();
                        item.setTitle(result.getSnippet().getTitle());
                            item.setDescription(result.getSnippet().getDescription());
                        item.setThumbnailURL(result.getSnippet().getThumbnails().getDefault().getUrl());
                        item.setId(result.getId().getVideoId());
                        items.add(item);
                    }
                    nextToken = response.getNextPageToken();
                    i ++;
                    System.out.println("nextToken :  "+ nextToken);
                } while (nextToken != null && i < 20);
    
                return items;
            } catch (IOException e) {
                Log.d("YC", "Could not search: " + e);
                return null;
            }
    
    }
    }
    

    希望对你有所帮助。

    【讨论】:

      【解决方案3】:

      您可以传递页面 nextpagetoken 并将其作为参数提供给 pagetoken

      这将显示下一个页面我写了一个vardamp来告诉你页面令牌不一样只需复制此代码并运行它并确保你已将api资源文件夹放在插件的同一文件夹中

          <?php
          function doit(){if (isset($_GET['q']) && $_GET['maxResults'] ) {
            // Call set_include_path() as needed to point to your client library.
           // require_once ($_SERVER["DOCUMENT_ROOT"].'/API/youtube/google-api-php-client/src/Google_Client.php');
           // require_once ($_SERVER["DOCUMENT_ROOT"].'/API/youtube/google-api-php-client/src/contrib/Google_YouTubeService.php');
            set_include_path("./google-api-php-client/src");
            require_once 'Google_Client.php';
            require_once 'contrib/Google_YouTubeService.php';
            /* Set $DEVELOPER_KEY to the "API key" value from the "Access" tab of the
            Google APIs Console <http://code.google.com/apis/console#access>
            Please ensure that you have enabled the YouTube Data API for your project. */
            $DEVELOPER_KEY = 'AIzaSyCgHHDrx5ufQlkXcSc8nm5uqrsNdXizbMs';
      
                              //  the old one    AIzaSyDOkg-u9jnhP-WnzX5WPJyV1sc5QQrtuyc 
      
      
      
          $client = new Google_Client();
            $client->setDeveloperKey($DEVELOPER_KEY);
      
            $youtube = new Google_YoutubeService($client);
      
            try {
              $searchResponse = $youtube->search->listSearch('id,snippet', array(
                'q' => $_GET['q'],
                'maxResults' => $_GET['maxResults'],
      
          ));
          var_dump($searchResponse);
      
      
          $searchResponse2 = $youtube->search->listSearch('id,snippet', array(
            'q' => $_GET['q'],
            'maxResults' => $_GET['maxResults'],
            'pageToken' => $searchResponse['nextPageToken'],
          ));
          var_dump($searchResponse2);
          exit;
      
      
          $videos = '';
          $channels = '';
            foreach ($searchResponse['items'] as $searchResult) {
                switch ($searchResult['id']['kind']) {
               case 'youtube#video':
      
                $videoId =$searchResult['id']['videoId'];
                $title = $searchResult['snippet']['title'];
                $publishedAt= $searchResult['snippet']['publishedAt'];
                $description = $searchResult['snippet']['description'];
                $iamge_url =  $searchResult['snippet'] ['thumbnails']['default']['url'];
                $image_high  = $searchResult['snippet'] ['thumbnails']['high']['url'];
      
      
      
      
                echo  '<div class="souligne" id="'.$videoId.'">
      
                  <div >
                  <a href=http://www.youtube.com/watch?v='.$videoId.' target=_blank"  >
                  <img src="'.$iamge_url .'"   width ="150px" /> 
                  </a> 
                  </div>
                  <div class="title">'.$title.'</div>
                  <div class="des"> '.$description.' </div>
                  <a id="'.$videoId.'" onclick="supp(this)" class="linkeda"> 
                      + ADD
                  </a>                
                  </div>'
                  ;
                break;
            }
          }
          echo  ' </ul></form>';
      
             } catch (Google_ServiceException $e) {
              $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
                htmlspecialchars($e->getMessage()));
            } catch (Google_Exception $e) {
              $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
                htmlspecialchars($e->getMessage()));
            }
          }}
             doit();
          ?>
          <!doctype html>
          <html>
            <head>
              <title>YouTube Search</title>
          <link href="//www.w3resource.com/includes/bootstrap.css" rel="stylesheet">
          <style type="text/css">
          body{margin-top: 50px; margin-left: 50px}
          </style>
            </head>
            <body>
              <form method="GET">
            <div>
              Search Term: <input type="search" id="q" name="q" placeholder="Enter Search Term">
            </div>
            <div>
      
              Max Results: <input type="number" id="maxResults" name="maxResults" min="1" max="1000000" step="1" value="25">
            </div>
            <div>
              page: <input type="number" id="startIndex" name="startIndex" min="1" max="50" step="1" value="2">
            </div>
            <input type="submit" value="Search">
          </form>
      
      <h3>Videos</h3>
          <ul><?php if(isset($videos))echo $videos; ?></ul>
          <h3>Channels</h3>
          <ul><?php if(isset($channels)) echo $channels; ?></ul>
      </body>
      </html>
      

      【讨论】:

        猜你喜欢
        • 2013-01-28
        • 2013-05-03
        • 2014-04-18
        • 2016-06-22
        • 2013-05-14
        • 2015-06-15
        • 1970-01-01
        • 2015-09-06
        • 2020-04-22
        相关资源
        最近更新 更多