前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何在YouTube Api限额的情况下获取更多视频

如何在YouTube Api限额的情况下获取更多视频

作者头像
一滴水的眼泪
发布于 2020-09-24 02:58:22
发布于 2020-09-24 02:58:22
2.8K00
代码可运行
举报
文章被收录于专栏:一滴水的眼泪一滴水的眼泪
运行总次数:0
代码可运行

如何在YouTube Api限额的情况下获取更多视频

YouTube视频

谷歌限制了YouTube api v3的请求量,一天10000配额,这里不是10000次请求,每次请求根据不同参数消耗不同配额。为了摆脱这种限制而获得更多的新发布视频,做了以下内容的方案。

需求:

运营配置YouTube的channelId,后台需要根据这些channelId去获取最近发布的可以在小屏播放的video信息,以增加用户活度。

问题:

YouTube限额问题,谷歌限制域名只能使用一个ApiKey,配置多会被封禁,按照现有全部用api检索会导致频道越配越多,获得的视频越来越少。

解决:

思路1:

出于问题中关键点,系统不知道channel下面发布的情况,只能被动查询,这样可能会导致查询消耗了配置结果返回为空或者很少视频的情况;所以考虑使用订阅模式去事先得知频道的情况。

查找了很多资料;最坑的竟然是YouTube api官网给的方法。。。。(youtubeApi)。我试着去使用它介绍的发布订阅,对于Google的集线器我研究了很久,毕竟不熟悉,而且没有相关的java实现。

方式1:

1.启动自己的回调服务器,随便弄个可以外网访问的服务返回200和请求参数中的hub_chanlenge即可。

2.订阅你需要订阅的频道的atom:类似:https://www.youtube.com/xml/feeds/videos.xml?channel_id=CHANNEL_ID 这种。

3.返回204即成功。

我的尝试:

我使用的自己的云服务器,使用谷歌的集线器,然后去订阅YouTube,发现509等错误,莫名其妙后使用了自己写的atom作为发布方,结果成功了。不过,可笑的是,这个集线器它并不能正常工作,我在修改atom再次发布的时候,它竟然没能好好工作;没向我的回调函数发送信息。我崩溃了,我去谷歌搜索了很多相关问题,发现YouTube已经不将视频信息发布到上面所说的xml中了,而且在这之前YouTube为了用户体验,每个频道只发送3条消息给订阅用户(YouTube自带的那个铃铛订阅)我去你…..

方式2:

再对问题思考,依然摆脱不了需要提前得知频道下视频的发布情况,我试着去YouTube网站videos下查看视频与api返回的视频做对照,发现可以使用解析http的标签获取发布的视频和时间(其实一开始也想过使用爬虫,奈何怕蹲牢啊。。)。我试着使用httpClient解析这个页面,果然得到了我想要的答案。

这样我就可以提前知道频道的发布情况,进而对使用api检索得到的结果有了大的优化。相关代码如下:

