写于 2019-12-18 ,不保证后续可用性。
brew install ffmpeg
npm install fs-extra puppeteer uuid
node ./download-iqiyi-videos.js "http://www.iqiyi.com/v_19rrrwga5s.html" "http://www.iqiyi.com/v_19rso4ypgs.html" ...
const fse = require('fs-extra'); | |
const uuid = require('uuid/v4'); | |
const {spawnSync} = require('child_process'); | |
const puppeteer = require('puppeteer'); | |
// 从视频列表页读取视频URL(在 console 中执行) | |
function getLinks() { | |
let links = document.querySelectorAll('.qy-mod-link-wrap > a'); | |
return Array.from(links).map(link => link.href); | |
} | |
copy(getLinks().join('\n')); | |
async function main(browser) { | |
let failedURLs = []; | |
let videoURLs = process.argv.slice(2); | |
for (let i = 0; i < videoURLs.length; i++) { | |
try { | |
let [m3u8, video] = await getVideoURL(videoURLs[i]); | |
console.log(videoURLs[i], m3u8, video); | |
let {stdout, stderr} = spawnSync('ffmpeg', [ | |
'-y', | |
'-protocol_whitelist', 'file,http,https,tcp,tls', | |
'-i', `tmp/${m3u8}`, | |
'-c:v', 'libx264', '-pix_fmt', 'yuv420p', | |
'-c:a', 'aac', '-ac', '2', '-b:a', '128k', | |
`tmp/${video}` | |
]); | |
console.log('stdout', stdout.toString('utf8')); | |
console.log('stderr', stderr.toString('utf8')); | |
} | |
catch (err) { | |
failedURLs.push(videoURLs[i]); | |
console.log(err); | |
} | |
} | |
console.log(`finish with ${failedURLs.length} error(s).`); | |
console.log('Failed URLs:'); | |
console.log(failedURLs.join('\n')); | |
async function getVideoURL(pageURL) { | |
const page = await browser.newPage(); | |
page.setViewport({ | |
width: 1280, | |
height: 800 | |
}); | |
let promise = new Promise(function (resolve, reject) { | |
page.on('response', async function (res) { | |
if (!res.ok()) { | |
return; | |
} | |
let resURL = res.url(); | |
if (resURL.startsWith('https://cache.video.iqiyi.com/') && resURL.includes('/dash')) { | |
let data = await res.text(); | |
// response is JSONP | |
let i = data.indexOf('({') + 1; | |
let j = data.lastIndexOf(');'); | |
content = data.substring(i, j); | |
try { | |
data = JSON.parse(content); | |
data = data.data; | |
} | |
catch (err) { | |
return | |
} | |
if (!data || !data.program || !data.program.video) return; | |
// TODO: find the video with the highest quality | |
let item = data.program.video.find(item => item.m3u8); | |
if (!item) { | |
reject(new Error('No m3u8 found')); | |
} | |
resolve(item.m3u8); | |
} | |
}); | |
}); | |
await page.goto(pageURL); | |
let title = await page.evaluate(function () { | |
return document.title; | |
}); | |
// TODO: timeout | |
let m3u8 = await promise; | |
let m3u8Filename = `${uuid()}.m3u8`; | |
await fse.writeFile('tmp/' + m3u8Filename, m3u8); | |
await page.close(); | |
return [m3u8Filename, `${title}.mp4`]; | |
} | |
} | |
puppeteer.launch({ | |
headless: false, | |
slowMo: 100, | |
userDataDir: './chrome-user-data' | |
}).then(async browser => { | |
await main(browser); | |
await browser.close(); | |
}).catch(function (err) { | |
console.log(err); | |
process.exit(1); | |
}); |
ดาวโหลดยังไงครับ งงมาก