selenium-webdriver 阿里云ARMS 自动化巡检

news2024/11/25 12:34:09

    很久没更新了,今天分享一篇关于做项目巡检的内容,这部分,前两天刚在公司做了部门分享,趁着劲还没过,发出来跟大家分享下。

一、本地巡检实现

1. Selenium Webdriver(SW) 简介

Selenium Webdriver(以下简称SW) 是一个用于自动化 web 浏览器操作的工具。

它提供了一组用于模拟用户在网页中的交互的 API,可以通过编程方式来控制浏览器并执行各种操作,例如点击、填写表单、提取数据等。

SW 支持多种编程语言,包括 Java、Python、JavaScript(Node.js)等,本次分享我们主要关注 SW 的 JavaScript 版本。

2. SW 能做什么

  • 自动化测试:Selenium Webdriver 可以通过编写代码来模拟用户在浏览器中的行为,例如点击链接、填写表单、提交数据、执行搜索等。它提供了对多种浏览器的支持,包括 Chrome、Firefox、Safari、Edge、Internet Explorer 等,可以用于编写和执行自动化测试用例,验证 Web 应用程序的功能和性能。

  • 浏览器自动化:Selenium Webdriver 可以以编程方式控制浏览器的行为和属性,例如打开指定的网址、最大化窗口、切换标签页、处理弹窗、截图等。它能够模拟真实用户在浏览器中的操作,并提供对 DOM 元素的定位和操作的方法。

  • 数据抓取:Selenium Webdriver 可以被用于抓取网页上的数据。通过模拟用户的交互操作,可以实现从网页上提取信息、进行表单填充和提交、模拟点击和滚动等操作,以便自动化地获取需要的数据。

  • 跨浏览器测试:Selenium Webdriver 提供了一致的 API,可以编写一套测试脚本并在不同的浏览器上运行,以验证 Web 应用程序在各个浏览器上的兼容性和一致性。

3. SW 巡检

这个是当前ARMS上最主要的监控指标,我们每天巡检要做的事,就是对这些数据做采集;同时对比过往指标,做异常分析、性能监控、用户行为分析等相关工作

3.1 浏览器相关

3.1.1 浏览器驱动

浏览器

驱动

chrome

chromedriver.exe

Firefox

 geckodriver.exe

IE

 IEDriverServer.exe

3.1.2 浏览器相关配置
const { Options } = require('selenium-webdriver/chrome')

let options = new Options() 
options.addArguments('--headless')
options.addArguments('--no-sandbox')
options.addArguments('--disable-gpu-sandbox')
options.addArguments('--disable-dev-shm-usage')
options.addArguments('--disable-extensions')
options.addArguments('--remote-debugging-port=9222')   
options.addArguments('--window-size=1920,1080'); 

options.addArguments('--start-fullscreen')    
options.addArguments('disable-blink-features=AutomationControlled') 

说明

参数

描述

--headless

无界面模式,Linux 上运行时由于缺少图形界面,可以避免显示窗口相关问题

--no-sandbox 

 禁用 Chrome 浏览器的沙盒模式,避免在无界面模式下的一些权限问题

--disable-gpu-sandbox

禁用 Chrome 浏览器的 GPU 沙盒,也是为了避免在无界面模式下出现问题

--disable-dev-shm-usage

 禁用 Chrome 浏览器的 /dev/shm 临时文件系统的使用

--disable-extensions

禁用 Chrome 浏览器的扩展插件功能,提高运行效率

--remote-debugging-port=9222

启用 Chrome 浏览器的远程调试端口,允许远程调试协议与浏览器进行交互

--window-size=1920,1080

 设置浏览器窗口大小

--start-fullscreen

 全屏模式

disable-blink-features=AutomationControlled

禁用 AutomationControlled特性,以避免被浏览器检测到自动化程序的控制。

3.2 巡检流程

巡检基本流程

1)登录                     输入账号、密码、滑动验证

