用 Puppeteer 实现一个自动化机器人

开发 前端 自动化
Puppeteer 是 Node.js 的一个函数库,可用来操控浏览器,是 Google 的项目,可以应用的范围包括:前端的自动化测试、爬虫、表单提交等。

 [[390866]]

目录

  • 简介

  • Selenium vs Puppeteer

  • 安装

  • 一个简单的例子

  • 解释代码

  • 把项目容器化

  • 容器打包时的一些坑

    • 1. Puppeteer 安装 Chromium 时会缺少一些组件

    • 2. 页面焦点问题

    • 3. Page Crash 问题

    • 4. 时区问题

Puppeteer 是 Node.js 的一个函数库,可用来操控浏览器,是 Google 的项目,可以应用的范围包括:前端的自动化测试、爬虫、表单提交等。

Selenium vs Puppeteer

之前有过用 Python 配合 Selenium 的经验,不过如果是做爬虫、自动化操作用 Puppeteer 还是非常方便的,安装简单快速,API 也容易使用。美中不足的是它只支持 Chromium 以下是两者的比较,仅供参考:

 

由于 Puppeteer 是用 Node.js 写的,所以必须要先安装 Node。

  1. 可以至官网 下载

  2. 如果用 mac 可以使用 https://nodejs.org/en/

安装完后可以在 terminal 输入 node -v 检查是否安装成功

然后到要开发的项目路径下输入 npm init -y 初始化项目,接着 npm i puppeteer ,安装的时候会发现它会连同 Chromium 一同安装。

安装成功后就可以开始了。

一个简单的例子

新增一个文件 main.js ,并复制以下代码:

const puppeteer = require('puppeteer'); 
 
(async () => { 
 
  // 开启 browser 
  const browser = await puppeteer.launch({ 
        headless: false 
  }); 
  // 新增分页 
  const page = await browser.newPage(); 
  // 到自己的博客网站 
  await page.goto(`https://www.myblog.com/`); 
  // 等待订阅按钮出现 
  await page.waitForSelector("button[class='subscribe-button pill-button']"); 
  // 点击订阅按钮 
  await page.click("button[class='subscribe-button pill-button']"); 
})(); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

接着到终端下输入 node main.js 执行。

解释代码

前面的代码先引入 Puppeteer,以便后续使用,接下来可以看到用 async 以及 () => , async 表示函数要用到异步操作, () => 则是 JS 的箭头函数。

const puppeteer = require('puppeteer'); 
  • 1.

接下来是用 Puppeteer 打开一个浏览器 ( Chromium ),其中可以看到我们设了参数 headless : false ,如果是设定为 true ,会开启没有界面的无头浏览器,如果设定 false ,就会开一个浏览器窗口。

const browser = await puppeteer.launch({ 
    headless: false 
}); 
  • 1.
  • 2.
  • 3.

这段就很简单了,它会帮你在浏览器开一个新的分页。

const page = await browser.newPage(); 
  • 1.

这段也很容易,看到 goto 就可以猜到会帮你导向后方指定的网址。

await page.goto(`https://b123105.blogspot.com/`); 
  • 1.

最后这段代码用到了 click 这个方法,它能够帮你点击后面指定的元素,可以看到我是指定 class = subscribe-button pill-button 的 <button> 。

waitForSelector 的作用是,在执行时整个操作速度会很快,有时可能这个元素都很没出现,就让它去点击,有可能会找不到。所以先让它等待指定元素出现后,再去点击。

await page.waitForSelector("button[class='subscribe-button pill-button']"); 
 
await page.click("button[class='subscribe-button pill-button']"); 
  • 1.
  • 2.
  • 3.

把项目容器化

首先下载 Docker,这里就不再赘述。接下来在项目目录下创建 Dockerfile ,把下面的脚本代码复制粘贴。

然后构建镜像: docker build -t puppeteer-bot . 。

构建完成后就执行 docker run -d --name puppeteer-bot-timeline puppeteer-bot:latest 。

之后可以通过 docker logs puppeteer-bot-timeline 查看 console.log 的内容 ( 如果有的话 )。

要记得 headless 要设定为 true 才能运行。

