抖音自觉过滤助手

过滤广告、直播、超4分钟的视频【注意:最前面的几个视频无法过滤,因为是直接附属在html页面上。

  1. // ==UserScript==
  2. // @name 抖音自觉过滤助手
  3. // @namespace https://gitee.com/yc556/dy-oil-monkey-filter-video
  4. // @version 2024-08-04
  5. // @description 过滤广告、直播、超4分钟的视频【注意:最前面的几个视频无法过滤,因为是直接附属在html页面上。
  6. // @author 仰晨
  7. // @match *://*.douyin.com/*
  8. // @icon https://7.z.wiki/autoupload/20240504/t0lK.1006X1006-Snipaste_2024-05-04_21-14-39.png
  9. // @grant none
  10. // @license AGPL License
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15. console.log('████抖音自觉助手成功启动█████');
  16. window.videos = {} // 初始化一个装视频url的东东:{描述:视频URL,。。。}
  17. window.ikunCount = 0; // 初始化计数器(秒)
  18. window.index = 1; // 记录在视频简介上加上,这样就真的刷了几个,然后也更好读取了
  19. window.liaoTianIndex = 1; // 【聊天】记录在视频简介上加上,这样就真的刷了几个,然后也更好读取了
  20. window.xihuanIndex = 1; // 【喜欢】记录在视频简介上加上,这样就真的刷了几个,然后也更好读取了
  21. window.videoSpareList = []; // 视频备用列表
  22. const MAX_SECOND = 300 * 1000; //(5分钟) // 定义“最长”的刷视频时间(毫秒)
  23. const ADD_SECOND = 120 * 1000; //(2分钟) // 定义加长的刷视频时间(毫秒)
  24. const SSP_V1URI= 'aweme/v1/web/tab/feed'; // 刷视频列表=星愿浏览器是这样
  25. const SSP_V2URI= 'aweme/v2/web/feed' // 刷视频列表=最新的谷歌是这个
  26. const SS_URI= 'aweme/v1/web/general/search/single' // 搜索视频列表
  27. const LT_URI= 'aweme/v1/web/multi/aweme/detail' // 聊天视频列表
  28. const XH_URI= 'aweme/v1/web/aweme/favorite' // 喜欢视频列表
  29.  
  30. function 处理刷视频列表 (xhr) {
  31. let respJson = JSON.parse(xhr.response)
  32. let durationCount = 0; // 最大的播放时间(毫秒)
  33. // let addIndex = 0; // 添加到备用列表 到2就好了
  34. const accordWithVideoList = []
  35. // 遍历拿到的视频列表 进行处理
  36. for (let i = 0; i < respJson.aweme_list.length; i++) {
  37. const item = respJson.aweme_list[i]
  38. const isVideo = item.video // 是否视频
  39. const haveTag = item.video_tag // 视频标签 有标签才是正常视频
  40. const noOutTime = isVideo?.duration < 1000 * 60 * 4 // 视频不超4分钟
  41. const noAvatarLarger = !item.author?.avatar_larger // 正常视频没有这个属性
  42.  
  43. if (isVideo && haveTag && noOutTime && noAvatarLarger) {
  44. item.desc += ` ——》》》${window.index}` // 在描述上加上标记
  45. window.videos[window.index] = [item.video.play_addr.url_list[0], item.desc] // 保存到win好读取
  46. window.index++
  47. console.log('███████window.ikunCount>>>>', window.ikunCount,'<<<<██████')
  48. console.log('███████durationCount>>>>', durationCount,'<<<<██████')
  49. console.log('███████window.ikunCount * 1000 + durationCount <= MAX_SECOND>>>>', window.ikunCount * 1000 + durationCount <= MAX_SECOND,'<<<<██████')
  50. console.log('█████████████████████████████████████████████████████████████████████████████████████████████████')
  51. if(window.ikunCount * 1000 + durationCount <= MAX_SECOND) {
  52. accordWithVideoList.push(item)
  53. durationCount += isVideo?.duration ?? 0 // 加入播放列表
  54. // } else if (((isVideo?.duration || 0) <= ADD_SECOND) && (addIndex < 2)) {
  55. } else if ((isVideo?.duration || 0) <= ADD_SECOND) {
  56. window.videoSpareList.push(item)
  57. // addIndex++
  58. }
  59. }
  60. }
  61. 刷新可下载视频列表()
  62. respJson.aweme_list = accordWithVideoList // 替换 过滤后的视频列表
  63. console.log('██████处理后的刷视频列表>', respJson);
  64. return respJson;
  65. }
  66.  
  67. function 处理搜索视频列表(xhr) {
  68. let respJson = JSON.parse(xhr.response)
  69. // 遍历拿到的视频列表 进行描述添加标记,然后保存到win好读取
  70. for (let i = 0; i < respJson.data.length; i++) {
  71. respJson.data[i].aweme_info.desc += ` ——》》》${window.index}`
  72. // 记录url和描述
  73. window.videos[window.index] = [respJson.data[i]?.aweme_info?.video?.play_addr?.url_list?.[2], respJson.data[i]?.aweme_info?.desc]
  74. window.index++
  75. }
  76. 刷新可下载视频列表()
  77. console.log('██████处理后的搜索视频列表>', respJson);
  78. return respJson;
  79. }
  80.  
  81. function 处理聊天视频列表(xhr) {
  82. let respJson = JSON.parse(xhr.response)
  83. // 遍历拿到的视频列表 进行描述添加标记,然后保存到win好读取
  84. for (let i = 0; i < respJson.aweme_details.length; i++) {
  85. respJson.aweme_details[i].desc += ` ——》》》LT${window.liaoTianIndex}`
  86. window.videos['LT' + window.liaoTianIndex] = [respJson.aweme_details[i]?.video?.play_addr?.url_list?.[0], respJson.aweme_details[i].desc]
  87. window.liaoTianIndex++
  88. }
  89. 刷新可下载视频列表()
  90. console.log('██████处理后的聊天视频列表>', respJson);
  91. return respJson;
  92. }
  93.  
  94. function 处理喜欢视频列表(xhr) {
  95. let respJson = JSON.parse(xhr.response)
  96. // 遍历拿到的视频列表 进行描述添加标记,然后保存到win好读取
  97. for (let i = 0; i < respJson.aweme_list.length; i++) {
  98. respJson.aweme_list[i].desc += ` ——》》》XH${window.xihuanIndex}`
  99. window.videos['XH' + window.xihuanIndex] = [respJson.aweme_list[i]?.video?.play_addr?.url_list?.[0], respJson.aweme_list[i].desc]
  100. window.xihuanIndex++
  101. }
  102. 刷新可下载视频列表()
  103. console.log('██████处理后的聊天视频列表>', respJson);
  104. return respJson;
  105. }
  106.  
  107. // ————————————————————————⭐⭐⭐拦截请求修改响应数据⭐⭐⭐————————————————————————————————
  108. function setupHook(xhr) {
  109. function getter() {
  110. delete xhr.responseText; // 不delete将造成递归
  111. let res = xhr.responseText;
  112. // 是视频列表获取请求
  113. if (xhr.responseURL.includes(SSP_V1URI,23) || xhr.responseURL.includes(SSP_V2URI,23)) {
  114. if (window.videoSpareList.length === 0) res = JSON.stringify(处理刷视频列表(xhr))
  115. if (window.videoSpareList.length === 1) res = JSON.stringify(window.videoSpareList.shift())
  116. if (window.videoSpareList.length === 2) {
  117. res = JSON.stringify(window.videoSpareList)
  118. window.videoSpareList = []
  119. }
  120. if (window.videoSpareList.length > 2) {
  121. res = JSON.stringify(window.videoSpareList.slice(0, 2))
  122. window.videoSpareList = window.videoSpareList.slice(2)
  123. }
  124. }
  125. if (xhr.responseURL.includes(SS_URI,23))
  126. res = JSON.stringify(处理搜索视频列表(xhr))
  127. if (xhr.responseURL.includes(LT_URI,23))
  128. res = JSON.stringify(处理聊天视频列表(xhr))
  129. if (xhr.responseURL.includes(XH_URI,23))
  130. res = JSON.stringify(处理喜欢视频列表(xhr))
  131.  
  132. setup();
  133. return res;
  134. }
  135.  
  136. function setter(str) {
  137. console.log('set response: %s', str);
  138. }
  139.  
  140. function setup() {
  141. Object.defineProperty(xhr, 'responseText', {
  142. get: getter,
  143. set: setter,
  144. configurable: true
  145. });
  146. }
  147.  
  148. setup();
  149. }
  150.  
  151.  
  152. // ⭐——————————————捕捉请求——————————————⭐
  153. const oldOpen = XMLHttpRequest.prototype.open;
  154. XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
  155. if ((url.includes(SSP_V1URI) || url.includes(SSP_V2URI))) console.log('█████##>>>看了:', window.ikunCount)
  156. if (window.ikunCount > 300 && (url.includes(SSP_V1URI) || url.includes(SSP_V2URI))) return console.log('█████##>>>>够钟,没得看了<<<<##████')
  157.  
  158. if (!this._hooked) {
  159. this._hooked = true;
  160. setupHook(this);
  161. }
  162.  
  163. oldOpen.apply(this, arguments);
  164. }
  165.  
  166.  
  167. /**
  168. * 刷视频界面计时器
  169. *
  170. * @author Yc
  171. * @since 2024/5/4 20:55
  172. */
  173. setInterval(()=>{
  174. if (document.visibilityState === 'visible') window.ikunCount++;
  175. }, 1000);
  176.  
  177. /**
  178. * 创建下载按钮
  179. *
  180. * @author Yc
  181. * @since 2024/7/28 18:32
  182. */
  183. (function () {
  184. const downloadButton = document.createElement('div');
  185. downloadButton.style.position = 'fixed';
  186. downloadButton.style.bottom = '1px';
  187. downloadButton.style.right = '1px';
  188. downloadButton.style.backgroundColor = 'green';
  189. downloadButton.style.borderRadius = '50%';
  190. downloadButton.style.width = '20px';
  191. downloadButton.style.height = '20px';
  192. downloadButton.style.zIndex = '9999';
  193. downloadButton.style.opacity = '0.5';
  194. downloadButton.style.textAlign = 'center';
  195. downloadButton.innerText = '↓';
  196. downloadButton.addEventListener('mouseover', () => window.downloadList.style.display = 'block')
  197.  
  198. window.downloadList = document.createElement('div');
  199. window.downloadList.style.display = 'none';
  200. window.downloadList.style.position = 'fixed';
  201. window.downloadList.style.top = '0px';
  202. window.downloadList.style.right = '0px';
  203. window.downloadList.style.backgroundColor = 'white';
  204. window.downloadList.style.width = '10vw';
  205. window.downloadList.style.height = '100vh';
  206. window.downloadList.style.zIndex = '9999';
  207. window.downloadList.style.opacity = '0.8';
  208. window.downloadList.style.overflow = 'auto'; // 启用滚动条
  209. window.downloadList.style.transform = 'translateZ(0)'; // 确保 div 完全独立于页面的其他部分
  210. window.downloadList.innerHTML = '<h2>可下载视频列表</h2>';
  211. // 事件监听器 不这样移到他的子元素时也会马上被隐藏
  212. let isInDiv = false;
  213. window.downloadList.addEventListener('mouseover', () => isInDiv = true);
  214. window.downloadList.addEventListener('mouseout', () => {
  215. isInDiv = false;
  216. setTimeout(() => {
  217. if (!isInDiv) window.downloadList.style.display = 'none';
  218. }, 100); // 延迟一段时间来确保鼠标确实离开了 div
  219. });
  220.  
  221. const rootElement = document.querySelector('body');
  222. rootElement.appendChild(downloadButton);
  223. rootElement.appendChild(window.downloadList);
  224. })()
  225.  
  226. function 刷新可下载视频列表() {
  227. let 列表内容 = '<h2>-可下载视频列表-</h2>';
  228. Reflect.ownKeys(window.videos).forEach(key => {
  229. 列表内容 += `
  230. <li style="border: 1px solid #8dbaec; border-radius: 15px; padding-left: 5px; margin: 5px;" title="${window.videos[key][1]}">
  231. <a href="${window.videos[key][0]}" target="_blank">可下视频${key}</a>
  232. </li>`;});
  233. window.downloadList.innerHTML = 列表内容;
  234. }
  235. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址