前言:
Selenium 一直是UI自动化框架的中流砥柱 而webdriver和对应版本的浏览器 也一直是使用Selenium这个库所绕不过去的门槛 本次文章中 我们将通过一个示例演示一下如何使用http请求+ws长链接 在不强制版本和不使用webdriver的情况下进行浏览器元素操作和页面的打开关闭
环境: golang 1.18
前置:
知其然知其所以然 首先我们需要知道 Selenium是如何跟浏览器进行交互的 他的原理是什么 以Python为例

在这里, selenium启动了一个服务 我们首先来看这个服务里做了什么事情

这里执行了一个cmd命令 用于启动一个服务,当服务无法启动或无法连接上时 会抛出一个异常


这里Selenium会通过ws一直去连接一个服务当服务连接上时返回一个成功的标识

那么这个服务是从哪里来的呢? 发送的这些请求有什么用处呢?接下来我们来认识一个协议: CDP(Chrome DevTools Protocol)
CDP(Chrome DevTools Protocol)
chrome devtools protocol允许第三方对基于chrome的web应用程序进行调试、分析等,它基于WebSocket,利用WebSocket建立连接DevTools和浏览器内核的快速数据通道。一句话,有了这个协议就可以自己开发工具获取chrome的数据
那到底怎么进行调试呢? 我们以chrome为例(我使用的是基于chrome内核二开的浏览器本质上与chrome一致):
首先找到浏览器在本地的安装地址:

接下来 我们在当前位置打开cmd命令行工具 执行以下命令:

chrome.exe --remote-debugging-port=9222

我们可以看到 打开了一个新的浏览器并在本地的9222端口上建立了一个浏览器服务

既然有服务 那么肯定就有外放的接口:
http://localhost:9222/json/list

我们能看到 该接口返回了一个数组.并且数组内有json响应值 接下来我们来解释一下其中内容
devtoolsFrontendUrl:当前页面的地址, 通过该参数加上localhost:9222/ 可以对该tab页进行操作
id: 服务返回的tab页所属id
type: 页面的类型 page为当前页面 iframe为嵌套页面
url: 内部访问的地址
webSocketDebuggerUrl: ws连接的地址 而看到这个地址 相比大家也就明白了Selenium为什么会去创建ws连接了
服务启动了,ws地址有了 那么参数怎么设计呢? 怎么就可以去操作浏览器的元素了呢? 接下来我们来认识一下ws的信令内容 共分为三部分:
id: 发送的指令唯一标识 后续CDP程序会根据该id返回内容
method: 调用的CDP方法
params: 本次请求中需要用到的参数
举个栗子:

