爱学习的好孩子

puppeteer

时间: 2024-06-12

概述

puppeteer是一个优秀的浏览器。

安装

PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts

经常在使用脚本自动安装时会出错,这个时候最好手动下载可执行文件。

可以根据提示Uncaught Error: Could not find browser revision 1022525.获得具体版本编号。

通常下载链接类似: https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1022525/chrome-linux.zip,这个里面的1022525是版本号。

基础知识

我们通过一个简单的实例来做一些了解。

const puppeteer = require("puppeteer");
(async () => {
  const browser = await puppeteer.launch({
    headless: false, //有浏览器界面启动
    defaultViewport: null,
    timeout: 30000, // 默认超时为30秒,设置为0则表示不设置超时
    slowMo: 500, //放慢浏览器执行速度,方便测试观察
    args: ["--no-sandbox"],
  });
  const page = await browser.newPage();
  await page.goto("https://www.baidu.com");
  await page.close();
  await browser.close();
})();

puppeteer.launch每次都会启动一个Chrome实例。

除此之外,我们也可以使用puppeteer.connect连接一个已经存在的Chrome实例。

首先启动实例。找到chrome的安装目录,通常在C:\Program Files (x86)\Google\Chrome\Application下面。然后从命令行启动:

$ chrome.exe --remote-debugging-port=9222 --user-data-dir=C:\tmp

这样会在9222端口启动一个调试实例。user-data-dir好像必须要配置,否则连接不成功?然后可以在http://127.0.0.1:9222/json/version查看到实例信息。

// 新建一个标签页(空白页或者带参数默认加载URL)
http://localhost:9222/json/new
http://localhost:9222/json/new?http://www.baidu.com

// 关闭一个标签页,传入该页面的id。
http://localhost:9222/json/close/477810FF-323E-44C5-997C-89B7FAC7B158

// 激活标签页。
http://localhost:9222/json/activate/477810FF-323E-44C5-997C-89B7FAC7B158

// 获取所有开打标签的信息。
http://loacalhost:9222/json/list

更详细的协议信息可以查看官网

const puppeteer = require("puppeteer");
let request = require("request-promise-native");

(async () => {
  //通过 9222 端口的 http 接口获取对应的 websocketUrl
  let version = await request({
    uri: "http://127.0.0.1:9222/json/version",
    json: true,
  });
  console.log(version);
  //直接连接已经存在的 Chrome
  let browser = await puppeteer.connect({
    browserWSEndpoint: version.webSocketDebuggerUrl,
  });
  const page = await browser.newPage();
  await page.goto("https://www.baidu.com");
  await page.close();
  await browser.disconnect();
})();

Browser对象API

方法名称 返回值 说明
browser.close() Promise 关闭浏览器
browser.disconnect() void 断开浏览器连接
browser.newPage() Promise(Page) 创建一个Page实例
browser.pages() Promise(Array(Page)) 获取所有打开的Page实例
browser.targets() Array(Target) 获取所有活动的targets
browser.version() Promise(String) 获取浏览器的版本
browser.wsEndpoint() String 返回浏览器实例的socket连接URL,可以通过这个URL重连接chrome实例

Page对象API

这里要明确一些基本概念。元素的各种属性。

<view>这是innerText</view>

要获取这是innerText需要用innerText

获取文本

let text = await page.$eval("#app", (ele) => ele.innerText);

获取元素的属性

比如,要获取下面这个元素的class属性:

<div class="box" style="background: #F00">盒子</div>
let checkd = await page.$eval(`#app`, (el) => el.getAttribute("class"));

设置文本框值

为了保险一点,通常在输入前清空一下文本框比较好。

await page.$eval("#input", (ele) => ele.value = ""); // 清空文本框
await page.type("#mytextarea", "Hello"); // 立即输入
await page.type("#mytextarea", "World", { delay: 100 }); // 输入变慢,像一个用户

获取frame

ddlogin-iframeframe的名字,也就是id

const ddloginIframe = page.frames().find((frame) =>
  frame.name() === "ddlogin-iframe"
);
const qrcode = await ddloginIframe.$eval("#qrcode > img", (ele) => ele.src);

获取页面标题

page.title()
returns: <Promise<string>> 返回页面标题.

添加cookie

await page.goto(url);

const cookies = [{
  "name": "cookie1",
  "value": "val1",
}, {
  "name": "cookie2",
  "value": "val2",
}, {
  "name": "cookie3",
  "value": "val3",
}];

await page.setCookie(...cookies);

参考

评论