YouTubeTest

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class YoutubeTest {
  
    private static String matching = "</li><li>";
    private final static String CONTENT = "class=\"yt-lockup-content\"";

    private static final String GET_VEDIO_INFO_PRE = "https://youtube.com/get_video_info?video_id=";

    public static void main(String[] args) throws Exception {
        http("UC24_Z2L-8Ki183AI9zJJzNQ");
    }




    private static void http(String channelId) throws Exception {
        String url = "https://www.youtube.com/channel/" + channelId + "/videos";
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();
            String responseYoutube = EntityUtils.toString(entity);
            List<String> countList = new ArrayList<>(100);
            int length = responseYoutube.length();
            int i1, i2 = 0;
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < length; i++) {
                i1 = responseYoutube.indexOf(CONTENT, i);
                if (i1 > 0) {
                    i2 = responseYoutube.indexOf("</div>", i1);
                    if (i2 > 0) {
                        countList.add(responseYoutube.substring(i1, i2));
                        i = i2;
                    }
                } else {
                    break;
                }
            }
            long endEachTime = System.currentTimeMillis();
            System.out.println("遍历耗时:" + (endEachTime - startTime) + "ms");
            List<VideoInfo> videoInfos = new ArrayList<>(30);
            countList.forEach((s) -> {
                int hrefStart = s.indexOf("v=");
                int hrefEnd = s.indexOf("\"", hrefStart);
                VideoInfo videoInfo = new VideoInfo();
                int lastIndex = s.indexOf("</li></ul>");
                if (lastIndex > 0) {
                    String substring = s.substring(s.indexOf(matching) + matching.length(), s.indexOf("</li></ul>"));
                    int time = analysisTime(substring);
                    if (time == -2) {
                        System.out.println(channelId + "返回参数中有解析错误的html标签:" + s);
                    }
                    videoInfo.setPublishTime(time);
                    videoInfo.setVideoId(s.substring(hrefStart + 2, hrefEnd));
                    System.out.println(substring);
                    videoInfos.add(videoInfo);
                }
            });

            videoInfos.forEach(System.out::println);
            System.out.println("打印耗时:" + (System.currentTimeMillis() - endEachTime) + "ms");
            System.out.println(countList.size());
        } finally {
            response.close();
        }

    }

    private final static String CH_SECONDS_PRE = "秒前";
    private final static String CH_MINUTES_PRE = "分鐘前";
    private final static String CH_HOURS_PRE = "小時前";
    private final static String CH_DAYS_PRE = "天前";

    private static int analysisTime(String substring) {
        boolean matches = substring.substring(0, 2).trim().matches("^[0-9]*[1-9][0-9]*$");
        int time=-2;
        if(matches){
            time = Integer.parseInt(substring.substring(0, 2).trim());
            if (substring.contains(CH_SECONDS_PRE)) {
                time = time + 0;
            } else if (substring.contains(CH_MINUTES_PRE)) {
                time = time + 100;
            } else if (substring.contains(CH_HOURS_PRE)) {
                time = time + 200;
            } else if (substring.contains(CH_DAYS_PRE)) {
                time = time + 300;
            } else {
                time = -1;
            }
        }

        return time;
    }

VideoInfo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Setter
@Getter
@ToString
public class VideoInfo {
    private String videoId;
    private int publishTime;

}

这里使用的是香港,所以这里匹配获取时间的时候使用了繁体,解释下这里面的匹配规则。

class=”yt-lockup-content”是返回的html中视频主题标签的class,从此开始一个个获取。

analysisTime 秒则直接使用,分钟则为100起,以此类推。

其实在F12调试的时候,这个URL请求获得的是一段json,不知道为什么变成了html,对这方面不是很熟悉,之后会想办法去优化这块。

