我找不到任何信息来检查YouTube频道是否实际上是流媒体。与Twitch你只需要频道名,与API,你可以检查是否有一个直播或不。
我不想使用OAuth,通常一个公共API密钥就足够了。比如查看一个频道的视频,我想知道这个频道是否在播放。
可以使用search.list
并指定通道ID,将类型设置为video
,将eventType
设置为live
。
例如,当我搜索:
https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCXswCcAMb5bvEUIDEzXFGYg&type=video&eventType=live&key=[API_KEY]
我得到了以下内容:
{
"kind": "youtube#searchListResponse",
"etag": ""sGDdEsjSJ_SnACpEvVQ6MtTzkrI/gE5P_aKHWIIc6YSpRcOE57lf9oE"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#searchResult",
"etag": ""sGDdEsjSJ_SnACpEvVQ6MtTzkrI/H-6Tm7-JewZC0-CW4ALwOiq9wjs"",
"id": {
"kind": "youtube#video",
"videoId": "W4HL6h-ZSws"
},
"snippet": {
"publishedAt": "2015-09-08T11:46:23.000Z",
"channelId": "UCXswCcAMb5bvEUIDEzXFGYg",
"title": "Borussia Dortmund vs St. Pauli 1-0 Live Stream",
"description": "Borussia Dortmund vs St. Pauli Live Stream Friendly Match.",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/W4HL6h-ZSws/default.jpg"
},
"medium": {
"url": "https://i.ytimg.com/vi/W4HL6h-ZSws/mqdefault.jpg"
},
"high": {
"url": "https://i.ytimg.com/vi/W4HL6h-ZSws/hqdefault.jpg"
}
},
"channelTitle": "",
"liveBroadcastContent": "live"
}
}
]
}
搜索方法(https://www.googleapis.com/youtube/v3/search)使用起来非常昂贵。默认情况下,您拥有10,000个配额单位,它需要花费100个配额单位(https://developers.google.com/youtube/v3/determine_quota_cost)。这意味着你每天只能收到100个请求,这很糟糕。
您可以请求增加配额,但这似乎是暴力强迫的问题。
真的没有其他更简单的方法吗?
伙计们,我找到了更好的方法。是的,它要求您对YouTube页面进行GET请求并解析HTML, 但它将与新版本一起工作+征得同意+与captcha一起工作(最有可能,90%)
您所需要做的就是向https://youtube.com/channel/[CHANNELID]/live
发出请求并检查<link rel="canonical" />
标签的href
属性。
<link rel="canonical" href="https://www.youtube.com/channel/UC4cueEAH9Oq94E1ynBiVJhw">
表示没有直播,而
<link rel="canonical" href="https://www.youtube.com/watch?v=SR9w_ofpqkU">
表示有一个流,你甚至可以通过videoid
获取它的数据。
由于规范URL对SEO非常重要,重定向在GET
或HEAD
请求中不再工作,我建议使用我的方法。
下面是我使用的简单脚本:
import { parse } from 'node-html-parser'
import fetch from 'node-fetch'
const channelID = process.argv[2] // process.argv is array of arguments passed in console
const response = await fetch(`https://youtube.com/channel/${channelID}/live`)
const text = await response.text()
const html = parse(text)
const canonicalURLTag = html.querySelector('link[rel=canonical]')
const canonicalURL = canonicalURLTag.getAttribute('href')
const isStreaming = canonicalURL.includes('/watch?v=')
console.log(isStreaming)
然后运行npm init -y && npm i node-html-parser node-fetch
在工作目录下创建项目并安装依赖项
然后运行node isStreaming.js UC4cueEAH9Oq94E1ynBiVJhw
,它将打印true/false(每次执行400-600毫秒)
它确实需要你依赖于node-html-parser
和node-fetch
,但你可以用内置的HTTP库(这很糟糕)发出请求,并将其重写为使用正则表达式。(不要用regex解析HTML)
我知道这很老了,但是我自己用PHP解决了这个问题。
$API_KEY = 'your api3 key';
$ChannelID = 'the users channel id';
$channelInfo = 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId='.$ChannelID.'&type=video&eventType=live&key='.$API_KEY;
$extractInfo = file_get_contents($channelInfo);
$extractInfo = str_replace('},]',"}]",$extractInfo);
$showInfo = json_decode($extractInfo, true);
if($showInfo['pageInfo']['totalResults'] === 0){
echo 'Users channel is Offline';
} else {
echo 'Users channel is LIVE!';
}
我也在与API限制作斗争。我发现最可靠和最便宜的方法是简单地将HEAD
请求到https://www.youtube.com/channel/CHANNEL_ID/live
。如果频道是直播的,那么它将自动加载流。如果没有,那么它将加载频道视频馈送。您可以简单地检查Content-Length
报头大小来确定哪个。
根据你所在的地区,你可能需要接受cookie同意页面。只需发送您的请求与cookies={ "CONSENT": "YES+cb.20210420-15-p1.en-GB+FX+634" }
.
如果你指向streamlink在https://www.youtube.com/channel/CHANNEL_ID/live
链接,它会告诉你是否直播
-
。Lofi节拍通常是现场的,
$ streamlink "https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow/live" [cli][info] Found matching plugin youtube for URL https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow/live Available streams: 144p (worst), 240p, 360p, 480p, 720p, 1080p (best)
-
而MKBHD不是
$ streamlink "https://www.youtube.com/c/mkbhd/live" [cli][info] Found matching plugin youtube for URL https://www.youtube.com/c/mkbhd/live error: Could not find a video on this page
我找到的最简单的方法就是抓取站点。这可以通过查找以下内容来实现:<link rel="canonical" href="linkToActualYTLiveVideoPage">
正如Vitya的回答。
bs4
的简单Python代码:
import requests
from bs4 import BeautifulSoup
def is_liveYT():
channel_url = "https://www.youtube.com/c/LofiGirl/live"
page = requests.get(channel_url, cookies={'CONSENT': 'YES+42'})
soup = BeautifulSoup(page.content, "html.parser")
live = soup.find("link", {"rel": "canonical"})
if live:
print("Streaming")
else:
print("Not Streaming")
if __name__ == "__main__":
is_liveYT()
这很奇怪,老实说,YouTube没有一个简单的方法通过API来做到这一点,尽管这可能更容易。
我发现@VityaSchel的答案非常有用,但它不区分有直播计划的频道和那些正在直播的频道。
为了区分预定和直播,我扩展了他的代码来访问YouTube Data API以查找直播细节:
import { parse } from 'node-html-parser'
import fetch from 'node-fetch'
const youtubeAPIkey = 'YOUR_YOUTUBE_API_KEY'
const youtubeURLbase = 'https://www.googleapis.com/youtube/v3/videos?key=' + youtubeAPIkey + '&part=liveStreamingDetails,snippet&id='
const c = {cid: process.argv[2]} // process.argv is array of arguments passed in console
const response = await fetch(`https://youtube.com/channel/${c.cid}/live`)
const text = await response.text()
const html = parse(text)
const canonicalURLTag = html.querySelector('link[rel=canonical]')
const canonicalURL = canonicalURLTag.getAttribute('href')
c.live = false
c.configured = canonicalURL.includes('/watch?v=')
if (!c.configured) process.exit()
c.vid = canonicalURL.match(/(?<==).*/)[0]
const data = await fetch(youtubeURLbase + c.vid).then(response => response.json())
if (data.error) {
console.error(data)
process.exit(1)
}
const i = data.items.pop() // pop() grabs the last item
c.title = i.snippet.title
c.thumbnail = i.snippet.thumbnails.standard.url
c.scheduledStartTime = i.liveStreamingDetails.scheduledStartTime
c.live = i.liveStreamingDetails.hasOwnProperty('actualStartTime')
if (c.live) {
c.actualStartTime = i.liveStreamingDetails.actualStartTime
}
console.log(c)
上面的输出示例:
% node index.js UCNlfGuzOAKM1sycPuM_QTHg
{
cid: 'UCNlfGuzOAKM1sycPuM_QTHg',
live: true,
configured: true,
vid: '8yRgYiNH39E',
title: '🔴 Deep Focus 24/7 - Ambient Music For Studying, Concentration, Work And Meditation',
thumbnail: 'https://i.ytimg.com/vi/8yRgYiNH39E/sddefault_live.jpg',
scheduledStartTime: '2022-05-23T01:25:00Z',
actualStartTime: '2022-05-23T01:30:22Z'
}
每个YouTube频道作为永久直播,即使该频道目前没有积极直播。在liveStream
资源中,您可以找到一个名为isDefaultStream
的布尔值。
但是我们从哪里可以得到这个视频(直播)id?转到https://www.youtube.com/user/CHANNEL_ID/live
,右键点击流,复制视频URL。
您现在可以向https://youtube.googleapis.com/youtube/v3/videos?part=liveStreamingDetails&id=[VIDEO_ID]&key=[API_KEY]
(该请求的配额成本为1个单位,见这里)
如果流当前是活动的/在线的,这将是结果。
{
"kind": "",
"etag": "",
"items": [
{
"kind": "",
"etag": "",
"id": "",
"liveStreamingDetails": {
"actualStartTime": "",
"scheduledStartTime": "",
"concurrentViewers": "",
"activeLiveChatId": ""
}
}
],
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 1
}
}
如果流当前处于离线状态,则属性concurrentViewers
不存在。换句话说,在线和离线直播之间的唯一区别是concurrentViewers
是否存在。有了这些信息,您就可以检查频道当前是否正在流式传输(至少对于它的默认流式传输)。
考虑到搜索操作的成本,我发现youtube API非常受限。使用aiohttp和beautifulsoup抓取网页不是一个选择,因为更好的指示器需要javascript支持。因此,我转向硒。我寻找css选择器
#info-text
然后搜索字符串Started streaming
或其中包含watching now
。
你也可以用flask在heroku上运行一个小API。
这是另一个不使用YouTube Data API的解决方案。如果你解析出这些元标签,它们会告诉你这是否是一个直播以及开始时间。如果缺少这些标签,则表示频道不是活动的。
也有额外的元标签,列出标题,描述和其他有用的信息。
要查看它是否是一个计划流,只需检查startDate并将其与当前时间进行比较。
<span itemprop="publication" itemscope itemtype="http://schema.org/BroadcastEvent">
<meta itemprop="isLiveBroadcast" content="True">
<meta itemprop="startDate" content="2022-07-13T21:47:38+00:00">
</span>
您可以通过以下方式查询这些标签:
document.querySelector('meta[itemprop="isLiveBroadcast"]').content === "True"
旁注:您甚至不需要解析HTML就可以知道,因为如果频道不是活动的,标记将根本不存在,所以这里有一个快速而肮脏的解决方案:
const data = await fetch(`https://www.youtube.com/[id]/live`)
const isLive = (await data.text()).includes('isLiveBroadcast')