输入关键字 抓取所有网页(Node批量爬取头条视频地址A坑库)

优采云 发布时间: 2021-10-21 08:04

  输入关键字 抓取所有网页(Node批量爬取头条视频地址A坑库)

  需要

  通过抖音的首页链接下载该用户的所有视频

  想法

  分析发现视频地址都是通过一个接口返回的,手动复制数据过滤掉需要的视频地址A

  坑①:

  地址A在浏览器的手机模式下只会跳转到真实的视频地址B

  查资料发现神器Puppeteer的中文文档

  Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。

  您可以在浏览器中手动执行的大部分操作都可以使用 Puppeteer 完成!这里有些例子:

  解决办法是:模仿iphone6打开页面,然后通过document.querySelector('source').src获取实际播放地址

  getUrl.js

// 获取视频实际下载链接

const puppeteer = require('puppeteer');

const devices = require('puppeteer/DeviceDescriptors');

const iPhone = devices['iPhone 6'];

const getUrl = async (item) => {

const browser = await puppeteer.launch(); //启动浏览器实例

const page = await browser.newPage(); //创建一个新页面

await page.emulate(iPhone); //模拟iphone6打开页面

await page.goto(item.url); //进入指定网页

const result = await page.evaluate((item) => {

let url = document.querySelector('source').src;

return {

title: item.title,

url

}

}, item);

await browser.close();

return result;

}

module.exports = getUrl

  下载视频

  这里直接参考Node对头条视频的批量抓取和保存方法的写法

  download.js

// 下载视频

const fs = require('fs');

const http = require('http');

const config = require('./config');

function getVideoData(url, encoding) {

return new Promise((resolve, reject) => {

let req = http.get(url, function (res) {

let result = ''

encoding && res.setEncoding(encoding)

res.on('data', function (d) {

result += d

})

res.on('end', function () {

resolve(result)

})

res.on('error', function (e) {

reject(e)

})

})

req.end()

})

}

function savefileToPath(fileName, fileData) {

let fileFullName = `${config.savePath}/${fileName}.mp4`

return new Promise((resolve, reject) => {

fs.writeFile(fileFullName, fileData, 'binary', function (err) {

if (err) {

console.log('savefileToPath error:', err)

}

resolve('已下载')

})

})

}

async function downloadVideo(video) {

// 判断视频文件是否已经下载

if (!fs.existsSync(`${config.savePath}/${video.title}.mp4`)) {

await getVideoData(video.url, 'binary').then(fileData => {

console.log('下载视频中:', video.title)

savefileToPath(video.title, fileData).then(res =>

console.log(`${res}: ${video.title}`)

)

})

} else {

console.log(`视频文件已存在:${video.title}`)

}

}

module.exports = downloadVideo

  以上都可以实现后,研究如何获取所有视频链接

  解决方案:仍然使用puppeteer获取请求完成事件并获取请求正文

  注:为保证能拿到所有的视频,需要滚动到模拟页面底部,没有更多的视频,然后抓取数据

  完成:

  判断页面是否滚动到底部

  let isScrollEnd = false

let scroll_timer = null

$(window).scroll(function () {

var scrollTop = $(this).scrollTop();

var scrollHeight = $(document).height();

var windowHeight = $(this).height();

// 防止滚动过快,接口较慢,500ms后再去判断

clearTimeout(scroll_timer)

scroll_timer = setTimeout(() => {

if (scrollTop + windowHeight >= scrollHeight) {

isScrollEnd = true

console.log("that.isScrollEnd", isScrollEnd)

}

}, 500)

});

  操作浏览器滚动到底部时停止

  坑评价范围

  await page.evaluate(async (aa) => {

这里是node自己打开的浏览器作用域,无法直接取到外部的变量,需要通过参数传入,如aa

且无法传入this这类无法序列化的参数

},aa);

  优化部分

  通过config.js配置各种参数

  module.exports = {

isShowChrome: false, //是否显示chrome浏览器

ajaxKey: 'v2/aweme/post',//接口的关键字,防止对所有接口都获取数据

ajaxPath: 'video.play_addr.url_list[0]',//视频在接口里的路径

inputUrl: 'https://v.douyin.com/qKDN9n/',//输入的链接,后期由页面传入吧

savePath: './output',//保存路径

isDownload: true,//是否下载视频

isSaveJsonData: false, //是否保存json数据,如获取到的接口数据和整理后的视频数据

}

  全码地址

  参考

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线