puppeteer 包模拟登录 模拟iframe网站自动登录

之前写了个chrome 扩展来完成公司内部的一个需求。在一个网站上实现了自动化程序,包括登录,后续操作,保持状态,被踢出后再次登录等等。

但是这个网站突然前几天更新了登录方式,在登录页面嵌入了iframe,使用内嵌的iframe登录。我还是用chrome扩展试了一下,但是chrome扩展无法操作iframe。

只能转换思路,最终群友提供了一个线索,找到了一个google官方出的node包 puppeteer ,顺利的完成了自动登录的流程。只能说这个包真强大,群友玩的真多。

所以以下内容和代码都为了解决一个问题: 使用 puppeteer 自动登录内嵌 iframe 页面登录的的网页,并监控到登录状态失效后,自动再次登录

监听
node脚本
logo宿主页面
自动登录
具体操作
登录超时

本文默认您会使用 nodenpm, 以下脚本基于node14.15.0,在node 12版本上运行通过

所需要的插件包
"devDependencies": {
    "carlo": "^0.9.46",
    "puppeteer-core": "^5.4.0"
  }

puppeteerpuppeteer-core 的区别

puppeteer的核心是puppeteer-corepuppeteer会下载 Chromium,而 puppeteer-core 不会自动下载 Chromiumpuppeteer运行时默认使用 puppeteer-core 来驱动 Chromiumpuppeteer还能配置 PUPPETEER_*。我这里使用了puppeteer-core,调用本地 google chrome

准备工作

const puppeteer = require('puppeteer-core');

//find_chrome模块来源于GoogleChromeLabs的Carlo,可以查看本机安装Chrome目录
const findChrome = require('./node_modules/carlo/lib/find_chrome');

const width = 1366; //浏览器宽度
const height = 768; //浏览器高度
let browser = null 
  , page = null 
  , init = false // 初次运行脚本
  , isOk = false; // 触发登录事件开关

以上导入了必须的模块,提前声明了需要的数据

1 传入配置 创建浏览器对象

const newBrowser = async () => {
  init = true; // 已经创建了浏览器对象
  let findChromePath = await findChrome({});
  let executablePath = findChromePath.executablePath;  //得到本机chrome路径

  browser = await puppeteer.launch({
    executablePath, // 本地chrome路径
    headless: false, // 启用页面GUI方式
    devtools: false, // F12打开控制台
    args: [
      `--disable-extensions-except=/Users/mac/project/debug/rechargenew`, // 不屏蔽这个扩展
      `--window-size=${width},${height}`, // 窗口大小
      `–disable-gpu` // 禁用 GPU加速
    ],
    defaultViewport: { width: width, height: height } // 页面大小
  });

  page = await browser.newPage(); // 创建浏览器

  newhtml()
}

此时到这里桌面就会打开一个chrome浏览器

2 打开指定的页面

// 创建打开google页面
const newhtml = async () => {

  await page.goto('http://www.xxxx.com/', {
    waitUntil: 'networkidle2'
  });

  startLogin()
}

运行到这里会打开指定页面

3 开启自动登录

// 开始登录
const startLogin = async (callback) => {
  const startLogin = await page.$(".submit-btn");

  if (startLogin) {
    page.click(".submit-btn")
  }

  // 检测到 iframe 请求返回回来了 再等5秒钟开始自动填写账号密码登录
  page.on('response', async req => {
	// 判断当前这个请求是不是请求 iframe 登录页面
    if (req.url().indexOf('xxxx.xxxx.com/xxxx') >= 0 && !isOk) {
      isOk = true // 阻止重复运行
      setTimeout(async () => {
        await page.waitFor('[id*="xxxxx"]');//等待我的iframe出现
        const frame = (await page.frames())[2]
        frame.click("#tab-password")

        await frame.waitFor(3000);
        
        await frame.waitFor('.ruleForm-pwd .form-item1 input');//等待用户名框出现
        await frame.type('.ruleForm-pwd .form-item1 input', 'xxxx');//输入用户名
        await frame.waitFor('.ruleForm-pwd .passwordInput input');//等待密码输入框出现
        await frame.type('.ruleForm-pwd .passwordInput input', 'xxxx');//输入密码

		// 点击登录
        setTimeout(() => {
          frame.click(".loginBtnWrap .loginBtn")

          setTimeout(() => {
            page.click(".banner-info .submit-btn")
          }, 2000);

        }, 1000);
      }, 5000);

    }
  });
}

