puppeteer在开发过程中的实践

MalthusRyan 发布于6月前 阅读359次
0 条评论

上篇文章我们谈了一下puppeteer是什么,以及具体能做什么,但文中谈到的在我们日常开发中并不常用到,截图我们有截图工具、前端自动化测试有phantomjs、selenium。不仅如此,为了SEO,前端基本都会做SSR,爬取这样的页面的话python得益于强大的模块,具有得天独道的优势。也许有人会问,那对于某些后台管理系统,是没有做SSR的,此时puppeteer的优势不就体现出来了吗?对于此种情况,首先,爬管理系统的数据的话需要有账号密码,我们没有。那如果是我们自己的系统的话,数据都是自己的,我还需要爬吗?

额。。。。

pupueteer看来似乎并没有想象中的那么强大。但实际情况下并非如此,虽然有些功能之前存在的一些框架也能做到,但毕竟对于我们前端开发来说,要想掌握新的技术就需要去学习新的语言,这样的话成本就很大了。

pupueteer提供了简洁的API和丰富的接口,以为其是一个nodejs库,所以从学习角度来讲对前端很友好,上手快。接下来就来具体描述一个在实际开发过程中使用puppeteer的场景。

在我们公司前端开发的过程中,大部分项目要去接CAS,其目的是为了获取COOKIE,以便于与后端进行交互。目前常见的场景存在三种形式。

1.前端网关nodejs,主要用于转换dubbo协议,获取数据,其项目中会用nodejs去接cas

2.有些应用,服务端接口需要登录cas后拿到回调的cookie去请求数据,而此时前端也要配代理,模拟cas登录,拿到cookie后写在header里

3.有些应用,直接登录相关应用的开发环境,然后把cookie拿过来通过document.cookie写到本地环境进行开发

第一种情况因为线上需要cas登录,暂且不表。

但对于后面两种情况,我们可以简单分析下,其实2和3都是在本地开发的时候拿到登录cas后的cookie,然后在请求数据的时候把cookie带回去拿到数据。但要放到服务器的时候实际上是前端把静态资源全部打包成某一个或若干个js文件(一般不会超过3个)。所以问题就在于我们怎么方便的拿到cookie,如果对于一个熟悉cas sso原理的话,其对接一下cas可能会很快,但弊端就是要新搭一个node服务,写一些登录cas,拿cookie的流程,而且如果针对不同权限角色的话,每次登录新的角色,都要重新用不同角色去登录系统,去拿cookie(之前我们在开发robert就是如此,涉及admin,运维,开发,测试,测试经理等不同角色,每次功能有掺和都是一个痛苦的切换过程),如果对于一个不明其理的开发来说,这无异于一枚张榜炸弹,你接口跨域我可以很简单的做下代理,你**还让我去接cas。。。。

(敲黑板) 划重点啦。

接下来我们就用puppeteer,来实现一个超级简单的获取cookie的过程,简单到令人发指。以下示例以robert为例,如有需要可根据相关需求自行修改,其实现原理如下:

puppeteer在开发过程中的实践

代码如下:

const puppeteer = require("puppeteer");  
let cookie = {  
  name: "JSESSIONID",
  value: "",
  domain: "localhost",
  url: "http://localhost:3000/",
  path: "/",
  httpOnly: true,
  secure: false
};
const role = process.argv.pop();

const getRole = role => {  
  return {
    admin: {
      username: "admin",
      password: "123456"
    },
    qa: {
      username: "04688",
      password: "123456"
    },
    dev: {
      username: "04588",
      password: "123456"
    },
    ops: {
      username: "04141",
      password: "123456"
    }
  }[role];
};

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto("http://192.168.11.38:24880");
  const { username, password } = getRole(role);
  await page.type("#username", username);
  await page.type("#password", password, {
    delay: 100
  });
  await page.click("input[type=submit]");
  await page.waitForSelector(".ant-layout");
  const cookies = await page.cookies();
  cookies.map(v => {
    if (v.name === cookie.name) {
      cookie.value = v.value;
    }
  });
  await browser.close();
  const browser1 = await puppeteer.launch({
    headless: false
  });
  const page1 = await browser1.newPage();
  await page1.setCookie(cookie);
  const { width, height } = await page.evaluate(() => {
    const body = document.querySelector("body");
    return { width: window.outerWidth, height: body.clientHeight };
  });
  await page1.setViewport({
    width,
    height
  });
  await page1.goto("http://localhost:3000/");
})();

看过上篇的应该对基础用法有基本了解,接下来我们以此例顺便谈下新的知识点。 首先生成一个新的浏览器实例,不明其理的人会发现里面我们定义了一个 getRole函数 ,而且里面有一坨不明所以的username和password。哈哈,这里就是我刚刚提到的关于不同权限的用户角色。当跳转成功后,通过 page.cookies 来获取界面的cookies,在我们robert中,我们只需拿到 cookie 为 JSESSIONID 的值就行,拿到之后,关闭这个浏览器实例。

接下来新建一个浏览器实例,用来跳转本地环境, 然后把上面拿到的cookie设置到该实例,然后跳转到我们本地的环境即可。

简单明了的完成了拿cookie的过程。至此,我们完成了puppeteer在实际开发中的应用,大大减少了登录,切换账号的过程。我已经在robert项目中加入该流程,确实挺爽的。

查看原文: puppeteer在开发过程中的实践

  • beautifulbutterfly
  • ticklishrabbit
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。