2)获取数据             读取DOM文本、模拟接口获取数据

3)生成表格并发送  将数据转化成带样式的表格,通过企微机器人发送到微信群

3.2.1 登录
// 跳转登录页
await driver.get('https://signin.aliyun.com/login.htm?callback=https%3A%2F%2Farms.console.aliyun.com%2Fretcode#/main')
driver.manage() 

// 等待页面加载完成
await driver.wait(async function () {
  let readyState = await driver.executeScript('return document.readyState')
  console.info('\x1B[37m ♫ Login  readyState=' + readyState)
  return readyState === 'complete'
}, 3000)
await sleep(1000)

// 输入用户名
let inputEl = await driver.findElement(By.xpath('//input[@name="username"]'))
await inputEl.clear();
await sleep(100)
await inputEl.sendKeys(USERNAME)
await sleep(100)
await (await driver.findElement(By.css('.next-col > button.next-btn-primary'))).click();

// 等待
await sleep(2000)
await driver.wait(async function () {
  let readyState = await driver.executeScript('return document.readyState')
  return readyState === 'complete'
}, 5000)

// 输入密码
let pwdInputEl = await driver.findElement(By.xpath('//input[@name="password"]'))    
await pwdInputEl.clear();
await sleep(100)
await pwdInputEl.sendKeys(PASSWORD)
await sleep(3000)

// 点击登录
await (await driver.findElement(By.css('.next-col > button.next-btn-primary'))).click();
await sleep(5000)
url = await driver.getCurrentUrl()

// 滑块验证
if(url.indexOf('https://signin.aliyun.com/login.htm') === 0){
  slideVerify(driver,'#baxia-dialog-content','.sm-pop-inner .btn_slide');
  await sleep(5000)
}

3.2.2 获取数据
1)读取DOM文本
async function getPvData(driver, times = 0) {
  const resultMap = {}
  try {
    let pvSpan = await driver.findElement(By.css('div[data-e2e-id="summary-title-pv"] span.noclick-title'))
    let uvSpan = await driver.findElement(By.css('div[data-e2e-id="summary-title-uv"] span.noclick-title'))
    let jsErrorRate = await driver.findElement(By.css('span[data-e2e-id="card-content_title-jsErrorRate"]'))
    let apiSucRate = await driver.findElement(By.css('span[data-e2e-id="card-content_title-api"]'))
    let jsError = await driver.findElement(By.css('span[data-e2e-id="card-content_title-jsError'))
    let apiError = await driver.findElement(By.css('span[data-e2e-id="card-content_title-apiError"]'))
    let resourceError = await driver.findElement(By.css('span[data-e2e-id="card-content_title-resourceError"]'))
    const pvData = await pvSpan.getText()
    const jsErrorRateData = await jsErrorRate.getText()
    const apiSucRateData = await apiSucRate.getText()
    const jsErrorData = await jsError.getText()
    const apiErrorData = await apiError.getText()
    const uvData = await uvSpan.getText()
    const resourceErrorData = await resourceError.getText()
    if (!pvData || pvData.indexOf('--') > -1 || !jsErrorRateData || jsErrorRateData.indexOf('--') > -1 || !apiSucRateData || apiSucRateData.indexOf('--') > -1
      || !jsErrorData || jsErrorData.indexOf('--') > -1  || !uvData || uvData.indexOf('--') > -1) {
      if (times > 8) {
        return null
      }
      await sleep(3000)
      return await getPvData(driver, ++times)
    } else {
      resultMap.pv = pvData
      resultMap.jsErrorRate = jsErrorRateData
      resultMap.apiSucRate = apiSucRateData
      resultMap.jsError = jsErrorData
      resultMap.apiError = apiErrorData
      resultMap.uv = uvData 
      resultMap.resourceError = resourceErrorData
      
      return resultMap
    }
  } catch (e) {
    if (times > 8) {
      return null
    }
    await sleep(3000)
    return await getPvData(driver, ++times)
  }
}

