【Nodejs】Puppeteer\爬虫实践

news2024/12/25 12:16:45

在这里插入图片描述

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"]'); // 定位输入框
  /*  1
  input.focus()
  page.keyboard.type("电影") */
  //2
  await input.type('电影');

  /* 1  
 elementHandle.click()
  const search = await page.$('input[name="Submit"]'); // 定位搜索按钮
  await search.click();  // 点击 */
  //2
  await 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);
})();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/789482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海外网红营销合作指南:详解海外合同与协议要点

随着互联网的发展和社交媒体的普及&#xff0c;海外网红营销成为了品牌推广和营销的重要力量。然而&#xff0c;这种跨国合作需要谨慎考虑&#xff0c;签订合适的合同与协议显得尤为重要&#xff0c;以确保各方权益得到保障并促进合作的顺利进行。本文Nox聚星将详细介绍与海外网…

Stable Diffusion - 扩展 Segment Anything 和 GroundingDINO 实例分割算法 插件的配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131918652 Paper and GitHub&#xff1a; Segment Anything: SAM - Segment Anything GitHub: https://github.com/facebookresearch/s…

学习机器视觉要点:

图像采集&#xff1a;了解镜头、光源、相机选型&#xff0c;打光对图像质量的重要性。 图像处理&#xff1a;掌握压缩、增强、匹配、识别等图像处理技术&#xff0c;包括滤波、连通域、腐蚀膨胀等基本操作。 矩视智能低代码平台&#xff1a;使用该平台进行快速开发&#xff0…

mac电脑强大的解压缩软件BetterZip 5.3.4 for Mac中文版及betterzip怎么压缩

BetterZip 5.3.4 for Mac 是Mac系统平台上一款功能强大的文件解压缩软件&#xff0c;不必解压就能快速地检查压缩文档。它能执行文件之间的合并并提供密码。使用它&#xff0c;用户可以更快捷的向压缩文件中添加和删除文件。它支持包括zip、gz、bz、bz2、tar、tgz、tbz、rar、7…

华为数通HCIA-数通网络基础

基础概念 通信&#xff1a;两个实体之间进行信息交流 数据通信&#xff1a;网络设备之间进行的通信 计算机网络&#xff1a;实现网络设备之间进行数据通信的媒介 园区网络&#xff08;企业网络&#xff09;/私网/内网&#xff1a;用于实现园区内部互通&#xff0c;并且需要部…

Python实现人脸识别功能

Python实现人脸识别功能 闲来没事&#xff0c;记录一下前几天学习的人脸识别小项目。 要想实现人脸识别&#xff0c;我们首先要搞明白&#xff0c;人脸识别主要分为哪些步骤&#xff1f;为了提高人脸识别的准确性&#xff0c;我们首先要把图像或视频中的人脸检测出来&#xf…

Linux入门 系统编程三 嵌入式开发 使用gcc制作静态库动态库,及调用库头文件应用

一、静态库的制作与使用 生成静态的主要是有5个步骤 1、编写源代码 2、将要编译成库的源文件编译成.o文件 3、使用ar命令创建静态库 4、调用库 5、测试 静态库的命名规则&#xff1a;lib开头。.a结尾。lib和.a中间的称作库名。lib库名称作库文件名 1.1 先写两个测试程序&…

《论文阅读》具有特殊Token和轮级注意力的层级对话理解 ICLR 2023

《论文阅读》具有特殊Token和轮级注意力的层级对话理解 前言简介问题定义模型构建知识点Intra-turn ModelingInter-turn Modeling分类前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到失望? 小白如何从零读懂论文?和我一…

用OpenCV图像处理技巧之巧用直方图

1. 引言 欢迎回到我的Python图像处理系列&#xff01;在这一节中&#xff0c;我们将更深入地研究图像分析领域中图像直方图的应用&#xff0c;事实上通过对直方图进行相应操作&#xff0c;我们可以来调整图像的对比度和亮度&#xff0c;这可以极大地改善图像的视觉效果。 闲话…

vue脚手架文件说明

vue脚手架文件说明 1、文件介绍2、脚手架里面主要文件和作用 1、文件介绍 2、脚手架里面主要文件和作用 node_modules 都是下载的第三方包public/index.html 浏览器运行的网页src/main.js webpack打包的入口src/APP.vue Vue页面入口package.json 依赖包列表文件

Tangible Software Solutions Crack

Tangible Software Solutions Crack 有形软件解决方案-最准确可靠的源代码转换器&#xff0c;在VB.NET、C#、Java、C和Python之间进行转换&#xff0c;同时节省了无数小时的艰苦工作和宝贵的时间。 主要优点&#xff1a; 节省宝贵时间 准确全面 安全-您的代码永远不会离开您的机…

阿里云容器镜像仓库(ACR)的创建和使用

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

(一)RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理 文章目录 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理RabbitMQ概念RabbitMQ的优势RabbitMQ劣势RabbitMQ应用的场景RabbitMQ_AMQPRabbitMQ工作原理 RabbitM…

如何在3ds max中创建可用于真人场景的巨型机器人:第 1部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建主体 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在左侧视口中&#xff0c;按键盘上的 Alt-B 键。它 打开视口配置窗口。 打开“锁定缩放/平移”和“匹配位图”选项。单击“文件”并转到参考 …

从Vue2到Vue3【五】——新的组件(Fragment、Teleport、Suspense)

系列文章目录 内容链接从Vue2到Vue3【零】Vue3简介从Vue2到Vue3【一】Composition API&#xff08;第一章&#xff09;从Vue2到Vue3【二】Composition API&#xff08;第二章&#xff09;从Vue2到Vue3【三】Composition API&#xff08;第三章&#xff09;从Vue2到Vue3【四】C…

STM32CUBUMX配置FLASH(W25Q128)--保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…

服务网格技术对比:深入比较Istio、Linkerd和Envoy等服务网格解决方案的优缺点

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Github上方导航栏介绍

Code Watch&#xff1a;相当于关注&#xff0c;到时候这个项目又有什么操作&#xff0c;就会以通知的形式提醒你。 Fork&#xff1a;也就是把这个项目拉到你的仓库里&#xff0c;之后你可以对该代码进行修改&#xff0c;之后你可以发起Pull Request&#xff0c;简称PR&#xf…

SpringBoot集成kafka全面实战

本文是SpringBootKafka的实战讲解&#xff0c;如果对kafka的架构原理还不了解的读者&#xff0c;建议先看一下《大白话kafka架构原理》、《秒懂kafka HA&#xff08;高可用&#xff09;》两篇文章。 一、生产者实践 普通生产者 带回调的生产者 自定义分区器 kafka事务提交…

Windows下基于VSCode搭建C++开发环境(包含整合MinGW64、CMake的详细流程)

最近想写写C&#xff0c;装了VisualStudio 2022&#xff0c;折腾半天。对于一个用惯VSCode的人来说&#xff0c;总感觉IDE太笨重。于是自己网上各种查资料&#xff0c;自己琢磨&#xff0c;搭建了一套Windows下基于VSCode和CMake的C轻量级开发环境。 具体搭建步骤 1. 下载并安…