puppeteer 包模拟登录 模拟iframe网站自动登录_缘_妙不可言的博客-程序员秘密_iframe模拟登录

技术标签: node  chrome自动登录  puppeteer  自动登录  chrome插件开发  

之前写了个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


微信群大佬都在等着你

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/joy1793/article/details/110562889

智能推荐

数据结构(C语言版 第2版)课后习题答案 严蔚敏 编著_数据结构c语言版严蔚敏课后答案_就是217的博客-程序员秘密

 转自 https://blog.csdn.net/Bamboo_shui/article/details/72433523    (原文没第八章答案)数据结构(C语言版 第2版)课后习题答案 严蔚敏 等 编著,仅供参考,还是自己认真做了再看第1章  绪论 5.选择题(1)在数据结构中,从逻辑上可以把数据结构分成(  C )。A.动态结构和静态结构     B.紧凑...

加载 bean*.xml_weixin_30782293的博客-程序员秘密

入口ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:bean*.xml");    /** * Main entry point. * @return {@code true} if the string matches agai...

c语言max函数是什么,什么是C语言函数_张个个的博客-程序员秘密

什么是C语言函数int max(a,b)int a,b;{if (a>b) return a;else return b;}第一行说明max函数是一个整型函数,其返回的函数值是一个整数。形参为a,b。第二行说明a,b均为整型量。 a,b 的具体值是由主调函数在调用时传送过来的。在{}中的函数体内, 除形参外没有使用其它变量,因此只有语句而没有变量类型说明。 上边这种定义方法称为“传统格式”。...

离散数学及其应用第六版中文电子书和答案_离散数学第六版电子书_a596643025的博客-程序员秘密

扫描版书: 链接: https://pan.baidu.com/s/1ew2xPyQyFgBwz9J3lyoQKQ 提取码: 1sne答案: 链接: https://pan.baidu.com/s/1cgY-QwcQSZ9A8skwo5R8cg 提取码: ksu4

JdbcTemplate_jdbctemplate findone__ady的博客-程序员秘密

1、什么是 JdbcTemplate(1)Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作.2、搭建环境(1)引入相关 jar 包(2)在 spring 配置文件配置数据库连接池 <!--配置数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <pro

vue-cli项目 使用 js-cookie_vue-cil 2.9.6 jscookie_成茂峰的博客-程序员秘密

js-cookie github地址https://github.com/js-cookie/js-cookie使用方式npm install js-cookie --save引入js-cookieimport Cookies from 'js-cookie'使用js-cookie获取cookie对应的值import Cookies from 'js-cookie'// 获取...

随便推点

Opencv中仿射变换函数_opencv中的仿射函数_tyf122的博客-程序员秘密

2DRotationMatrix 2DRotationMatrix计算二维旋转的仿射变换矩阵 CvMat* cv2DRotationMatrix( CvPoint2D32f center, double angle,double scale, CvMat* map_matrix );center 输入图像的旋转中心坐标 angle 旋转角

BZOJ 2302: [HAOI2011]Problem c [DP 组合计数]_weixin_30613727的博客-程序员秘密

2302: [HAOI2011]Problem cTime Limit:30 SecMemory Limit:256 MBSubmit:648Solved:355[Submit][Status][Discuss]Description给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第...

JQuery鼠标移到图片改变,移出图片恢复原来图片_不问归期的博客-程序员秘密

JQuery鼠标移到图片改变,移出图片恢复原来图片<script src="js/jquery-1.11.2.min.js"></script> <script type="text/javascript">$(document).ready(function(){ $(".imgdiv").mouseover(function(){ $(".imgsrc").attr("src","images/adver2.jpg");

利用用户自己的server、tomcat下的解决iOS7.1企业应用无法安装应用程序 由于证书无效的问题_由于证书问题,无法安装应用程序。证书与安装的应用程序证书不匹配,或证书不支持应_whackw的博客-程序员秘密

1、环境(1)操作系统:Windows server 2003、Windows server2008(2)JDK:jdk 1.6(3)apache-tomcat-6.0.35(注意版本号号,版本号6.0.18測试未通过)(4)网络:互联网、专网測试均通过。2、使用到的软件、jar包(1)Win32OpenSSL_Light-1_0_1

2020-01-06 Docker入门1_qq_42720896的博客-程序员秘密

Docker简介•官网 www.docker.com• github https://github.com/docker/docker.github.io• 开源的容器引擎,可以让开发者打包应用以及依赖的库,然后发布到任何流行的linux发行版上,移植很方便• 由go语言编写,基于apache2.0协议发布• 基于linux kernel,要想在win下运行需要借助一个vm(...

01.Vuepress2.x 创建自己的技术文档站_AvatarGiser的博客-程序员秘密

一、简介Vuepress2.x 英文官网Vuepress2.x 中文官网二、安装参考步骤1:新建一个文件夹,如:Doc2.0步骤2:进入文件夹目录,新建 package.json,命令:npm init步骤3:安装本地依赖,我当时使用的是如下版本,可在此找到自己需要的npm i [email protected]步骤4:在 package.json 中添加如下信息"scripts": { "docs:dev": "vuepress dev

推荐文章

热门文章

相关标签