爬取滚动加载页面数据
nodejs+puppeteer
之前有写一篇爬取普通网站的数据
nodejs爬虫 爬取爱奇艺 node + cheerio 爬取滚动加载页面
地址
https://blog.csdn.net/qq_43017024/article/details/118786153
但是遇到有反爬策略的网站,查不到页面dom数据的来源接口怎么办呢?
此时我们可以用到 puppeteer
Puppeteer本质上是一个chrome浏览器,只不过可以通过代码进行各种操控。比如模拟鼠标点击、键盘输入等操作,有点像按键精灵,网页很难分清这是人类用户还是爬虫,所以限制也就无处谈起。通过一招简单的模拟用户操作就能破解绝大部分限制,它就是由谷歌出品的爬取动态网页神器Puppeteer。
比如优酷的,犹豫对爬虫的不熟悉,我以为数据就在这几个接口里面,花了一天的时间去找结果什么也没找到,后来发现原来是优酷的反爬策略
直接上代码
const puppeteer = require('puppeteer')
//设置网址
var url = 'https://www.youku.com/'
async function start(bool) {
//启动浏览器,传入headless为false可以打开窗口
const browers = await puppeteer.launch({
headless: bool
})
//启动新页面
const page = await browers.newPage()
//设置页面打开时的页面宽度高度
await page.setViewport({
width: 1920,
height: 1080,
})
//链接网址
await page.goto(url)
var content, $
await page.evaluate(function () {
var top = 0
//每200毫秒滚动100px
var timer = setInterval(() => {
console.log(window.scrollY);
window.scrollTo(0, top += 100)
}, 200);
//15秒后清除定时器并开始获取内容
setTimeout(() => {
clearInterval(timer)
var box = $('.module_mod')
let List = []
for (let i = 0; i < box.length; i++) {
let e = box.eq(i)
let title
let obj = {
title: '',
name: []
}
if (e.find('.module_main_title').length > 0 && e.find('.pack_title').length > 0) {
title = e.find('.module_main_title').eq(0).text()
obj.title = title
let textlist = e.find('.pack_title')
for (let idx = 0; idx < textlist.length; idx++) {
obj.name.push(textlist.eq(idx).text())
}
List.push(obj)
}
if (e.find('.tabs_main_title').length > 0 && e.find('.pack_title').length > 0) {
title = e.find('.tabs_main_title').eq(0).text()
obj.title = title
let textlist = e.find('.pack_title')
for (let idx = 0; idx < textlist.length; idx++) {
obj.name.push(textlist.eq(idx).text())
}
List.push(obj)
}
}
console.log(List);
List = JSON.stringify(List, undefined, 4)
//以下是下载json,创建元素
var ele = document.createElement('a');
//设置下载文件名
ele.download = "youku.json";
//隐藏元素
ele.style.display = "none";
//字符内容转变成blob地址
var blob = new Blob([List], {type: 'text/json'});
//如果是链接,这里也可以直接设置链接地址
ele.href = URL.createObjectURL(blob);
document.body.appendChild(ele);
//模拟点击
ele.click();
//移除元素
document.body.removeChild(ele);
}, 15000);
})
}
start(false)
- 需要注意的是这里的滚动加载我用的是计时器的加载方式,滚动的速度和时间都可以自行更改
- 对于获取页面的一些操作都在setTimeout,这样可以在自动打开的浏览器的控制台里可以console出来
- setTimeout外面的代码会在cmd窗口打印出来,但是因为我的知识盲区太广,我不知道怎么把在setTimeout里面拿到的数据传到外面,还请多多指教
- 任何网站都要有一个分析一下dom布局,找到你想要获取数据的模块,检查是否都一样之后再去获取dom