元素定位方法


driver.findElement(By.css('.btn_slide'))

driver.findElement(By.id("login_button"))

driver.findElements(By.className('con_list_item'))

driver.findElement(By.xpath('//input[@name="fm-login-id"]'))

driver.executeScript('document.querySelector(\'.sts-loginout-wrap\').click()') 

2)模拟发起请求
function requestWhiteScreen(driver, cookie, startDate, endDate, appId, page) {
  const intervalMillis = 2147483647,
   token = getQueryStr('XSRF-TOKEN', cookie.replace(/;/g, '&'))
  return driver.executeScript(`
    return window.fetch('https://arms.console.aliyun.com/api/retcode.json?action=RetcodeAction&eventSubmitDoGetDatas=1', { 
      method: 'post', 
      credentials: 'include',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        'cookie': '${cookie}',
        'X-XSRF-TOKEN': '${token}'
      },
      body: 'queryParams=%7B%22metric%22%3A%22webstat.sum%22%2C%22measures%22%3A%5B%22sum_val%22%5D%2C%22filters%22%3A%7B%22appId%22%3A${appId}%7D%2C%22dimensions%22%3A%5B%22key%22%5D%2C%22intervalMillis%22%3A${intervalMillis}%2C%22startTime%22%3A${startDate}%2C%22endTime%22%3A${endDate}%2C%22orderBy%22%3A%22sum_val%22%2C%22order%22%3A%22DESC%22%2C%22limit%22%3A%221000%22%7D'
    }).then(response => response.json())
  `)
}

3.2.3 生成巡检表格

为了实现表格的良好视觉效果,采用了两个主要组件,分别是 xlsx 和 xlsx-style。

xlsx                 数据整合成Excel表格

xlsx-style        渲染表格样式

xlsx 组件用于将数据整合成Excel表格的格式,而 xlsx-style 组件则提供了一系列丰富的表格样式,可以帮助我们实现带有样式的表格,从而提高表格的可读性和可视化效果。

效果

二、Linux 服务端部署

1. 代码部署

登录堡垒机

1)同步代码:进入存放项目的目录,上传项目压缩文件,通过指令解压:unzip xx.zip

2)安装依赖:npm i

3)测试巡检:npm run xx

2. 添加定时任务

2.1 创建执行文件

项目目录下,创建Shell脚本执行文件,如:h5-linux.sh

说明

  1. killall -9 xx   结束其他关联进程

  2. npm run xx        执行巡检指令

2.2 添加定时任务 

1)查看当前的定时任务:终端窗口输入 crontab -l 指令

crontab相关可参考:crontab使用方法

2)添加定时任务:终端窗口输入 crontab -e 指令,进入编辑界面,添加定时任务(*最后一个用于测试)

格式:

*     *    *   *   *  command       分   时   日   月  周   命令

说明

示例    30 8 1,15,25 * * command   每月1、15、25日的 8 : 30 执行一次

语法

 描述

*

代表所有可能的值,从左到右:分钟、小时、日期、月、星期几;

其中分钟以 0-59、小时以1~23 (0表示0点) 、日期以 1-31 、月份以 1-12 、星期几以 0-6 的数字表示(0 表示星期日,1 表示星期一,以此类推)。 如每小时的第15分钟执行一次:      15 * * * * command

,

可以用逗号隔开的值指定一个列表范围,例如:1,2,5,7,8,

-

可以用整数之间的中杠表示一个整数范围,例如 2-6 表示:2,3,4,5,6

/

用于指定时间区间,如:* 18-8/1 * * * command  晚上18点到早上8点之间,每隔一小时执行一次

2.2 测试定时任务

执行:./文件名.sh  或 sh 文件名.sh 运行任务

3. 配置日志

配置日志,用于记录巡检流程,确定问题的来源,并进行相关的故障排查。

方法:进入编辑界面,在对应任务后面新增日志

说明

语法

