// ==UserScript== // @name 抖音视频下载工具 // @namespace https://scriptcat.org/zh-CN/users/176579 // @version 1.0.2 // @description 抖音视频下载工具,用于下载抖音视频。一定要看教程,一定要看教程,一定要看教程。 // @author xyz-xyz // @match https://www.douyin.com/* // @connect v3-web.douyinvod.com // @grant GM_xmlhttpRequest // @grant GM_download // @icon https://lf-douyin-pc-web.douyinstatic.com/obj/douyin-pc-web/2025_0313_logo.png // ==/UserScript== (function () { 'use strict'; var pageUrl = window.location.href; (async () => { if (window.self == window.top) { createUi(); } else { if (pageUrl.includes('/video/7558459629781421351')) { await delay(3000); let semiButtonNode = document.querySelector('#douyin-right-container > div.parent-route-container.route-scroll-container.IhmVuo1S > div > div > div.detailPage.W_7gCbBd > div > div.cHwSTMd3 > div.V_bVSPdS > button.semi-button-primary'); if (semiButtonNode) { semiButtonNode.click(); } } else if (pageUrl.includes('/video/')) { await delay(3000); let videoNode = document.querySelector('video'); if (videoNode) { let sourceNode = videoNode.querySelector('source') let showVideo = window.top.document.getElementById('showVideo'); if (showVideo) { showVideo.src = sourceNode.src; log('视频链接获取成功'); showMessage('获取成功', 'green'); log('请点击下载'); } else { log('视频链接获取失败'); } } else { log('视频链接获取失败'); } } } })() async function createUi() { let templateDiv = document.createElement('div'); templateDiv.id = 'templateDiv'; templateDiv.style.cssText = ` padding: 15px; position: fixed; z-index: 999; background-color: #f1f1f1; border: 1px solid #d3d3d3; width: 300px; right: 50px; top: 50px; `; templateDiv.innerHTML = `

抖音视频下载工具

使用帮助:详见脚本发布页

扫描二维码,关注公众号学长喵

公众号二维码

操作日志

视频显示

`; document.body.appendChild(templateDiv); await delay(1000); let bigtosmall = document.getElementById("bigtosmall"); let templateDivBody = document.getElementById("templateDivBody"); bigtosmall.addEventListener('change', function () { if (this.checked) { templateDivBody.style.display = "none"; } else { templateDivBody.style.display = ""; } }); templateDiv = document.getElementById("templateDiv"); let templateDivHeader = document.getElementById("templateDivHeader"); dragElement(templateDiv, templateDivHeader); function dragElement(elmnt, elmnt0) { var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; if (document.getElementById(elmnt.id + "Header")) { document.getElementById(elmnt.id + "Header").onmousedown = dragMouseDown; } else { elmnt.onmousedown = dragMouseDown; } function dragMouseDown(e) { e = e || window.event; e.preventDefault(); pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = closeDragElement; document.onmousemove = elementDrag; } function elementDrag(e) { e = e || window.event; e.preventDefault(); const screenWidth = window.innerWidth; const screenHeight = window.innerHeight; const windowWidth = elmnt.offsetWidth; const windowHeight = elmnt0.offsetHeight; pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; let newX = elmnt.offsetLeft - pos1; let newY = elmnt.offsetTop - pos2; newX = Math.max(0, newX); newX = Math.min(newX, screenWidth - windowWidth); newY = Math.max(0, newY); newY = Math.min(newY, screenHeight - windowHeight - 25); elmnt.style.top = newY + "px"; elmnt.style.left = newX + "px"; } function closeDragElement() { document.onmouseup = null; document.onmousemove = null; } } let base_urlInput = document.getElementById('baseurlInput'); if (!base_urlInput) return; let saveBtn = document.getElementById('saveBtn'); if (saveBtn) saveBtn.addEventListener('click', downloadVideo); let verifyBtn = document.getElementById('verifyBtn'); if (verifyBtn) verifyBtn.addEventListener('click', getVideo); let userIframe = document.createElement('iframe'); userIframe.style.display = ''; userIframe.src = `https://www.douyin.com/video/7558459629781421351`; document.body.appendChild(userIframe); function getVideo() { let iframe = document.createElement('iframe'); iframe.style.display = ''; let videoString = base_urlInput.value; let regex = /https:\/\/v\.douyin\.com\/[^\s]+/; let matchResult = videoString.match(regex); iframe.src = `${matchResult}`; document.body.appendChild(iframe); showMessage('获取视频', 'blue'); log('正在获取视频链接......'); } function downloadVideo() { let showVideo = window.top.document.getElementById('showVideo'); let videoUrl = showVideo.src; if (!videoUrl || !videoUrl.startsWith('http')) { log('视频地址无效,请检查!'); return; } downloadVideoAsMP4(videoUrl); } } function showMessage(text, color) { let messageEl = window.top.document.getElementById('message'); if (messageEl) { messageEl.textContent = text; messageEl.style.color = color; setTimeout(() => { messageEl.textContent = ''; }, 3000); } } function log(message) { let logArea = window.top.document.getElementById('logArea'); if (!logArea) return; let now = new Date(); let timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`; let logEntry = document.createElement('div'); logEntry.style.cssText = 'margin: 3px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 2px;'; logEntry.innerHTML = `[${timeString}] ${message}`; logArea.appendChild(logEntry); logArea.scrollTop = logArea.scrollHeight; } function downloadVideoAsMP4(videoUrl, fileName = `video_${Date.now()}.mp4`) { if (!videoUrl || !videoUrl.startsWith('http')) { alert('视频URL不合法,请检查!'); return; } log(`开始请求视频,请等待片刻.....`); GM_xmlhttpRequest({ method: 'GET', url: videoUrl, responseType: 'blob', headers: { 'User-Agent': navigator.userAgent, 'Referer': window.location.href, 'Accept': '*/*', 'Range': 'bytes=0-' }, onload: function (response) { if (response.status < 200 || response.status >= 300) { alert(`请求失败:${response.status} ${response.statusText}`); return; } const videoBlob = response.response; if (!videoBlob) { alert('未获取到视频二进制数据!'); return; } if (typeof GM_download !== 'undefined') { const blobUrl = URL.createObjectURL(videoBlob); GM_download({ url: blobUrl, name: fileName, saveAs: false, onerror: (error) => { console.error('GM_download失败:', error); fallbackDownload(blobUrl, fileName); }, onload: () => { log(`视频已保存:${fileName}`); URL.revokeObjectURL(blobUrl); } }); } else { const blobUrl = URL.createObjectURL(videoBlob); fallbackDownload(blobUrl, fileName); } }, onerror: function (error) { alert(`请求出错:${error.message}`); console.error('GM_xmlhttpRequest错误:', error); }, ontimeout: function () { alert('请求超时,请检查网络或重试!'); }, timeout: 30000 }); } function fallbackDownload(blobUrl, fileName) { const a = document.createElement('a'); a.href = blobUrl; a.download = fileName; a.style.display = ''; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(blobUrl); log(`原生下载触发:${fileName}`); showMessage('下载成功', 'green'); } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } })();