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

【Nodejs】Puppeteer\爬虫实践

在这里插入图片描述

puppeteer

文档:puppeteer.js中文文档|puppeteerjs中文网|puppeteer爬虫教程

Puppeteer本身依赖6.4以上的Node,但是为了异步超级好用的async/await,推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高,centos服务器依赖偏稳定,v6很难使用headless Chrome,提升依赖版本可能出现各种服务器问题(包括且不限于无法使用ssh),最好使用高版本服务器。

Puppeteer因为是一个npm的包,所以安装很简单:

pnpm i puppeteer-core

puppeteer会自动安装一个谷歌浏览器的安装包,所以选择core版,但是得指定启动路径

使用和例子

Puppeteer类似其他框架,通过操作Browser实例来操作浏览器作出相应的反应。

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('http://rennaiqian.com');await page.screenshot({path: 'example.png'});await page.pdf({path: 'example.pdf', format: 'A4'});await browser.close();
})();

上述代码通过puppeteer的launch方法生成了一个browser的实例,对应于浏览器,launch方法可以传入配置项,比较有用的是在本地调试时传入{headless:false}可以关闭headless模式。

const browser = await puppeteer.launch({headless:false})

browser.newPage方法可以打开一个新选项卡并返回选项卡的实例page,通过page上的各种方法可以对页面进行常用操作。上述代码就进行了截屏和打印pdf的操作。

一个很强大的方法是page.evaluate(pageFunction, ...args),可以向页面注入我们的函数,这样就有了无限可能

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('http://rennaiqian.com');// Get the "viewport" of the page, as reported by the page.const dimensions = await page.evaluate(() => {return {width: document.documentElement.clientWidth,height: document.documentElement.clientHeight,deviceScaleFactor: window.devicePixelRatio};});console.log('Dimensions:', dimensions);await browser.close();
})();

需要注意的是evaluate方法中是无法直接使用外部的变量的,需要作为参数传入,想要获得执行的结果也需要return出来。因为是一个开源一个多月的项目,现在项目很活跃,所以使用时自行查找api才能保证参数、使用方法不会错。

调试技巧

① 关掉无界面模式,有时查看浏览器显示的内容是很有用的。使用以下命令可以启动完整版浏览器:

const browser = await puppeteer.launch({headless: false})

② 减慢速度,slowMo选项以指定的毫秒减慢Puppeteer的操作。这是另一个看到发生了什么的方法:

const browser = await puppeteer.launch({headless:false,slowMo:250
});

③捕获console的输出,通过监听console事件。在page.evaluate里调试代码时这也很方便:

page.on('console', msg => console.log('PAGE LOG:', ...msg.args));
await page.evaluate(() => console.log(`url is ${location.href}`));

爬虫实践

很多网页通过user-agent来判断设备,可以通过page.emulate(options)来进行模拟。options有两个配置项,一个为userAgent,另一个为viewport可以设置宽度(width)、高度(height)、屏幕缩放(deviceScaleFactor)、是否是移动端(isMobile)、有无touch事件(hasTouch)。

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];puppeteer.launch().then(async browser => {const page = await browser.newPage();await page.emulate(iPhone);await page.goto('https://www.example.com');// other actions...await browser.close();
});

上述代码则模拟了iPhone6访问某网站,其中devices是puppeteer内置的一些常见设备的模拟参数。

很多网页需要登录,有两种解决方案:

让puppeteer去输入账号密码 常用方法:点击可以使用page.click(selector[, options])方法,也可以选择聚焦page.focus(selector)。 输入可以使用page.type(selector, text[, options])输入指定的字符串,还可以在options中设置delay缓慢输入更像真人一些。也可以使用keyboard.down(key[, options])来一个字符一个字符的输入。 如果是通过cookie判断登录状态的可以通过page.setCookie(...cookies),想要维持cookie可以定时访问。
Tip:有些网站需要扫码,但是相同域名的其他网页却有登录,就可以尝试去可以登录的网页登录完利用cookie访问跳过扫码。

简单例子

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch({headless: false});const page = await browser.newPage();await page.goto('https://baidu.com');await page.type('#kw', 'puppeteer', {delay: 100});page.click('#su')await page.waitFor(1000);const targetLink = await page.evaluate(() => {return [...document.querySelectorAll('.result a')].filter(item => {return item.innerText && item.innerText.includes('Puppeteer的入门和实践')}).toString()});await page.goto(targetLink);await page.waitFor(1000);browser.close();
})()

在这里插入图片描述

多元素处理

const puppeteer = require('puppeteer-core');(async function () {//puppeteer.launch实例开启浏览器,//可以传入一个options对象,可以配置为无界面浏览器,也可以配置为有界面浏览器//无界面浏览器性能更高更快,有界面一般用于调试开式let options = {//设置视窗的宽高defaultViewport: {width: 1400,height: 800,},//设置为有界面,如果为true,即为无界面// headless: false,args: ['--window-size=1400,700'],//指定浏览器路径executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',};let browser = await puppeteer.launch(options);//打开新页面let page = await browser.newPage();//访问页面await page.goto('https://www.jd.com/');//截屏//   await page.screenshot({ path: 'example.png', fullPage: true });//获取页面内容// page.$eval相当于querySelector,然后在对这个元素进行dom操作// page.$$eval相当于querySelectorAll,然后在对这个元素进行dom操作let input = await page.$('#key');await input.type('手机');await page.keyboard.press('Enter');await page.waitForSelector('.gl-warp>.gl-item:last-child');const lis = await page.$$eval('.gl-warp>.gl-item', els =>//这个el就是获取到的对象//这里可以使用dom操作// console.log(el);els.map(item => item.innerText));//这个lis就是上面回调函数的返回值console.log(lis);//关闭浏览器await browser.close();
})();

输入文本与元素点击

const puppeteer = require('puppeteer-core');
(async function () {let options = {defaultViewport: {width: 1400,height: 800,},headless: false,args: ['--window-size=1400,700'],executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',};let browser = await puppeteer.launch(options);let page = await browser.newPage();await page.goto('https://www.ygdy8.com/index.html');//获取页面内容//  page.$相当于querySelector//  page.$$相当于querySelectorAll//这些返回的是一个elementHandle对象const input = await page.$('input[name="keyword"]'); // 定位输入框/*  1input.focus()page.keyboard.type("电影") *///2await input.type('电影');/* 1  elementHandle.click()const search = await page.$('input[name="Submit"]'); // 定位搜索按钮await search.click();  // 点击 *///2await page.click('input[name="Submit"]');
})();

获取元素的文本值

const puppeteer = require('puppeteer-core');
(async function () {let options = {defaultViewport: {width: 1400,height: 700,},args: ['--window-size=1400,700'],headless: false,executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',};let browser = await puppeteer.launch(options);let page = await browser.newPage();await page.goto('https://www.baidu.com/');let input = await page.waitForSelector('#kw');await input.type('hello world');let btn = await page.$('#su');btn.click();/* 等待指定的选择器匹配的元素出现在页面中,如果调用此方法时已经有匹配的元素,那么此方法立即返回。如果指定的选择器在超时时间后扔不出现,此方法会报错。 返回: <Promise<ElementHandle>>*/await page.waitForSelector('div#content_left > div.result-op.c-container.xpath-log');let text = await page.$eval('div#content_left > div.result-op.c-container.xpath-log',el => el.innerText);console.log(text);
})();

处理js方法

const puppeteer = require('puppeteer-core');
(async function () {let options = {defaultViewport: {width: 1400,height: 700,},args: ['--window-size=1400,700'],// headless: false,executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',};let browser = await puppeteer.launch(options);let page = await browser.newPage();await page.goto('https://www.baidu.com/');let input = await page.waitForSelector('#kw');await input.type('hello world');let btn = await page.$('#su');btn.click();await page.waitForSelector('div#content_left > div.result-op.c-container.xpath-log');//里面可以直接写js代码let text = await page.evaluate(() => {let div = document.querySelector('div#content_left > div.result-op.c-container.xpath-log');return div.innerText;});console.log(text);
})();

相关文章:

【Nodejs】Puppeteer\爬虫实践

puppeteer 文档:puppeteer.js中文文档|puppeteerjs中文网|puppeteer爬虫教程 Puppeteer本身依赖6.4以上的Node&#xff0c;但是为了异步超级好用的async/await&#xff0c;推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高&#xff0c;c…...

Windows Active Directory密码同步

大多数 IT 环境中&#xff0c;员工需要记住其默认 Windows Active Directory &#xff08;AD&#xff09; 帐户以外的帐户的单独凭据&#xff0c;最重要的是&#xff0c;每个密码还受不同的密码策略和到期日期的约束&#xff0c;为不同的帐户使用单独的密码会增加用户忘记密码和…...

安科瑞能源物联网以能源供应、能源管理、设备管理、能耗分析的能源流向为主线-安科瑞黄安南

摘要&#xff1a;随着科学技术的发展&#xff0c;我国的物联网技术有了很大进展。为了提升电力抄表服务的稳定性&#xff0c;保障电力抄表数据的可靠性&#xff0c;本文提出并实现了基于物联网的智能电力抄表服务平台&#xff0c;结合云计算、大数据等技术&#xff0c;提供电力…...

FPGA设计时序分析一、时序路径

目录 一、前言 二、时序路径 2.1 时序路径构成 2.2 时序路径分类 2.3 数据捕获 2.4 Fast corner/Slow corner 2.5 Vivado时序报告 三、参考资料 一、前言 时序路径字面容易简单地理解为时钟路径&#xff0c;事实时钟存在的意义是为了数据的处理、传输&#xff0c;因此严…...

spring复习:(52)注解方式下,ConfigurationClassPostProcessor是怎么被添加到容器的?

进入AnnotationConfigApplicationContext的构造方法&#xff1a; 进入AnnotatedBeanDefinitionReader的构造方法&#xff1a; 进入this(registry, getOrCreateEnvironment(registry));代码如下&#xff1a; 进入AnnotationConfigUtils.registerAnnotationConfigProcessors方…...

全国大学生数据统计与分析竞赛2021年【本科组】-B题:用户消费行为价值分析

目录 摘 要 1 任务背景与重述 1.1 任务背景 1.2 任务重述 2 任务分析 3 数据假设 4 任务求解 4.1 任务一&#xff1a;数据预处理 4.1.1 数据清洗 4.1.2 数据集成 4.1.3 数据变换 4.2 任务二&#xff1a;对用户城市分布情况与分布情况可视化分析 4.2.1 城市分布情况可视化分析 4…...

力扣1667. 修复表中的名字

表&#xff1a; Users ------------------------- | Column Name | Type | ------------------------- | user_id | int | | name | varchar | ------------------------- 在 SQL 中&#xff0c;user_id 是该表的主键。 该表包含用户的 ID 和名字。…...

【设计模式】详解观察者模式

文章目录 1、简介2、观察者模式简单实现抽象主题&#xff08;Subject&#xff09;具体主题&#xff08;ConcreteSubject&#xff09;抽象观察者&#xff08;Observer&#xff09;具体观察者&#xff08;ConcrereObserver&#xff09;测试&#xff1a; 观察者设计模式优缺点观察…...

用html+javascript打造公文一键排版系统8:附件及标题排版

最近工作有点忙&#xff0c;所 以没能及时完善公文一键排版系统&#xff0c;现在只好熬夜更新一下。 有时公文有包括附件&#xff0c;招照公文排版规范&#xff1a; 附件应当另面编排&#xff0c;并在版记之前&#xff0c;与公文正文一起装订。“附件”二字及附件顺序号用3号黑…...

微服务体系<1>

我们的微服务架构 我们的微服务架构和单体架构的区别 什么是微服务架构 微服务就是吧我们传统的单体服务分成 订单模块 库存模块 账户模块单体模块 是本地调用 从订单模块 调用到库存模块 再到账户模块 这三个模块都是调用的同一个数据库 这就是我们的单体架构微服务 就是…...

M5ATOMS3基础02传感器MPU6886

M5ATOMS3基础01按键 简洁版本 MPU6886是一款6轴IMU单元&#xff0c;具有3轴重力加速度计和3轴陀螺仪。它采用16位ADC&#xff0c;内置可编程数字滤波器和片上温度传感器&#xff0c;并通过I2C接口&#xff08;地址为0x68&#xff09;与上位机通信。MPU6886支持低功耗模式&#…...

vue 快速自定义分页el-pagination

vue 快速自定义分页el-pagination template <div style"text-align: center"><el-paginationbackground:current-page"pageObj.currentPage":page-size"pageObj.page":page-sizes"pageObj.pageSize"layout"total,prev,…...

0-虚拟机补充知识

虚拟机克隆 如果想要构建服务器集群&#xff0c;没有必要一台一台的去进行安装&#xff0c;只要通过克隆就可以。 快速获得多台服务器主要有两种方式&#xff0c;分别为&#xff1a;直接拷贝操作和vmware的克隆操作 直接拷贝 将之前安装虚拟机的所有文件进行拷贝&#xff0…...

如何将电机控制器添加到您的 ROS 机器人

一、说明 如果您正在构建与 ROS/ROS2 一起使用的移动机器人,您需要做的第一件事就是集成电机控制器。电机控制器的目的是接受来自更高级别的软件(如导航堆栈)的消息,并将其转换为驱动电机的信号。它还将从电机的编码器接收信息,以计算机器人的速度和位置。 您可以…...

ChatGPT统计“一到点就下班”的人数

ChatGPT统计“一到点就下班”的人数 1、到点下班 Chatgpt统计各部门F-D级员工到点下班人数占比&#xff0c;是在批评公司内部存在到点下班现象。 根据图片&#xff0c;该占比的计算方法是&#xff1a;最后一次下班卡在17:30-17:40之间&#xff0c;且1-5月合计有40天以上的人…...

Games101学习笔记 - 变换矩阵基础

二维空间下的变换 缩放矩阵 缩放变换: 假如一个点&#xff08;X,Y&#xff09;。x经过n倍缩放&#xff0c;y经过m倍缩放&#xff0c;得到的新点&#xff08;X1&#xff0c;Y1&#xff09;&#xff1b;那么新点和远点有如下关系&#xff0c;X1 n*X, Y1 m*Y写成矩阵就是如下…...

Ubuntu18.04未安装Qt报qt.qpa.plugin could not load the Qt platform plugin xcb问题的解决方法

在Ubuntu 18.04开发机上安装了Qt 5.14.2&#xff0c;当将其可执行程序拷贝到另一台未安装Qt的Ubuntu 18.04上报错&#xff1a;拷贝可执行程序前&#xff0c;使用ldd将此执行程序依赖的动态库也一起拷贝过去&#xff0c;包括Qt5.14.2/5.14.2/gcc_64/plugins目录系的platforms目录…...

GPT4ALL私有化部署 01 | Python环境

进入以下链接&#xff1a; https://www.python.org/downloads/release/python-3100/ 滑动到底部 选择你系统对应的版本&#xff0c;如果你是win&#xff0c;那么大概率是win-64bit 有可能你会因为网络的问题导致下载不了&#xff0c;我提供了 链接 接着只需要打开 等待…...

GPT-AI 使用的技术概览

ChatGPT 使用的技术概览 智心AI-3.5/4模型&#xff0c;联网对话&#xff0c;MJ快速绘画 从去年 OpenAI 发布 ChatGPT 以来&#xff0c;AI 的能力再次惊艳了世人。在这样的一个时间节点&#xff0c;重新去学习相关技术显得很有必要。 ChatGPT 的内容很多&#xff0c;我计划采用…...

NoSQL-Redis持久化

NoSQL-Redis持久化 一、Redis 高可用&#xff1a;1.概述&#xff1a; 二、Redis持久化&#xff1a;1.持久化的功能&#xff1a;2.Redis 提供两种方式进行持久化&#xff1a; 三、RDB 持久化&#xff1a;1.定义&#xff1a;2.触发条件&#xff1a;3.执行流程&#xff1a;4.启动时…...

SIwave串扰分析保姆级教程:从Allegro文件导入到结果解读,手把手教你排查PCB信号问题

SIwave串扰分析实战指南&#xff1a;从Allegro文件导入到精准定位信号问题 在高速PCB设计中&#xff0c;串扰问题如同电路板上的"隐形杀手"&#xff0c;往往在原型测试阶段才暴露出信号完整性问题。本文将带您深入掌握SIwave这一专业工具&#xff0c;从零开始构建完整…...

用梦话编程:睡眠开发者的效率革命

在传统认知中&#xff0c;软件开发是高度依赖清醒、理性思维的活动。程序员在屏幕前敲击键盘&#xff0c;与逻辑、算法和Bug进行着日复一日的“搏斗”。然而&#xff0c;一场静默的效率革命正在发生&#xff0c;它挑战着我们对“工作状态”的定义——这场革命的核心&#xff0c…...

GHelper:如何用轻量级工具解决华硕笔记本性能控制的三大难题?

GHelper&#xff1a;如何用轻量级工具解决华硕笔记本性能控制的三大难题&#xff1f; 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Fl…...

Fluvio 实时数据处理实战指南:如何构建高性能流式传输应用程序

Fluvio 实时数据处理实战指南&#xff1a;如何构建高性能流式传输应用程序 【免费下载链接】fluvio &#x1f980; event stream processing for developers to collect and transform data in motion to power responsive data intensive applications. 项目地址: https://g…...

GLM-OCR嵌入式部署轻量化实践:从服务器到边缘设备的模型压缩

GLM-OCR嵌入式部署轻量化实践&#xff1a;从服务器到边缘设备的模型压缩 最近在做一个智能零售柜的项目&#xff0c;需要实时识别商品包装上的文字信息。一开始我们用的是云端API&#xff0c;识别效果确实不错&#xff0c;但网络延迟和稳定性成了大问题——有时候网络一波动&a…...

Hyperf方案 分库分表实现

<?php /*** 案例标题&#xff1a;分库分表实现* 说明&#xff1a;基于用户ID取模实现分表路由&#xff0c;水平分片存储海量订单数据* 需要安装的包&#xff1a;* composer require hyperf/db-connection*/declare(strict_types1);// app/Sharding/ShardingStrategy.php…...

学生项目福音:AI超清画质增强快速入门,WebUI界面开箱即用

学生项目福音&#xff1a;AI超清画质增强快速入门&#xff0c;WebUI界面开箱即用 1. 为什么你需要AI画质增强技术 1.1 低清图像的普遍困扰 作为学生开发者&#xff0c;你可能经常遇到这样的场景&#xff1a;课程项目需要展示清晰的图片素材&#xff0c;但手头只有模糊的截图…...

告别官方驱动:深度解读ES7210寄存器,打造你自己的音频采集库(ESP32平台)

告别官方驱动&#xff1a;深度解读ES7210寄存器&#xff0c;打造你自己的音频采集库&#xff08;ESP32平台&#xff09; 在嵌入式音频开发领域&#xff0c;ES7210作为一款高性能多通道ADC芯片&#xff0c;被广泛应用于智能音箱、会议系统等场景。然而&#xff0c;官方驱动往往封…...

ESP32平台ST7703 RGB TFT驱动组件(PlatformIO兼容)

1. 项目概述htcw_esp_lcd_st7703是一个面向 PlatformIO&#xff08;PIO&#xff09;生态的 ESP-IDF 兼容 LCD 驱动组件&#xff0c;其核心目标是为基于 ESP32 系列 SoC&#xff08;尤其是 ESP32-S2/S3/C3/C6&#xff09;的嵌入式系统提供对 ST7703 RGB TFT 显示控制器的完整、可…...

OpenClaw故障诊断:Qwen3.5-9B接口超时问题排查实录

OpenClaw故障诊断&#xff1a;Qwen3.5-9B接口超时问题排查实录 1. 问题现象与初步判断 那天深夜&#xff0c;我正在调试一个自动化文档处理流程&#xff0c;OpenClaw突然开始频繁报错。控制台不断弹出"Model timeout after 30000ms"的警告&#xff0c;原本10秒内能…...