描述

 >> 目录/文件名.log

 日志输出目录/文件

2>&1  

是一种将标准错误输出(stderr)重定向到标准输出(stdout)的方法;确保即使发生错误,也能完整记录脚本的输出和错误信息。

三、企微机器人

1. 创建机器人

企微群 (右上角) > ... > 添加群机器人 > 新创建一个机器人 > 输入机器人名称 > 添加机器人 

2. 发送消息

获取key:点击群机器人,从Webhook 地址获取到key

2.1 发送文档

1)文件上传:

配置 formData,通过文件上传接口,将文档上传到文件系统,获取到 media_id(文件标识名)

2)发送文件到企微群:

通过配置消息类型文件标识名,使用发送接口,将文件发送到企微群中,并@对应负责人对异常指标进行分析

const key = 'xx'  
async function sendWx(filePath) {       
  const readStream = fs.createReadStream(filePath)
  const formData = new FormData()
  formData.append('media', readStream)   
  const mediaId = await axios.post(`https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=${key}&type=file`, formData)  
  axios({ 
    url:`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${key}`,
    method: 'post', 
    headers: {
      'Content-Type': 'application/json',
    },
    data: {
      msgtype: 'file',
      file: {
        'media_id': mediaId?.data?.media_id||''
      }
    }  
  }).then(() =>{ 
    fs.unlinkSync(filePath) 
    console.info('\x1B[37m✔ 巡检已发送企微群\x1B[32m')  
    const { mobile } = dutyArrangement()    
    if(mobile){ 
      sentWxMsg('请项目负责人填写指标分析',mobile)
    }
  })    
}

2.2 发送消息

消息支持多种类型的配置,用户可以根据自身需求,选择不同的消息类型

msgtype 支持类型

  • text                        文本消息
  • file                        文件消息
  • markdown                 Markdown 格式的消息
  • image                      图片消息
  • news                       新闻消息
  • template_card        模板卡片消息
async function sentWxMsg(content,mentioned_mobile_list=[]){
  axios({ 
    url:`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${key}`,
    method: 'post', 
    headers: {
      'Content-Type': 'application/json',
    },
    data: {
      msgtype: 'text',       
      text: {
        content,       
        mentioned_mobile_list,
      }    
    } 
  }).then(() =>{ 
    console.info('\x1B[37m✔ 巡检提示已发送企微群\x1B[32m')  
  })  
}

说明

参数

说明

msgtype

  消息类型

content

消息内容

mentioned_mobile_list

手机号列表,提醒手机号对应的群成员(@某个成员),@all表示提醒所有人

 Markdown 格式的消息

async function sentWxMarkdownMsg(content,tip){
  axios({ 
    url:`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${key}`,
    method: 'post', 
    headers: {
      'Content-Type': 'application/json',
    },
    data: {
      msgtype: 'markdown',       
      markdown: {
        content            
      }
    } 
  }).then(() =>{ 
    console.info(`\x1B[37m✔ ${tip}\x1B[32m`)  
  })  
}

const markdown = '昨天:ARMS--JS错误数:<font color="warning">8,686</font>,上周平均值为:<font color="info">2025.29</font>'
sentWxMarkdownMsg(markdown,'错误提示')

 *注意:markdown消息不支持@成员

效果

图文消息

async function sentWxNewsMsg(news={},tip){
  axios({ 
    url:`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${key}`,
    method: 'post', 
    headers: {
      'Content-Type': 'application/json',
    },
    data: {
      msgtype: 'news',       
      news      
    } 
  }).then(() =>{ 
    console.info(`\x1B[37m✔ ${tip}\x1B[32m`)  
  })  
}

 const news = {
    articles : [
      {
          title : '🌕月满情浓,好耶相送',
          description : '花好月圆人团圆,迎风赏月合家欢',
          url : 'https://www.baidu.com/',
          picurl:'https://i.hd-r.cn/317e50d14adb76e4e322df93a1da07b1.png'                
      }
   ]
}
sentWxNewsMsg(news,'图文消息已发送')

