selenium自动化原理应用 - 利用 requests 模拟 selenium 驱动浏览器

前言

selenium是一个web自动化测试的开源框架,它支持多语言:python/java/c#…

前面也有一篇文章说明了,selenium+浏览器的环境搭建。

selenium支持多语言,是因为selenium与浏览器驱动之间是通过http协议进行通信的。只关心通信的数据是否能够正确解读 ,并不关心这个数据是从哪个客户端来。无论来自python\java,还是jmeter,postman都没有问题。

本篇文章中,以requests做为客户端,跳过selenium,直接与谷歌浏览器驱动(chromedriver)进行http通信,驱动chrome浏览器去执行命令。

requests库

先解释一下requests库:一个python的第三方库,是目前最好用的http请求库。

直接封装了get请求、post请求。

只需要提供 请求url、请求方法、请求内容即可。

以下为request库使用的简单示例(request的详细使用可参看其它博主其它的博文):


import requests


s = requests.session()

response = s.get("http://www.baidu.com") # 发起get请求

print(response.text) # 获取响应结果的 响应数据

res = response.json() # 将 响应数据 转换成python数据对象。

如果我要利用requests库,去向chromedriver发送请求。那么我必须得了解请求的类型、请求的数据、请求的内容是什么。

基于此,我们需要了解在selenium库当中,会有哪些请求?

需要解决的问题

  1. selenium有哪些请求?
  2. 每一个请求的请求url、请求类型如何获取?
  3. 每一个请求的请求数据又如何获取?

selenium - json wire protocol - 获取请求url和类型

要想解决以上3个问题,我们需要了解selenium的部分原理。

在selenium与驱动进行http通信的协议全称叫做:json wire protocol.

我们在使用selenium库驱动浏览器的时候,我们的操作有一部分大概是以下这样的:

  1. 打开chrome浏览器;
  2. 访问某一个网址;
  3. 查找该网址中的某一个元素;
  4. 操作3)中查找到的元素。

在selenium库看来,以上每一步操作都是一个http请求,也叫做命令(Command)。

chromedriver在收到这个请求之后,再去驱动对chrome浏览器执行对应的动作。

所以,在selenium库当中,存储了所有命令(Command)名称、命令对应的http请求类型、命令对应的请求url。

首先,来看看Command的名称(选取几个大家熟知的操作):

访问网站命令(GET)对应的请求类型和请求url为:

从上图可以看出,GET命令是post请求,请求地址只有一部分。

url中有3个问题:

1)请求的url并不完整。

url中,缺失中base地址。base地址为,chromedriver的ip+端口号。因为,命令是发给chromedriver去执行的。

2)url当中的$sessionId是什么?

在selenium当中,每开启一次与chromedriver的会话,都会生成一个会话ID。sessionId就是这个会话ID。在很多的命令请求当中,在请求地址中,通过sessionId都绑定了当前的会话。

换句话说,我们要用requests与chromedriver进行通信,那么我们首先,得生成会话ID,并得到这个ID值,才能够进一步的去访问网页,去发送更多的浏览器操作命令。

3)sessionId从何而来?如何获取?

在selenium当中,通过NEW_SESSION请求来开启会话,chromedriver在收到请求后,在响应数据中,返回本次会话的sessionId


请求的参数如下(启动什么类型的浏览器、有什么配置参数):


params = {'capabilities': {

'firstMatch': [{}],

'alwaysMatch': {'browserName': 'chrome',

'platformName': 'any',

'goog:chromeOptions': {'extensions': [], 'args': []}

}},

'desiredCapabilities': {'browserName': 'chrome',

'version': '',

'platform': 'ANY',

'goog:chromeOptions': {'extensions': [], 'args': []}}

}


chromedriver在正常收到请求之后,响应的数据如下(主要为sessionId):


