打开某瓜视频网站的某个列表页,例如 宠物 列表页, 然后按 F12
打开开发者工具,切换到控制台面板,将以下代码粘贴进去,再按 Enter
回车键执行即可。
async function getVideoUrl(url) {
let iframe = document.createElement('iframe')
document.body.appendChild(iframe)
try {
await new Promise((resolve, reject) => Object.assign(iframe, {
onload: resolve, onerror: reject, src: url }))
//anyVideo.gidInformation.packerData.videoResource.normal.video_list
let videoRes;
if (iframe.contentWindow._SSR_HYDRATED_DATA.anyVideo.gidInformation.packerData.video) {
videoRes = iframe.contentWindow._SSR_HYDRATED_DATA.anyVideo.gidInformation.packerData.video.videoResource;
}
else{
videoRes = iframe.contentWindow._SSR_HYDRATED_DATA.anyVideo.gidInformation.packerData.videoResource;
}
let {
video_list: videoList } = videoRes.normal
let key = Object.keys(videoList).sort().pop()
let {
main_url: videoUrl } = videoList[key]
return videoUrl
} finally {
document.body.removeChild(iframe)
}
}
async function download(title, url) {
let board = document.createElement('div')
board.style = `
position: fixed; left: 0; top: 0; z-index: 10000; background: lightgray;
font-size: 20px; line-height: 40px; padding: 18px 2em; box-shadow: #b6b6b6 0 0 20px 14px;
white-space: pre; text-align: center;
`
document.body.appendChild(board)
try {
let xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = 'arraybuffer'
xhr.onprogress = ({
loaded, total }) => board.textContent = `当前任务:${
title}\n进行中:${
(loaded / total * 100).toFixed(1)}%`
await new Promise((resolve, reject) => (Object.assign(xhr, {
onload: resolve, onerror: reject }), xhr.send()))
const {
response } = xhr
return new Blob([response], {
type: 'arraybuffer'})
} finally {
document.body.removeChild(board)
}
}
function retryWrapper(fn, times = 3) {
return async function() {
for (let i = 0; i < times; i++) {
try {
return await fn.apply(this, arguments)
} catch (e) {
await new Promise(resolve => setTimeout(resolve, 500 * Math.pow(2, i)))
}
}
}
}
(async function main() {
let nodeList = document.querySelectorAll('div.HorizontalFeedCard a.HorizontalFeedCard__coverWrapper')
for (let element of nodeList) {
let title = element.getAttribute('title')
let url = location.origin + element.getAttribute('href')
let videoUrl = await retryWrapper(getVideoUrl, 5)(url)
let blob = await retryWrapper(download, 10)(title, videoUrl)
let link = URL.createObjectURL(blob)
Object.assign(document.createElement('a'), {
href: link, download: `${
title}.mp4` }).click()
}
})()
脚本首先遍历列表页所有视频的链接地址,然后创建一个iframe并把iframe的src设置为单个视频链接地址,在iframe的window._SSR_HYDRATED_DATA.anyVideo.gidInformation.packerData.video.videoResource.normal.video_list
里获得视频播放地址,最后显示一个进度条下载视频。