private static async Task <(string ytInitialData, ListType)> GetYtinitialData(IYouTubeLibeServer server, string url) { var html = await server.GetEnAsync(url); var ytInitialData = Tools.ExtractYtInitialDataFromChannelHtml(html); var type = GetType(ytInitialData); return(ytInitialData, type); }
internal async Task <List <string> > GetVidsFromChannelId2(IYouTubeLibeServer server, string channelId) { //2021/01/10 生放送履歴が無い場合は投稿された動画の一覧になってしまうっぽい。 var url = $"https://www.youtube.com/channel/{channelId}/videos?view=2&live_view=501"; var html = await server.GetEnAsync(url); var matches = Regex.Matches(html, "\"url\":\"/watch\\?v=([^\"]+)\""); var vids = new List <string>(); foreach (Match match in matches) { if (match == null) { continue; } vids.Add(match.Groups[1].Value); } return(vids); }
internal async Task <List <string> > GetVidsFromChannelId2(IYouTubeLibeServer server, string channelId) { var url = $"https://www.youtube.com/channel/{channelId}/live"; var html = await server.GetEnAsync(url); string ytInitialData; try { ytInitialData = Tools.ExtractYtInitialDataFromChannelHtml(html); } catch (ParseException) { if (!html.Contains("ytInitialData")) { //条件がわからないけど結構よくある。 throw new YtInitialDataNotFoundException(url: url, html: html); } else { //空白が無くなったりだとかそういう系だろうか throw new SpecChangedException(html); } } var vids = new List <string>(); var d = DynamicJson.Parse(ytInitialData); //2019/07/19この方法だと直近の生放送を取得する。今現在生放送中とは限らない。数年間生放送していなければ数年前のものを取得することになる。 //生放送中かどうかの判定ができればこれでも良いと思う。 if (d.IsDefined("currentVideoEndpoint") && d.currentVideoEndpoint.IsDefined("watchEndpoint") && d.currentVideoEndpoint.watchEndpoint.IsDefined("videoId")) { var vid = (string)d.currentVideoEndpoint.watchEndpoint.videoId; vids.Add(vid); } return(vids); }
/// <summary> /// /// </summary> /// <param name="server"></param> /// <param name="channelId"></param> /// <returns></returns> /// <exception cref="YtInitialDataNotFoundException"></exception> /// <exception cref="SpecChangedException"></exception> internal async Task <List <string> > GetVidsFromChannelId(IYouTubeLibeServer server, string channelId) { var url = $"https://www.youtube.com/channel/{channelId}/videos?flow=list&view=2"; var html = await server.GetEnAsync(url); var match = Regex.Match(html, "window\\[\"ytInitialData\"\\]\\s*=\\s*({.+?});\\s+", RegexOptions.Singleline); if (!match.Success) { if (!html.Contains("ytInitialData")) { //条件がわからないけど結構よくある。 throw new YtInitialDataNotFoundException(url: url, html: html); } else { //空白が無くなったりだとかそういう系だろうか throw new SpecChangedException(html); } } var list = new List <string>(); try { var ytInitialData = match.Groups[1].Value; var json = JsonConvert.DeserializeObject <Low.ChannelYtInitialData.RootObject>(ytInitialData); var tabs = json.contents.twoColumnBrowseResultsRenderer.tabs; Low.ChannelYtInitialData.Tab videosTab = null; foreach (var tab in tabs) { if (tab.tabRenderer == null) { continue; } if (tab.tabRenderer.title == "Videos") { videosTab = tab; break; } } if (videosTab == null) { return(list); } var contents = videosTab.tabRenderer.content.sectionListRenderer.contents; foreach (var content in contents) { var videoRenderer = content.itemSectionRenderer.contents[0].videoRenderer; //"このチャンネルには動画がありません"のとき、videoRendererがnull if (videoRenderer == null) { continue; } var videoId = videoRenderer.videoId; var isLive = IsLive(videoRenderer.badges); if (isLive) { list.Add(videoId); } } } catch (Exception ex) { throw new SpecChangedException(html, ex); } return(list); }