如何为 Youtube v3 数据使用 Etags API?

How do I use Etags for Youtube v3 Data API?

我正在构建一个扩展,它发出了 很多 的请求。我正在开发的功能是显示观看播放列表所需的总时间长度。给定一个大小为 1000 的播放列表,我必须发出 40 个请求才能找到此信息(时间限制为 50 个视频,第一次调用 /v3/playlistItems 获取视频 ID 数组,第二次调用 /v3/videos 持续时间信息)。据我所知,仅仅为了那个播放列表,我就失去了 600 个配额。每次加载页面。我知道,没有什么好担心的,因为我每天允许 50,000,000 个配额,但我想尽早优化。这也是一个速度问题。获得播放列表长度需要整整一分半钟。

现在,ETag。出于某种原因,每次我向 youtube 的数据 API 请求视频或播放列表项时,我都会得到一个全新的 Etag(大多数时候,我遇到过 return 相同的 ETag 的情况) ,无论播放列表如何(我还没有尝试过私人播放列表,还没有做 OAuth)。我假设原因是播放列表中某处发生了变化,导致新的 Etag 非常快。意见? PlaylistItems 甚至没有 return 观看次数!

下面是 API 调用通心粉播放列表的示例。 ETag 总是不同的!如果它们不起作用,我应该如何使用它们?它们是特定的,视频的长度不可能在请求之间发生变化。 api 键被省略,因为您可以制作自己的 api 键。

```
Playlist Items, give me video id's, page tokens, and Etag for playlist for items 100-150
https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&maxResults=50&playlistId=PLF-hTvh6KCehzImlI2pAKsOFPR62QZTv-&fields=etag%2Citems%2FcontentDetails%2CnextPageToken%2CprevPageToken&key={YOUR_API_KEY}&pageToken=CGQQAA

Videos, give me durations and Etag for these video ids
https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=SswxpqGX1F0,3Hy5BuFTBbI,ZnlW1fSXZZM,8sb_YOrReZ4,6IN_mupBjh8,VzoqsRLY5Qk,5m8H9YrPvPA,JdRbtGdR68E,hEzPBiYPsDU,bJuioKFYv-c,1N8O8OOG2_U,QDgqSL8nU5U,gP4gB45Z52M,pI1oB2y9c0M,WZGn5Vh_mc4,A0KpbS5WjSU,b0yoIOX8Bk0,5Y7iQt7vtOE,qIijCwjUApQ,RgHjqvznjxg,QzceROWtn5o,8z0VnMQFGR8,5olHoTWB1Hw,vz0T59Ql7fQ,LhktiZYQraU,WIuuZOD9ahI,rwEHW6GRH1Q,FjT1BpKvfgo,FRZL2yaZyZk,U5-vjCDwDUU,b21Lj9bfDWc,yox3-U7r_i8,rXJ5ph83Vrs,nXrk2finMcA,VfagTkQWHuI,K_ZaRAtZQOg,_JIcREsn9pU,y9WGvudeDAM,O08jNtrieI4,9UkEzW1AY7Y,jOaBdnYsobg,y7dSbhc-8h0,IfpPiCGcF8g,2rTRmb9nKbY,bHgv3A26O6Y,hFQmV-zvcbM,Osc4y45oQxw,GHusS6Yd5A8,T2Z3CuUWUQc,OPV-DopMqxs&fields=etag%2Citems%2FcontentDetails%2Fduration&key={YOUR_API_KEY}
```

我想缓存这个数据。我正在考虑对播放列表的总视频提出额外的开始请求,因为这与播放列表的总时间长度直接相关。但这感觉像是很多逻辑。 added/removed 是什么视频?多少?如果它被添加到开头,我想优化,我必须将前 50 个视频 ID 与我缓存的视频 ID 持续时间进行比较。如果它在中间某处被更改,我必须继续查询。也许缓存别的东西让这更容易?多个播放列表可以有相同的视频,播放列表可以有不止一次相同的视频,我不知道。也许没有办法查询整个播放列表,也许我应该只缓存对 /v3/videos 的调用。问题是我想优化对 /v3/playlistItems 的调用,因为它很长(需要 3 倍的时间到 /v3/videos)。

我的主要问题是:我缓存什么来优化获取播放列表长度,我该怎么做,ETag 怎么了?

当您 运行 相同的查询且内容未更改时,YouTube 数据 API returns 始终在变化的 Etag。因此,看起来 Etag 实现已损坏。

但是,事实上并非如此。如果您在请求中提供之前收到的 Etag,则 YouTube 数据 API 将正常运行。它将识别 Etag 并使用 HTTP 状态 304 Not Modified 进行响应。

我刚才想出了如何缓存数据,抱歉!

您可以调用 /playlists 以获取播放列表中项目的总数,以及当且仅当播放列表本身发生变化时 etag 的变化,这正是我想要的。我只想在基本播放列表更改时提出新请求。

调用 /playlistItems 总是会生成一个新的 etag,无论更改如何。我认为此端点用于临时查询以找出与播放列表相关的视频元数据,而不是用于静态数据查找。播放列表非常灵活,我认为 YouTube 决定不缓存此数据,因为对 /playlistItems 的调用通常基于 case-by-case。他们的后端很可能会自动生成一个 etag,但实际上并没有为此端点保存任何内容。

因此,这些是获取播放列表的总时长以及缓存的步骤:

  1. 获取播放列表 ID
  2. 通过播放列表 ID 在缓存中查找 etag
  3. 使用 If-None-Match header 中的 etag 调用 /playlists(即使 etag 为空也应该有效)
    • 如果api returns 304,使用缓存的播放列表长度
    • 如果 api returns 200,将新的 etag 保存在缓存中
    • 你可以做更多的缓存!
  4. 使用播放列表 ID 调用 /playlistItems(包含所有 pageTokens)
  5. 在缓存中查找每个videoId以获得视频长度
    • 缓存定义为videoId:videoLength
    • 的字典
    • 如果未找到 videoLength,请将 videoId 添加到 videos 数组
    • 如果找到 videoLength,添加到 lengths 数组
  6. 使用缓存中未找到的所有视频 ID 调用 /videos,最多 50 个元素
    • 可以在 /playlistItems 调用后立即完成,或者在所有调用完成后完成,我认为现在偷懒并在每次调用后立即进行是可以的
    • 您还可以使用 etags 缓存视频通话并保存它以检查长度是否没有改变,但是您必须为每个视频调用 api。我不知道,但我认为这是 over-optimizing。仍然可能要记住,调试时可以通过 YouTube 的编辑工具更改视频长度
  7. (接 7)对于响应中的每个视频,将视频长度作为 videoId:videoLength 对缓存在字典中,然后将长度添加到 lengths 数组
  8. lengths 数组缩减为 moment.js 持续时间 object
  9. 保存播放列表长度的格式化字符串作为key
  10. Return播放列表长度的格式化字符串

Here is the implementation on my github

我发现,只有当您使用 "part=id" 而不是 "maxResults=NN" 时,etag 才能正常工作。 否则每次调用 API returns new etag.

eTag 不会更改每个请求。但是您会针对特定请求获得特定数量的不同电子标签。 原因是响应中的某些元素改变了它们的顺序,因此创建 eTag 的算法会产生不同的 eTag。只要两个响应的内容元素顺序完全相同,eTag 就会再次相同。我记录了一堆请求并得出了这个结论。通过 id 和 part=brandingSettings,snippet 使用频道请求进行测试。 如果您 select 在响应中包含大量嵌套元素的多个部分,您将获得更多不同的组合,因此会获得不同的 eTag。