{

"sessionId": "ed76b48661b6fe58b9be6f56716531b7", # 本次会话的sessionId

"status": 0,

"value": {

"acceptInsecureCerts": false,

"acceptSslCerts": false,

"applicationCacheEnabled": false,

"browserConnectionEnabled": false,

"browserName": "chrome",

"chrome": {

"chromedriverVersion": "74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29})",

"userDataDir": "/var/folders/gm/k4pj0kf50vz9f3gznsp4cn340000gn/T/.com.google.Chrome.OPZURo"

},

"cssSelectorsEnabled": true,

"databaseEnabled": false,

"goog:chromeOptions": {

"debuggerAddress": "localhost:63649"

},

"handlesAlerts": true,

"hasTouchScreen": false,

"javascriptEnabled": true,

"locationContextEnabled": true,

"mobileEmulationEnabled": false,

"nativeEvents": true,

"networkConnectionEnabled": false,

"pageLoadStrategy": "normal",

"platform": "Mac OS X",

"proxy": {},

"rotatable": false,

"setWindowRect": true,

"strictFileInteractability": false,

"takesHeapSnapshot": true,

"takesScreenshot": true,

"timeouts": {

"implicit": 0,

"pageLoad": 300000,

"script": 30000

},

"unexpectedAlertBehaviour": "ignore",

"version": "75.0.3770.100",

"webStorageEnabled": true

}

}

ps: 可访问此网站了解详情:https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol
 

selenium - 每一个命令函数 - 设置请求数据

以上我们获取到了每一个命令的请求地址和请求类型。那么请求数据从哪里获取 呢?

每一个命令的功能不一样,请求的数据也就不一样。在selenium当中,都是在命令对应的函数当中去设置请求数据的。

比如,访问网址操作命令,在selenium当中是get函数,那么我们去看get函数的源码:

在上图中的execute函数当中,第二个参数params对应的就是请求数据。所以get命令的请求体为:{"url":调用get函数传进来的url值}
再比如,查找元素命令,在selenium当中是find_element函数,那么我们去看find_element的源码:

所以find_elment命令的的请求体为:{"using":定位类型,"value":定位表达式}

利用requests - 开启浏览器会话、访问百度首页、搜索柠檬班

  1. 启动本地电脑 上的chromedriver程序。双击即可。默认的服务端口为9515

2. 通过requests库向chromedriver发起会话、并打开百度首页的代码如下:


#!/usr/bin/python3

# -*- coding: utf-8 -*-

# Name: use_request_send_http_chromedriver

# Author: liyuan

# Time: 15:52


# 1、base_url从哪里来的?如何确定?

# 2、命令的请求类型从哪里来的?请求地址从哪里来的?

# 3、请求参数从何获取。


import requests


# chromedriver服务的base地址。

base_url = "http://127.0.0.1:9515"

# 创建会话

s = requests.Session()



# **************************向chromedriver发送的命令1:建立会话**************************


# 创建与chromedriver会话的请求数据

params = {'capabilities': {

'firstMatch': [{}],

'alwaysMatch': {'browserName': 'chrome',

'platformName': 'any',

'goog:chromeOptions': {'extensions': [], 'args': []}

}},

'desiredCapabilities': {'browserName': 'chrome',

'version': '',

'platform': 'ANY',

'goog:chromeOptions': {'extensions': [], 'args': []}}

}


# 创建与chromedriver的会话。注意请求数据格式是application/json

res = s.request("POST",base_url+'/session',json=params)

# 获取sessionId值

sessionid = res.json()["sessionId"]



# **************************向chromedriver发送的命令2:打开网址**************************


# 请求数据

datas = {'url': "http://www.baidu.com"}

# 请求地址拼接

url = base_url + "/session/{}/url".format(sessionid)

# 发送打开百度首页的请求,注意请求数据格式是application/json

res = s.request("post",url,json=datas)



# # **************************向chromedriver发送的命令3:找到搜索输入框**************************

# 请求数据

datas3 = {'using':"id","value":"kw"}

# 请求地址拼接

url3 = base_url + "/session/{}/element".format(sessionid)

# 发送打开百度首页的请求

res3 = s.request("post",url3,json=datas3)

# 返回结果类似:{"sessionId":"2dae661546b28cd481d84048310fb196","status":0,"value"{"ELEMENT":"0.899392980463724-1"}}

# 获取元素的id

ele_id = res3.json()["value"]["ELEMENT"]



# *****************向chromedriver发送的命令4:在搜索框当中输入 柠檬班******************

# /session/$sessionId/element/$id/value

# 请求数据

datas4 = {'text': '码尚接口自动化测试', 'value': ['码', '尚', '接']}

# 请求地址拼接

url4 = base_url + "/session/{}/element/{}/value".format(sessionid,ele_id)

# 发送打开百度首页的请求

res4 = s.request("post",url4,json=datas4)

以上代码运行的结果如下:

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值