GET_VEDIO_INFO_PRE这个地址是YouTube的公共API,目前还是可以使用的,可以检索一些视频的信息。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java高效分割字符串
最近优化一段代码的调用时间,发现性能瓶颈居然是io和split!io操作慢情有可原,那么对于split有没有更高效的方法呢?
weishu
2018/09/05
5.4K0
JAVA零基础小白学习教程之day10-API&Object&String
API(Application Programming Interface),应用程序编程接口。Java API是一本程序员的字典 ,是JDK中提供给 我们使用的类的说明文档。这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。所以我们可以通过查询API的方式,来学习Java提供的类,并得知如何使用它们。
张哥编程
2024/12/13
760
探寻Java文件上传流量层面waf绕过姿势
Y4tacker真是太牛逼了,新一代的java王子,每天一花活又强又卷年纪轻轻还有女朋友。
用户7151998
2023/07/24
6880
探寻Java文件上传流量层面waf绕过姿势
【15】JAVASE-常用工具类【从零开始学JAVA】
Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。
用户4919348
2024/05/25
1680
【15】JAVASE-常用工具类【从零开始学JAVA】
Java基础-12(01)总结Scanner,String
1:Scanner的使用(了解) (1)在JDK5以后出现的用于键盘录入数据的类。 (2)构造方法: A:讲解了System.in这个东西。 它其实是标准的输入流,对应于键盘录入 B:构造方法 InputStream is = System.in; Scanner(InputStream is) C:常用的格式 Scanner sc = new Scanner(System.in); (3)基本方法格式: A:hasNextXxx() 判断是否是某种类型的 B:nextXxx() 返
Java帮帮
2018/03/15
7130
Java常用类应用详解
可以通过图查询到其含有的字段和方法,jump to source 可以查看到源码。
timerring
2023/05/01
4810
Java常用类应用详解
JAVA字符串常用api
截取一串字符串的一串子字符串,从from位置的字母(包括from)到end(不包括end位置)的字符串。
用户7886150
2021/02/26
1.2K0
刷算法,这些api不可不知!
在刷题中,各种数据结构是我们常常用到的,例如栈实现迭代、哈希存储键值对等等,我们来看看常用集合和相关api。
三分恶
2021/07/19
5220
刷算法,这些api不可不知!
Java String「建议收藏」
一、构造函数      String(byte[ ] bytes):通过byte数组构造字符串对象。      String(char[ ] value):通过char数组构造字符串对象。      String(Sting original):构造一个original的副本。即:拷贝一个original。      String(StringBuffer buffer):通过StringBuffer数组构造字符串对象。   例如:       byte[] b = {‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’,’i’,’j’};       char[] c = {‘0′,’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9’};       String sb = new String(b);                 //abcdefghij       String sb_sub = new String(b,3,2);     //de       String sc = new String(c);                  //0123456789       String sc_sub = new String(c,3,2);    //34       String sb_copy = new String(sb);       //abcdefghij       System.out.println(“sb:”+sb);       System.out.println(“sb_sub:”+sb_sub);       System.out.println(“sc:”+sc);       System.out.println(“sc_sub:”+sc_sub);       System.out.println(“sb_copy:”+sb_copy);  输出结果:sb:abcdefghij                       sb_sub:de                        sc:0123456789                         sc_sub:34                         sb_copy:abcdefghij
全栈程序员站长
2022/08/03
2750
java基础API
(1)Application Programming Interface,应用程序接口。 是一些预先定义的类和接口,或指软件系统不同组成部分衔接的约定。 (2)API说明文档
全栈程序员站长
2022/09/08
9030
java基础API
Java入门代码练习与记录-1
大学没好好学JAVA,工作后发现JAVA的重要性,这是我在工作之余,重新学习java时手敲的代码练习,这里做下记录。
Tommonkey
2023/03/20
2150
AndroidStudio——利用APIStore获取网络新闻
public class HttpJsonActivity extends AppCompatActivity {
用户7886150
2020/12/31
5870
项目打包成jar包和war包获取文件路径的方法
用户9131103
2023/07/17
3100
你不知道的 equals 和 ==
i1 == i2 和 i1.equals(i2) 这两个都是 true,大多数人应该可以答对。后面的 i3 == i4 和 i3.equals(i4) 估计就有不少人搞不清了。
Wizey
2018/08/30
5150
js indexOf()用法
该方法将从头到尾地检索字符串 stringObject,看它是否含有子串 searchvalue。开始检索的位置在字符串的 fromindex 处或字符串的开头(没有指定 fromindex 时)。如果找到一个 searchvalue,则返回 searchvalue 的第一次出现的位置。stringObject 中的字符位置是从 0 开始的。
全栈程序员站长
2022/09/14
4.3K0
【day16】Java开发常用API
BigInteger类用于处理超出long范围的超大整数。以下是其构造方法和常用操作:
程序员波特
2024/12/25
810
【day16】Java开发常用API
Java Review (二十、基础类库----常用类)
Object 类是所有类、数组、枚举类的父类 ,也就是说, Java 允许把任何类型的对象赋给 Object 类型的变量 。 当定义一个类时没有使用 extends 关键字为它显式指定父类,则该类默认继承 Object 父类。
三分恶
2020/07/16
5670
Java基础之String
(1)多个字符组成的一串数据。 其实它可以和字符数组进行相互转换。 (2)构造方法: public String():空构造。 public String(byte[] bytes):把字节数组转成字符串。 public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串。 public String(char[] value):把字符数组转成字符串。 public String(char[] value,int index,int c
南风
2018/07/02
4940
JDK源码分析 Integer
对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:http://www.cnblogs.com/skywang12345/category/455711.html。
Yano_nankai
2018/10/08
3020
JDK源码分析 Integer
Java-常用类
哈喽!大家好,我是小简。今天开始学习《Java-常用类》,此系列是我做的一个 “Java 从 0 到 1 ” 实验,给自己一年左右时间,按照我自己总结的 Java-学习路线,从 0 开始学 Java 知识,并不定期更新所学笔记,期待一年后的蜕变吧!
小简
2023/01/04
3720
Java-常用类
相关推荐
Java高效分割字符串
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验