效果

最后,佳节将至,祝大家:

花好月圆人团圆,迎风赏月合家欢 ♥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1033648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用接口包装器模块简化在FPGA上实现PCIe的过程

许多最终应用程序都将基于FPGA的设计用作其解决方案的固有组件。他们通常需要PCI Express&#xff08;PCIe&#xff09;作为必不可少的功能&#xff0c;以提供与系统中其他组件的标准化接口。 从历史上看&#xff0c;PCI Express一直难以在FPGA中实现&#xff0c;因为它需要具…

一、博弈论概述

知人者智&#xff0c;自知者明&#xff1b;胜人者力&#xff0c;自胜者强&#xff1b;小胜者术&#xff0c;大胜者德。 一、什么是“博弈” &#xff08;一&#xff09;博弈的定义 博&#xff1a;博览全局&#xff1b;弈&#xff1a;对弈棋局&#xff0c;最后做到谋定而动。…

文件包含漏洞的 00截断

isset&#xff08;&#xff09;函数若变量不存在则返回 FALSE&#xff1b;若变量存在且其值为NULL&#xff0c;也返回 FALSE。若变量存在且值不为NULL&#xff0c;则返回 TURE %00是被服务器解码为0x00发挥了截断作用。核心是chr(0)字符 00截断上传原理 - 知乎 协议参考地址&…

科研之路(2023.9.21)

惰轮 麦轮 https://mp.weixin.qq.com/s/sjb3O91auADKN7iDsut0jA 理解底盘代码

FL Studio 21内置鼓机FPC怎么用 常用编曲鼓点怎么排列

FL Studio 21内置鼓机FPC怎么用&#xff1f;FPC是一款模拟硬件打击垫建模的鼓机&#xff0c;使用方法和硬件打击垫很像&#xff0c;但是多出了修改采样等更加细节的功能。常用鼓点怎么排列&#xff1f;电子音乐中常见的鼓点有4/4拍鼓组和Trap类型鼓组。 FL Studio Win-安装包&a…

【ODPS 新品发布第 2 期】实时数仓 Hologres:推出计算组实例/支持 JSON 数据/向量计算+大模型等新能力

云布道师 阿里云 ODPS 系列产品以 MaxCompute、DataWorks、Hologres 为核心&#xff0c;致力于解决用户多元化数据的计算需求问题&#xff0c;实现存储、调度、元数据管理上的一体化架构融合&#xff0c;支撑交通、金融、科研、等多场景数据的高效处理&#xff0c;是目前国内最…

S7通信协议的挑高点

目录 1. S7协议之布尔操作 2. S7协议之PDU读取 3 S7协议之多组读取 在电气学习的路上&#xff0c;西门子PLC应该是每个人的启蒙PLC&#xff0c;从早期的S7-300/400PLC搭建Profibus-DP网络开始接触&#xff0c;到后来的S7-200Smart PLC&#xff0c;再到现在的S7-1200/1500 PLC…

leetcode 10. 正则表达式匹配

2023.9.20 感觉是目前做过dp题里最难的一题了... 本题首要的就是需要理解题意&#xff0c;翻了评论区我才发现之前一直理解的题意是错的。 我原来理解的 “ *匹配0次” 是指&#xff1a;*直接消失&#xff0c;不会影响到前面的字符。 但是*和前一个字符其实是连体的&#xff0…

学习路之PHP--lumen安装配置

一、下载lumen源码 composer create-project --prefer-dist laravel/lumen blog 安装lumen-generator composer require flipbox/lumen-generator 二、配置 bootstrap\app.php 97行 $app->register(Flipbox\LumenGenerator\LumenGeneratorServiceProvider::class);三、生成…

MQ - 24 RabbitMQ集群架构设计与实现