FROM node:11-slim 
# 下载 chromium 在 docker 运行时所需组件 
RUN apt-get update && apt-get install -yq libgconf-2-4 
RUN apt-get update && apt-get install -y wget --no-install-recommends \ 
    && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 
    && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ 
    && apt-get update \ 
    && apt-get install -y google-chrome-unstable \ 
      --no-install-recommends \ 
    && rm -rf /var/lib/apt/lists/* \ 
    && apt-get purge --auto-remove -y curl \ 
    && rm -rf /src/*.deb 
 
ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 /usr/local/bin/dumb-init 
RUN chmod +x /usr/local/bin/dumb-init 
USER root 
ENV TZ=Asia/Shanghai # 转换时区,非必要 
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 
COPY . /app/ 
WORKDIR app 
RUN npm install 
EXPOSE 8084 
ENTRYPOINT ["dumb-init""--"
CMD ["node""main.js"
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

容器打包时的一些坑

接下来是我在用 Docke 打包过程遇到的一些问题:

1. Puppeteer 安装 Chromium 时会缺少一些组件

本来用 docker 封装是很容易的,安装 node 然后 npm install 就行了,但是在实际操作时一直报错说 Chromium 缺少组件。后来去 Puppeteer 的 issue 上查到原来安装 Puppeteer 时会自动安装 Chromium,但要在 Docker 上运行的相关组件并不会自动下载。

2. 页面焦点问题

在开发时我是通过开启一个浏览器,然后持续开三个分页来进行操作,希望能加快处理的速度。但是发现当 headless:false 时,会同时开启三个分页,但只有被设置为焦点的当前页面在执行后面的脚本,另外两页并没有。因为在开发过程中执行时 tab 页会被关闭,所以接下来第二个 tab 中的页面获得焦点后会再开始运行。

在 issue 中也看到有人遇到了同样的问题,只有在 headless:true 的时候会同时处理,但目前还没找到其他解法。

3. Page Crash 问题

上面有提到我在一个浏览器上操作三个分页,放在 docker 中运行,总是遇到 Page Crash 问题,第一反应是可能内存不足,在 issue 上查到原来在打开浏览器时要加上 --disable-dev-shm-usage 。

原文是这样说的:

By default, Docker runs a container with a /dev/shm shared memory space 64MB. This is typically too small for Chrome and will cause Chrome to crash when rendering large pages. To fix, run the container with docker run --shm-size=1gb to increase the size of /dev/shm. Since Chrome 65, this is no longer necessary. Instead, launch the browser with the --disable-dev-shm-usage flag: const browser = await puppeteer.launch({ args: ['--disable-dev-shm-usage'] });

4. 时区问题

这个问题与 Puppeteer 无关,有的服务器时区默认是 GMT,这时就要在 Dockerfile 指定容器的时区,不然代码中涉及到时间的操作时会被自动加 8 小时。

责任编辑:张燕妮 来源: 前端先锋
相关推荐

2021-04-21 13:56:32

人工智能机器学习

2023-10-30 17:41:29

机器人自动化

2023-07-11 16:35:13

机器人流程自动化

2019-04-02 09:00:00

机器人人工智能HMI设计

2020-09-10 11:40:00

Python机器人人工智能

2023-10-18 15:23:47

人工智能聊天机器人

2020-04-11 22:21:07

开源机器人过程自动化工具RPA

2024-03-04 15:04:37

机器人人工智能

2020-04-29 11:28:54

智能自动化机器人流程自动化AI

2020-12-02 13:00:17

Recast.AI聊天机器人人工智能

2022-09-30 13:55:46

Python机器人

2021-08-11 11:18:25

机器人人工智能技术

2021-10-08 09:31:05

机器人自动化物流

2024-02-04 09:43:53

机器人物联网

2020-08-18 09:55:21

机器人过程自动化数字化转型RPA

2023-08-28 16:16:15

机器人测试

2021-09-02 10:19:17

人工智能AI机器人

2024-03-07 14:37:46

自动化机器人人工智能

2024-03-08 13:10:23

ARVR机器人

2023-09-08 14:58:10

点赞
收藏

51CTO技术栈公众号