当前位置: 首页 > news >正文

基于JavaScript、puppeteer的爬虫

前期准备:

npm puppeteer

import puppeteer from 'puppeteer';

puppeteer文档

第一步:启动浏览器,跳转到需要爬取的页面

const browser = await puppeteer.launch({ headless: false });const page = await browser.newPage();await page.goto(url, { waitUntil: 'networkidle2' });

第二步:打开需要爬取的网页,按“F12”查看前端的dom,查看我们想获取的文本信息的父级类名,例如:

第三步,通常列表页面都有下拉刷新,我们需要写一个脚本让页面下拉刷新

我要爬取的页面下拉到一定的地步后会有一个“加载更多”按钮,需要点击,直到页面无法滚动,且没有加载更多按钮的时候停止,脚本参考如下:

 // 定义滚动函数const scrollPage = async () => {const distance = 100000; // 每次滚动的距离const delay = 2000; // 每次滚动后的延迟let previousHeight = await page.evaluate('document.body.scrollHeight');while (true) {await page.evaluate(`window.scrollBy(0, ${distance})`);await new Promise(resolve => setTimeout(resolve, delay));const newHeight = await page.evaluate('document.body.scrollHeight');if (newHeight === previousHeight) {const loadMoreButton = await page.$('.类名1.类名2');//锁定“加载更多按钮”if (loadMoreButton) {await loadMoreButton.click();console.log('点击加载更多结果按钮');await new Promise(resolve => setTimeout(resolve, delay)); // 等待加载更多内容} else {console.log('已滚动到底部,没有更多内容加载');break;}}previousHeight = newHeight;}
};await scrollPage();

第四步,封装成对象并打印

第三步的脚本让我们把页面加载到拥有全部数据的状态,现在需要将第二步收集的类名里的文本封装成数组

await page.waitForSelector('.卡片父级类名', { timeout: 60000 });//卡片最外层
const info= await page.evaluate(() => {const cardElements = document.querySelectorAll('.卡片父级类名');//获取所有卡片const arr= [];cardElements.forEach(hotel => {const nameElement = hotel.querySelector('[需要的元素1的属性]');const priceElement = hotel.querySelector('[需要的元素2的属性]');const name = nameElement ? nameElement.innerText.trim() : null;const price = priceElement ? priceElement.innerText.trim() : null;if (name || price) {arr.push({ name, price });}});return arr;
});console.log(JSON.stringify(info, null, 2))// 完事关闭浏览器
await browser.close();

运行

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Unix/Linux】Unix/Linux如何查看系统版本
  • 双系统ubuntu20.04扩容
  • 使用 Qt 和 ECharts 进行数据可视化
  • 百川工作手机实现销售管理微信监控系统
  • The IsA relationship and HasA relationship
  • Ubuntu安装PostgreSQL
  • Python开发 ——循环中的 `continue` 语句
  • DNS隧道
  • Kafka 和 RabbitMQ对比
  • 我跟ai学web知识点:“短链接”
  • React@16.x(51)路由v5.x(16)- 手动实现文件目录参考
  • ARM/Linux嵌入式面经(十):极氪
  • 静态网页基础知识
  • 19_谷歌GoogLeNet(InceptionV1)深度学习图像分类算法
  • C++初探究
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • .pyc 想到的一些问题
  • 2017届校招提前批面试回顾
  • CSS魔法堂:Absolute Positioning就这个样
  • JDK 6和JDK 7中的substring()方法
  • Kibana配置logstash,报表一体化
  • laravel 用artisan创建自己的模板
  • learning koa2.x
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 人脸识别最新开发经验demo
  • 如何学习JavaEE,项目又该如何做?
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 优化 Vue 项目编译文件大小
  • 源码安装memcached和php memcache扩展
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • # 数论-逆元
  • (Note)C++中的继承方式
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (十八)三元表达式和列表解析
  • (算法)大数的进制转换
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)树状数组
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .gitignore
  • .gitignore文件忽略的内容不生效问题解决
  • .java 9 找不到符号_java找不到符号
  • .mysql secret在哪_MYSQL基本操作(上)
  • .net core docker部署教程和细节问题
  • .net core Redis 使用有序集合实现延迟队列
  • .NET Framework 3.5安装教程
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .net和php怎么连接,php和apache之间如何连接
  • /deep/和 >>>以及 ::v-deep 三者的区别