Nodejs实战-基于puppeteer运行javascript

1,827 阅读1分钟

一、神奇的国度

puppeteer是一个谷歌的无头浏览器插件,他可以做很多事情,爬虫,运行js脚本,截取网页生成图片,自动化测试等等,这里我主要使用运行js脚本,获取一个加密后的返回值,为什么要写这篇文章呢?也是业务的需求,爬虫的哥们破解不掉一个关键性的参数,于是这个光荣而伟大的任务到了我们前端手里,不废话了,为了年终奖,开干... ps:爬虫有风险,慎重 [api参考地址](https://www.kancloud.cn/luponu/puppeteer/870133)

二、初始化Nodejs

我是使用egg.js去做的,为啥用它?因为傻瓜。。。哈哈哈,直接运行下面命令去生成项目:

| ```
$ mkdir puppeteer && cd puppeteer $ npm init egg --type=simple $ npm i 
``` |
| ----------------------------------------------------------------------------------- |

启动项目:

| ```
$ npm run dev $ open http://localhost:7001
``` |
| --------------------------------------------------

三、无脑装包

先增加白名单和跨域配置

我们首先在config设置文件下新增config.default.js和config.prod.js,内容可直接把默认的config.local.js的拷贝过来,这里主要去配置一些本地开发的信息和上线的信息,因为我使用了一个静态页面去加载了一个脚本,所以我这里配置了两个上线的地址,我这里直接给出相关配置项

config.default.js配置
const config = exports = {
    // 跨域配置白名单
    security: {
      csrf: {
        enable: false,
        ignoreJSON: true,
      },
      domainWhiteList: [ '*' ], // 配置白名单
    },
    cors: {
      origin: '*', // 允许所有跨域访问
      credentials: true, // 允许 Cookie 跨域跨域
      allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
    },
  };

config.local.js配置
const userConfig = {
    htmlUrl:'http://127.0.0.1:8899/public/index.html', // 根据自己需求自行更改
 };

config.prod.js配置
const userConfig = {
    htmlUrl:'http://xxxxx/public/index.html', // 根据自己需求自行更改
 };

在app文件夹下面拷贝进去我们的静态页面和脚本

后面我们需要用node打开这个页面,调用里面的js函数去执行逻辑,获取到我们需要的东西

22.png

装包

// 执行
npm install --save puppeteer

四、逻辑开发提供接口

分析:我们需要打开预先准备的静态页面,然后执行页面上面的函数,才能获取到需要的参数,这里我们首先在router.js下面写出接口,然后在controller.js下编写逻辑

router.js代码如下:
 router.post('/getxb', controller.home.getxb);
controller.js代码如下:
 // 获取xb加密参数
  async getxb() {
    const { ctx } = this;
    const data = await ctx.helper.puppeteer(this)
    if(data){
      ctx.body = {
        code:'Success',
        data:data,
        msg:'成功'
      };
      ctx.status=200
    }else{
      ctx.body = {
        code:'error',
        data:null,
        msg:'系统繁忙'
      };
      ctx.status=500
    }
  } 

我这里把核心逻辑入到了extend下面的helper.js中

helper.js代码如下:
const puppeteer = require('puppeteer'); 
let browser=null,page=null;
exports.puppeteer  = async (that) => {    
    //创建一个Browser浏览器实例,并设置相关参数
    const { ctx } = that;
    const {xb} = ctx.request.body;
    if(!browser){
        browser = await puppeteer.launch({
            headless: true, // 是否以 无头模式 运行浏览器。默认是 true
            defaultViewport: null,// 为每个页面设置一个默认视口大小。默认是 800x600。如果为 null 的话就禁用视图口。
            // timeout: 0, // 等待浏览器实例启动的最长时间(以毫秒为单位)。默认是 30000 (30 秒). 通过 0 来禁用超时。
            ignoreHTTPSErrors: true, // 是否在导航期间忽略 HTTPS 错误. 默认是 false
            args: [
                '--no-sandbox',
            ],
        });
        // 创建一个Page实例
        page = await browser.newPage();
        // 这里容易踩坑习惯上我们可能直接下传我们的参数,这样是不行的,因为这是我们的node环境,参数需要传递到我们静态页面所以我挂在了url上面
        await page.goto(`${that.config.htmlUrl}?xb=${xb}`);
    }
    //执行原生Js方法
    return await page.evaluate(() => {
        return window.byted_acrawler.getxb(window.location.href.split('?')[1],null);
    })
}
exports.closepuppeteer  = async (that) => {    
    //调用此接口时关闭窗口
    const { ctx } = that;
    if(browser){
        await browser.close();
        browser=null;
        page=null;
        return '成功'
    }else{
        return null
    }
}

ps:为什么变量声明在了外面这里是考虑到效率的问题,因为频繁的发开关闭窗口非常耗时间,这里是提供个接口给比人用所以我只打开了一次,后续所有的调用都在这里完成,下面我还写了一个关闭窗口的接口。

五、postman试试吧

我们带我们需要的参数试一下,可以看到拿到了我们需要的参数

1640669962127.jpg ok,快来试试这个神迹吧!!!