在这里使用 page.on('response') 监听到特定的请求接口返回后,开始填入账号和密码准备登录
有些地方需要用到延时器等待dom或者js操作完成,才能进行下一步,这样较为保险。

检测登录状态是否失效

// 检查是否被踢出登录  被踢出登录后重新登录
setInterval(() => {
  console.log(page.url());
  
  if (page.url().indexOf("xxx.xxx.com/index.html?") >= 0 && init) {
    isOk = false
    newhtml()
  }
  
}, 20000);

这里开启了一个定时器,判断当前宿主页面的url是否是登录页面的url,如果是登录页面的url,就判定当前登录状态已经失效了,然后再次重启登录流程。

完整代码:

const puppeteer = require('puppeteer-core');

//find_chrome模块来源于GoogleChromeLabs的Carlo,可以查看本机安装Chrome目录
const findChrome = require('./node_modules/carlo/lib/find_chrome');
const width = 1366;
const height = 768;
let browser = null
  , page = null
  , init = false // 初次运行
  , isOk = false; // 触发登录事件开关

const newBrowser = async () => {
  init = true;
  let findChromePath = await findChrome({});
  let executablePath = findChromePath.executablePath;

  browser = await puppeteer.launch({
    executablePath,
    headless: false,
    devtools: false, // F12打开控制台
    args: [
      `--disable-extensions-except=/Users/mac/project/debug/rechargenew`, // 不屏蔽这个插件
      `--window-size=${width},${height}`, // 窗口大小
      `–disable-gpu`
    ],
    defaultViewport: { width: width, height: height } // 页面大小
  });

  page = await browser.newPage();

  newhtml()
}
// 创建打开google页面
const newhtml = async () => {

  await page.goto('http://www.xxxx.com/', {
    waitUntil: 'networkidle2'
  });

  startLogin()
}

// 开始登录
const startLogin = async (callback) => {
  const startLogin = await page.$(".submit-btn");

  if (startLogin) {
    page.click(".submit-btn")
  }

  // 检测到 iframe 请求返回回来了 再等5秒钟开始自动填写账号密码登录
  page.on('response', async req => {

    if (req.url().indexOf('xxxxx.xxxxxx.com/xxxx') >= 0 && !isOk) {
      isOk = true // 阻止重复运行
      setTimeout(async () => {
        await page.waitFor('[id*="xxxxx"]');//等待我的iframe出现
        const frame = (await page.frames())[2]
        frame.click("#tab-password")

        await frame.waitFor(3000);
        
        await frame.waitFor('.ruleForm-pwd .form-item1 input');//等待用户名框出现
        await frame.type('.ruleForm-pwd .form-item1 input', 'xxxxxxx');//输入用户名
        await frame.waitFor('.ruleForm-pwd .passwordInput input');//等待密码输入框出现
        await frame.type('.ruleForm-pwd .passwordInput input', 'xxxxx');//输入密码
		// 点击登录
        setTimeout(() => {
          frame.click(".loginBtnWrap .loginBtn")

          setTimeout(() => {
            page.click(".banner-info .submit-btn")
          }, 2000);

        }, 1000);
      }, 5000);

    }
  });
}

newBrowser()

// 检查是否被踢出登录  踢出登录后重新登录
setInterval(() => {
  console.log(page.url());

  if (page.url().indexOf("xxxxxxx.xxxxxxx.com/index.html?") >= 0 && init) {
    isOk = false
    newhtml()
  }
  
}, 20000);

注意点

  • 合理运用定时器和延时器,防止dom还未生成时,使用了相关代码
  • --disable-extensions-except 插件路径的写法,在mac中上面写法是正确的。在window中,\字符需要替换成 /,这里浪费了好多时间
  • 获取 frame dom树,page.frames() 返回的集合需要找到指定的frame,试了好多方法,最后直接暴力去2了

参考连接
新手必须看的
大佬翻译的puppeteer文档
puppeteer之iframe1
puppeteer之iframe2
puppeteer之iframe3


微信群大佬都在等着你

微信扫描二维码加入微信群,交流学习,及时获取代码最新动态。

你可能感兴趣的:(chrome插件开发,puppeteer,puppeteer,node,自动登录,chrome自动登录,puppeteer)