info.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. const request = async (method, url, data = null, headers = {}) => {
  2. return new Promise(function (resolve, reject) {
  3. const xhr = new XMLHttpRequest();
  4. xhr.open(method, url);
  5. // 设置请求头
  6. Object.keys(headers).forEach(function (key) {
  7. xhr.setRequestHeader(key, headers[key]);
  8. });
  9. xhr.onload = function () {
  10. if (xhr.status >= 200 && xhr.status < 300) {
  11. resolve(xhr.responseText);
  12. } else {
  13. reject(new Error('Request failed with status: ' + xhr.status));
  14. }
  15. };
  16. xhr.onerror = function () {
  17. reject(new Error('Request failed'));
  18. };
  19. xhr.send(data);
  20. });
  21. }
  22. getVideoDetail = async (url) => {
  23. const headers = {
  24. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36',
  25. }
  26. const res = await request('GET', url, null, headers)
  27. let regex = /var ytInitialPlayerResponse\s*=\s*({.*?});/;
  28. let match = res.match(regex);
  29. if (!match || !match.length) {
  30. throw new Error('JSON not found.');
  31. }
  32. const ytInitialPlayerResponse = JSON.parse(match[1]);
  33. console.log(ytInitialPlayerResponse);
  34. const originVideoDetails = ytInitialPlayerResponse["videoDetails"];
  35. const thumbnails = []
  36. for (const item of originVideoDetails["thumbnail"]["thumbnails"]) {
  37. thumbnails.push({
  38. "url": item["url"],
  39. "width": item["width"] + "",
  40. "height": item["height"] + ""
  41. })
  42. }
  43. const formats = []
  44. for (const item of ytInitialPlayerResponse["streamingData"]["formats"].concat(ytInitialPlayerResponse["streamingData"]["adaptiveFormats"])) {
  45. if (item && item["signatureCipher"] && item["mimeType"]) {
  46. let urlRegex = /url=([^&]+)/;
  47. let match = item["signatureCipher"].match(urlRegex);
  48. if (!match) {
  49. continue;
  50. }
  51. const encodedUrl = match[1];
  52. const decodedUrl = decodeURIComponent(encodedUrl);
  53. formats.push({
  54. "width": item["width"] + "",
  55. "height": item["height"] + "",
  56. "type": item["mimeType"],
  57. "quality": item["quality"],
  58. "itag": item["itag"],
  59. "fps": item["fps"] + "",
  60. "bitrate": item["bitrate"] + "",
  61. "url": decodedUrl,
  62. "ext": "mp4",
  63. "vcodec": item["mimeType"],
  64. "acodec": item["mimeType"],
  65. "vbr": "0",
  66. "abr": "0",
  67. "container": "mp4_dash"
  68. })
  69. }
  70. }
  71. regex = /var ytInitialData\s*=\s*({.*?});/;
  72. match = res.match(regex);
  73. if (!match || !match.length) {
  74. throw new Error('JSON not found.');
  75. }
  76. if (!match || !match.length) {
  77. throw new Error('JSON not found.');
  78. }
  79. const ytInitialData = JSON.parse(match[1]);
  80. console.log(ytInitialData);
  81. const recommendInfo = [];
  82. for (const item of ytInitialData["contents"]["twoColumnWatchNextResults"]["secondaryResults"]["secondaryResults"]["results"]) {
  83. if (item["compactVideoRenderer"]) {
  84. const recommendVideo = item["compactVideoRenderer"];
  85. recommendInfo.push({
  86. "type": "gridVideoRenderer",
  87. "videoId": recommendVideo["videoId"],
  88. "title": recommendVideo["title"]["simpleText"],
  89. "thumbnails": recommendVideo["thumbnail"]["thumbnails"],
  90. "channelName": recommendVideo["longBylineText"]["runs"][0]["text"],
  91. "publishedTimeText": recommendVideo["publishedTimeText"]["simpleText"],
  92. "viewCountText": recommendVideo["viewCountText"]["simpleText"],
  93. "shortViewCountText": recommendVideo["shortViewCountText"]["simpleText"],
  94. "lengthText": recommendVideo["lengthText"]["simpleText"]
  95. })
  96. }
  97. }
  98. const videoDetails = {
  99. "isLiveContent": originVideoDetails["isLiveContent"],
  100. "title": originVideoDetails["title"],
  101. "thumbnails": thumbnails,
  102. "description": originVideoDetails["shortDescription"],
  103. "lengthSeconds": originVideoDetails["lengthSeconds"],
  104. "viewCount": originVideoDetails["viewCount"],
  105. "keywords": originVideoDetails["keywords"],
  106. "author": originVideoDetails["author"],
  107. "channelID": originVideoDetails["channelId"],
  108. "recommendInfo": recommendInfo,
  109. "channelURL": `https://www.youtube.com/channel/${originVideoDetails["channelId"]}`,
  110. "videoId": originVideoDetails["videoId"]
  111. }
  112. return {
  113. "code": 200,
  114. "msg": "",
  115. "data": {
  116. "videoDetails": videoDetails,
  117. "streamingData": {
  118. "formats": formats
  119. }
  120. },
  121. "id": "MusicDetailViewModel_detail_url"
  122. }
  123. }