{ID:     111, // 自己定义Method: "Page.navigate", // 官方定义好的 可以通过Chrome DevTools Protocol官方地址查看Params: map[string]interface{}{  // 消息体"url": "https://xxxxx.xxxxx.com/drelease/#/project/",},},

这里我们简单列举三个method 而这三个方法也是UI页面操作中最常用的三个:
page.navigate: 访问params参数中的url地址
expression: 执行javaScript方法
Browser.close 关闭浏览器

接下来 我们开始与浏览器进行交互

如果打算个人应用 可以通过os.exec先去将浏览器的服务启动起来, 在通过http请求获取到api接口的响应值 解析出ws的地址
本次只是为了演示 所以直接从地址中复制出来
import ("encoding/json""fmt""github.com/gorilla/websocket""log""net/url""os""os/signal""time"
)func Ws() {interrupt := make(chan os.Signal, 1) // 创建一个通道 用于监听信号signal.Notify(interrupt, os.Interrupt)// 拼接url地址u := url.URL{Scheme: "ws", Host: "localhost:9222", Path: "/devtools/page/D6E1A14E3A3FB5E1757ABDAC6F692DB1"}// 创建一个连接c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)if err != nil {log.Fatal("dial:", err)}defer c.Close()// 关闭信号的通道done := make(chan struct{})// 启动一个后台协程监听服务返回的数据并输出go func() {defer close(done)for {_, message, err := c.ReadMessage()if err != nil {log.Println("read:", err)return}log.Printf("recv: %s", message)}}()// 用一个临时结构体 进行数据拼接用于发送信令type DataMap struct {ID     int                    `json:"id"`Method string                 `json:"method"`Params map[string]interface{} `json:"params"`}dataMap := []DataMap{{ID:     111,Method: "Page.navigate",Params: map[string]interface{}{"url": "https://XXXXx/drelease/#/project/", // 第一步 打开一个地址},},{ID:     112,Method: "Runtime.evaluate",Params: map[string]interface{}{"expression":    "document.getElementById('ui_username').value = ''",// 第二步输入账号"returnByValue": true,},},{ID:     115,Method: "Runtime.evaluate",Params: map[string]interface{}{"expression":    "document.getElementById('ui_password').value = ''", //第三步输入密码"returnByValue": true,},},{ID:     117,Method: "Runtime.evaluate",Params: map[string]interface{}{"expression":    "document.getElementById('submit_login').click()", //第四步点击按钮"returnByValue": true,},},{ID:     119,Method: "Browser.close", // 关闭浏览器Params: nil,},}for _, v := range dataMap {// 遍历出结构体进行数据发送// ws协议发送的是二进制 所以通过json进行序列化data, _ := json.Marshal(v)if err := c.WriteMessage(websocket.TextMessage, data); err != nil {fmt.Println("消息发送失败")continue}// 延时5秒后进行下一次数据发送fmt.Printf("正在等待5秒结束当前执行的是%#v", v)time.Sleep(time.Second * 5)}// 当操作完成以后 关闭ws通道if err = c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""));err!=nil {log.Println("write close:", err)return}}

效果:

当然市面上已经很多的大佬基于这套协议封装好了框架 功能更加丰富可用 大家感兴趣的话可以在github.com上进行搜索自行查看

GO 如何利用websocket与浏览器进行交互相关推荐

  1. html5 websocket java 聊天室_如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

  2. springboot框架下利用websocket实现即时通讯

    springboot框架下利用websocket实现即时通讯(文章末尾有git项目打包文件,直接下载使用即可) 用websocket实现简单的在线聊天,先画个时序图,直观感受下流程 SystemCon ...

  3. ios浏览器滚动交互太差_使用ScrollMagic.js构建交互式滚动网站

    ios浏览器滚动交互太差 ScrollMagic is a jQuery plugin which lets you use the scrollbar like a playback scrub c ...

  4. android封装浏览器,android利用WebView实现浏览器的封装

    android提供了封装浏览器的接口,可以让开发者利用自己的view显示网页内容.今天又实现研究了一下,利用WebView显示浏览器内容,还可以利用 WebViewClient显示自己需要的内容. 效 ...

  5. html5利用websocket完成的推送功能(tomcat)

    html5利用websocket完成的推送功能(tomcat) 利用websocket和java完成的消息推送功能,服务器用的是tomcat7.0.42,一些东西是自己琢磨的,也不知道恰不恰当,不恰当 ...

  6. android利用WebView实现浏览器的封装

    android提供了封装浏览器的接口,可以让开发者利用自己的view显示网页内容.今天又实现研究了一下,利用WebView显示浏览器内容,还可以利用 WebViewClient显示自己需要的内容.中国 ...

  7. python 浏览器自动化_Python利用splinter实现浏览器自动化操作方法

    利用Splinter开发浏览器自动化操作,编写代码比较简单. 案例一: from splinter import Browser with Browser() as browser: # Visit ...

  8. html5利用websocket完成的推送功能

    程序简单来说,就是客户A可以发送消息给客户B,但有很多可以扩展的地方, 比如 1.如果加入数据库后,A发消息时客户B未上线,服务端将会把消息存在数据库中,等客户B上线后,在将消息取出发送给客户B 2. ...

  9. 利用websocket实现群聊以及单聊

    利用websocket实现群聊以及单聊 项目结构 实现代码 运行截图 在这里提供一下思路,正常情况下我们登陆进去之后就应该打开一个ws连接,以便和服务器进行通信,将打开的管道用一个set容器进行存储, ...

最新文章

  1. c语言中随机选择函数,怎样让c语言中的随机函数真正随机?
  2. GPU深度发掘(一)::GPGPU数学基础教程
  3. 归并排序算法 C++实现与时间复杂度(考过)恋上数据结构笔记
  4. [我的1024开源程序]350元写的HTML5程序
  5. 微软出品 Kubernetes 最新学习指南 v3.0
  6. kotlin学习笔记——lambda表达式
  7. 数学--数论--同余及其性质(超详细)
  8. librtmp分析(发送数据包处理)
  9. stm32程序怎么设置apb2总线时钟_stm32学习笔记
  10. C# 读取Execl和Access数据库
  11. Lapack求解线性方程组
  12. delete和truncate的区别
  13. Inno Setup 6.0.0+ 繁体中文语言包
  14. Cisco路由器密码设置
  15. C语言二级操作题满分班(2015年9月方法篇)-叶冬冬-专题视频课程
  16. Mysql的分组函数
  17. Python 手机端自动推送功能(利用极光推送API)
  18. xp系统怎么创建新宽带连接服务器地址,XP宽带连接怎么创建?
  19. 多线程同步器之CountDownLatch
  20. 数据库通过出生日期计算年龄

热门文章

  1. 【医学图像处理】MRI T1, T2 PD-加权成像
  2. 如何申请电子邮件邮箱账号?邮件系统服务器哪个稳定?
  3. vee-validate 验证
  4. 简历python技能怎么写_游戏测试简历专业技能怎么写
  5. 虚拟创业云|小霸王游戏机全集
  6. 激光溶脂效果好吗安全吗,肚子抽脂肪对身体有害吗
  7. php mq死信队列,RabbitMQ死信队列+延时队列
  8. 谁能成为“代码勇士”(3)——《观止》
  9. python中cPickle用法
  10. Hook机制之动态代理