文章目录 导图集群构建节点发现元数据存储数据可靠性镜像队列仲裁队列安全控制传输加密身份认证资源鉴权可观测性总结导图 集群构建 集群构建由节点发现和元数据存储两部分组成。RabbitMQ 也是一样的实现思路。 节点发现 在节点发现方面,RabbitMQ 通过插件化的方式支持了多…

Centos下载配置Maven

Linux下安装配置Maven 注意&#xff1a;没配置JDK的先把JDK给配置了&#xff0c;JDK环境变量名为JAVA_HOME 1、安装wget命令 如果需要通过使用wget命令&#xff0c;直接通过网络下载maven安装包时&#xff0c;需要在linux系统中安装wget命令。 yum -y install wget2、下载m…

基于SpringBoot的企业客户管理系统的设计与实现【附PPT|万字文档(LW)和搭建文档】

主要功能 后台登录&#xff1a; 可注册员工&#xff1a;工号、密码、姓名、身份证、手机、邮箱 员工&#xff1a; ①首页、个人中心、修改密码、个人信息 ②客户信息管理、项目信息管理、项目收益管理等 后台登录&#xff1a; 管理员&#xff1a; ①首页、个人中心、修改密码、…

【Flowable】Flowable自动生成的数据库表的含义

一、Flowable简介 Flowable是一个开源的工作流引擎&#xff0c;它的主要目标是提供一个灵活、可扩展、可靠的流程管理系统。Flowable通过提供一组API和工具&#xff0c;使组织能够自动化和管理其业务流程。 二、Flowable中的数据库 Flowable使用数据库来存储和管理其运行时的…

qt matlab 混合编程

1.环境的说明 matlab 2021a qt 5.12.10 qt creator 4.13.1 opencv 4.3.0 eigen-3.4.0/eigen-3.4.0 2.matlab 中导出dill 以aberr_analy1的导出dill举例 命令行中输入&#xff1a;deploytool 2. 选择LIbrarycompiler 3type 选择c 4,选择相应的 5. 点击package 选择保存的路径…

“新KG”视点 | 漆桂林——知识图谱和大语言模型的共存之道

OpenKG 大模型专辑 导读 知识图谱和大型语言模型都是用来表示和处理知识的手段。大模型补足了理解语言的能力&#xff0c;知识图谱则丰富了表示知识的方式&#xff0c;两者的深度结合必将为人工智能提供更为全面、可靠、可控的知识处理方法。在这一背景下&#xff0c;OpenKG组织…

psd-tools

安装 使用 PSD document layers Exporting data to PIL Exporting data to Numpy psd_tools.api.layers PixelLayer TypeLayer 参考资料 psd-tools/psd-tools psd-tools psd-tools/usage 使用psd-tools更改文本层的文本 psd_tools设置文本 https://blog.csdn.net/qq_4010957…

位移贴图的实现原理

在以前的文章中介绍过GLTF编辑器 &#xff0c; 编辑器可以对模型的各种材质纹理进行编辑修改&#xff0c;但是有一些新手用户可能对这些材质纹理不太了解&#xff0c;所以我收集了一些资料对这些材质纹理做一下详细的介绍&#xff0c;今天这篇文章主要是介绍位移贴图。 1、什么…

Leetcode 386. 字典序排数

文章目录 题目代码&#xff08;9.22 首刷看解析&#xff09; 题目 Leetcode 386. 字典序排数 代码&#xff08;9.22 首刷看解析&#xff09; 迭代DFS class Solution { public:vector<int> lexicalOrder(int n) {vector<int> ret(n);int number 1;for(int i 0…

vue下载Excel文件

前端vue实现导出Excel文件 用到的是 上代码 var wb XLSX.utils.table_to_book(document.querySelector(#my-table));//关联dom节点 这个是表格绑定的id名称var wbout XLSX.write(wb, {bookType: xlsx,bookSST: true,type: array})try {FileSaver.saveAs(new Blob([wbout], {…

【C++】STL详解(七)—— stack和queue的使用及模拟实现

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】STL…