![cover](https://image.oss.salted-fish.tech/blog/2585220384.jpg)
使用Youtube官方API订阅功能的实现
在开篇之前,请允许我引用并重新组织一位博主的言语:若想实现对一个YouTube频道的订阅功能,目前所知有两种方法。
1. 采用直接而笨重的轮询机制 - 即每隔一段时间去请求频道下的视频接口,根据返回的视频名称判断是否是新视频。这样做的缺点显而易见,一是除非轮询时间间隔特别短,否则基本没法保证时效性。二是频繁的访问查询接口会浪费掉大量的api 配额,因此这不是一种优雅的解决方案。
2. 使用官方的发布订阅系统 - 一种基于Webhooks实现的订阅推送(对于Webhooks机制不清楚的同学可以了解后再去尝试),可以实现几乎实时的更新推送
部分内容引用自以下博客,本篇博客也就是对以下文章中第三点(订阅功能实现)的补充说明
详细资料参考官方的这篇文档
https://developers.google.com/youtube/v3/guides/push_notifications
其主要流程就是,在下面这个网址中添加订阅频道和回调地址
这样你就会在你的服务器上接收到这样的更新信息
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015"
xmlns="http://www.w3.org/2005/Atom">
<link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<link rel="self" href="https://www.youtube.com/xml/feeds/videos.xml?channel_id=CHANNEL_ID"/>
<title>YouTube video feed</title>
<updated>2015-04-01T19:05:24.552394234+00:00</updated>
<entry>
<id>yt:video:VIDEO_ID</id>
<yt:videoId>VIDEO_ID</yt:videoId>
<yt:channelId>CHANNEL_ID</yt:channelId>
<title>Video title</title>
<link rel="alternate" href="http://www.youtube.com/watch?v=VIDEO_ID"/>
<author>
<name>Channel title</name>
<uri>http://www.youtube.com/channel/CHANNEL_ID</uri>
</author>
<published>2015-03-06T21:40:57+00:00</published>
<updated>2015-03-09T19:05:24.552394234+00:00</updated>
</entry>
</feed>
除以上资料外并没有更多像具体怎么实现的信息了,我想看到这像我一样的Java新手来言简直就是一头雾水。
为此我在此贴上我为时两个星期的测试代码(还是因为公司事务较忙,没空去查看日志所致)
以下代码只做测试、研究使用,生产环境勿用
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
/**
* @author 枫铃也
* @time 2020-05-14 14:59
* @description YouTube订阅服务接口 https://pubsubhubbub.appspot.com/subscribe
*/
@RestController
@RequestMapping("/system/youtube")
@Api(tags = "YouTubePubSubHubbubController")
public class YouTubePubSubHubbubController {
private static final Logger LOGGER = LoggerFactory.getLogger(YouTubePubSubHubbubController.class);
@RequestMapping(value = "subscribe", method = {RequestMethod.GET, RequestMethod.POST})
@ApiOperation(value = "YouTube订阅认证接口", notes = "YouTube订阅认证接口")
public String subscribe(HttpServletRequest request, @RequestHeader Map<String, String> headers) {
LOGGER.info("----------------打印请求全部消息开始----------------");
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
LOGGER.info("{} - {}", name, request.getHeader(name));
}
LOGGER.info("----------------打印请求全部消息结束----------------");
LOGGER.info("-----------------打印请求头消息开始-----------------");
headers.forEach((String key, String value) -> LOGGER.info(String.format("Header '%s' = %s", key, value)));
LOGGER.info("-----------------打印请求头消息结束-----------------");
Map<String, String[]> parameterMap = request.getParameterMap();
LOGGER.info("------------------打印全部参数开始------------------");
String result = "";
if (parameterMap.isEmpty()) {
LOGGER.info("请求参数为空");
}else {
parameterMap.forEach((String key, String[] value) -> {
for (String s : value) {
LOGGER.info("Param '{}' = {}", key, s);
}
});
result = parameterMap.get("hub.challenge")[0];
}
LOGGER.info("------------------打印全部参数结束------------------");
LOGGER.info("-----------------打印Reader数据开始----------------");
StringBuilder buffer = new StringBuilder();
try (BufferedReader reader = request.getReader()){
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
LOGGER.info("reader -> {}", buffer);
LOGGER.info("-----------------打印Reader数据结束----------------");
return result;
}
}
请大家忽略以上代码中的日志和API文档生成的辅助类,并附上实践 具体 完装的日志输出
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - ----------------打印请求全部消息开始----------------
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - host - 这个我不能给你们看,嘿嘿嘿
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - link - <https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCXQexglLCaJyTImYLmSO9Ng>; rel=self, <http://pubsubhubbub.appspot.com/>; rel=hub
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - content-type - application/atom+xml
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - cache-control - no-cache,max-age=0
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - pragma - no-cache
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - content-length - 943
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - connection - keep-alive
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - accept - */*
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - from - googlebot(at)googlebot.com
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - user-agent - FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - accept-encoding - gzip,deflate,br
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - ----------------打印请求全部消息结束----------------
09:39:30.330 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - -----------------打印请求头消息开始-----------------
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'host' = 这个我不能给你们看,嘿嘿嘿
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'link' = <https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCXQexglLCaJyTImYLmSO9Ng>; rel=self, <http://pubsubhubbub.appspot.com/>; rel=hub
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'content-type' = application/atom+xml
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'cache-control' = no-cache,max-age=0
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'pragma' = no-cache
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'content-length' = 943
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'connection' = keep-alive
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'accept' = */*
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'from' = googlebot(at)googlebot.com
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'user-agent' = FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - Header 'accept-encoding' = gzip,deflate,br
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - -----------------打印请求头消息结束-----------------
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - ------------------打印全部参数开始------------------
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - 请求参数为空
09:39:30.331 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - ------------------打印全部参数结束------------------
09:39:30.332 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - -----------------打印Reader数据开始----------------
09:39:30.332 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - reader -> <?xml version='1.0' encoding='UTF-8'?><feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns="http://www.w3.org/2005/Atom"><link rel="hub" href="https://pubsubhubbub.appspot.com"/><link rel="self" href="https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCXQexglLCaJyTImYLmSO9Ng"/><title>YouTube video feed</title><updated>2020-05-28T01:39:27.887188153+00:00</updated><entry> <id>yt:video:GRrUhlU34GM</id> <yt:videoId>GRrUhlU34GM</yt:videoId> <yt:channelId>UCXQexglLCaJyTImYLmSO9Ng</yt:channelId> <title>Dota2 - Team Nigma vs. Gambit - Game 3 - ESL One Birmingham 2020 - Group B - EU/CIS</title> <link rel="alternate" href="https://www.youtube.com/watch?v=GRrUhlU34GM"/> <author> <name>ESL Archives</name> <uri>https://www.youtube.com/channel/UCXQexglLCaJyTImYLmSO9Ng</uri> </author> <published>2020-05-28T01:36:33+00:00</published> <updated>2020-05-28T01:39:27.887188153+00:00</updated> </entry></feed>
09:39:30.332 [http-nio-4930-exec-7] INFO o.f.m.i.y.c.s.YouTubePubSubHubbubController - -----------------打印Reader数据结束----------------
一行字数太多,若换行显示或不方便查看大家则可以复制到Notpad++或其他编辑器缩放显示
通过以上日志输出可以看出此订阅方式的参数并非是传统的from表单形式。到此,具体的代码实现也就没什么可写的了。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Salted Fish
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果