Selenium实现原理
创始人
2024-01-22 12:15:43
0

Selenium 是目前主流的用于Web应用程序测试的工具,可以直接运行在浏览器中,就像真正的用户在操作一样。

selenium的实现原理是这样的:

1.运行代码,启动浏览器后,webdriver会将浏览器绑定到特定端口,作为webdriver的remote server;
2.Client(也就是测试脚本)借助ComandExecutor创建sessionId,发送HTTP请求(包括HTTP method, body)给remote server;
3.remote server收到HTTP请求后,调用webdriver完成操作,并将HTTP响应的结果返回给Client。

Selenium工作的过程中有三个角色,

其一便是跟我们最近的自动化测试代码:自动化测试代码发送请求给浏览器的驱动

其二便是浏览器的驱动:每个浏览器都有自己的驱动,均以exe文件形式存在,比如谷歌的chromedriver.exe、火狐的geckodriver.exe、IE的IEDriverServer.exe,

它来解析这些自动化测试的代码,解析后把它们发送给浏览器;

其三便是浏览器:执行浏览器驱动发来的指令,并最终完成工程师想要的操作

下面以谷歌浏览器为例:

首先,selenium client 会初始化一个 service 服务,通过 Webdriver 启动浏览器驱动程序 chromedriver.exe

接着通过 RemoteWebDriver 向浏览器驱动程序发送 HTTP 请求,浏览器驱动程序解析请求,并获得 sessionId,如果再次对浏览器操作需携带此 id

接下来打开浏览器,绑定特定的端口,把启动后的浏览器作为 Webdriver 的Remote Server

打开浏览器后,每一条 Selenium 脚本,一个 http 请求会被创建并且发送给浏览器,浏览器执行具体的测试步骤后再将步骤执行结果返回给 Remote Server,Remote Server 又将结果返回给 Selenium 的脚本,如果是错误的 http 代码我们就会在控制台看到对应的报错信息。

WebDriver 和 Selenium-Server 区别

你可能需要,也可能不需要 Selenium Server,取决于你打算如何使用 Selenium-WebDriver。

如果你仅仅需要使用 WebDriver API,那就不需要 Selenium-Server。

如果你所有的测试和浏览器都在一台机器上,那么你仅需要 WebDriver API。WebDriver 将直接操作浏览器。

在有些情况下,你需要使用 Selenium-Server 来配合 Selenium-WebDriver 工作,例如:
你使用 Selenium-Grid 来分发你的测试给多个机器或者虚拟机。
你希望连接一台远程的机器来测试一个特定的浏览器。
你没有使用 Java 绑定(例如 Python, C#, 或 Ruby),并且可能希望使用 HtmlUnit Driver。

底层实现原理

下面先写一个通过火狐浏览器启动百度首页的脚本:

from selenium import webdriver
import logging

logging.basicConfig(level=logging.DEBUG)  # 打印源码中的日志
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

打印日志如下:

DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:63959/session {"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "args": []}}}}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:63959
DEBUG:urllib3.connectionpool:http://localhost:63959 "POST /session HTTP/1.1" 200 794
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"102.0.5005.115","chrome":{"chromedriverVersion":"102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819})","userDataDir":"C:\\Users\\jeff.xie\\AppData\\Local\\Temp\\scoped_dir15248_1149020991"},"goog:chromeOptions":{"debuggerAddress":"localhost:63963"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"windows","proxy":{},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:credBlob":true,"webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"a402557c61699397cccbdabf77e06cd1"}} | headers=HTTPHeaderDict({'Content-Length': '794', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:63959/session/a402557c61699397cccbdabf77e06cd1/url {"url": "https://www.baidu.com"}
DEBUG:urllib3.connectionpool:http://localhost:63959 "POST /session/a402557c61699397cccbdabf77e06cd1/url HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

可以看到,首先通过 Webdriver 启动浏览器驱动程序 chromedriver.exe,打开浏览器,并获得 sessionId,然后再向带上 sessionId 向浏览器发送打开百度主页的请求。

下面自己通过 requests 模块来模拟这一系列过程(执行之前首先要打开selenium-server 服务,我是使用的 selenium-server 服务,你也可以使用浏览器服务)
 

首先在cmd中启动selenium-server  服务

 然后再Pycharm中运行以下代码

# coding=utf-8
import requestsclass MySelenium:def __init__(self):self.driver = self.my_webdriver_chrome()def my_webdriver_chrome(self):'''获取driver:return:'''driver_url = 'http://127.0.0.1:4444/wd/hub/session/'# 打开浏览器的请求参数
        driver_value = {"capabilities":{"alwaysMatch":{"browserName": "chrome", }}}# 发送求清response_session = requests.post(driver_url, json=driver_value)# 获取返回的 sessionIdprint(response_session.json())# 获取session ID my_sessionId = response_session.json()['value']['sessionId']return driver_url + my_sessionIddef my_get(self, url):'''通过get方式访问网址:param url::return:'''temp_url = self.driver + '/url'value = {'url': url}requests.post(temp_url, json=value)if __name__ == '__main__':obj_my_selenium = MySelenium()obj_my_selenium.my_get('https://www.baidu.com/')

 

在cmd中的log

10:43:36.123 INFO [ActiveSessionFactory.apply] - Capabilities are: {
  "browserName": "chrome"
}
10:43:36.124 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.chrome.ChromeDriverService)
Starting ChromeDriver 102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819}) on port 28904
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
10:43:38.565 INFO [ProtocolHandshake.createSession] - Detected dialect: W3C
10:43:38.594 INFO [RemoteSession$Factory.lambda$performHandshake$0] - Started new session f40b23a4faffac1dadf030c5073f5b7a (org.openqa.selenium.chrome.ChromeDriverService)
 

代码返回的session ID

# 获取返回的 sessionId

print(response_session.json())

{'value': {'sessionId': '287f14c5789390e0570ae8c5ae62dc9f', 'capabilities': {'acceptInsecureCerts': False, 'browserName': 'chrome', 'browserVersion': '102.0.5005.115', 'chrome': {'chromedriverVersion': '102.0.5005.61 (0e59bcc00cc4985ce39ad31c150065f159d95ad3-refs/branch-heads/5005@{#819})', 'userDataDir': 'C:\\Users\\jeff.xie\\AppData\\Local\\Temp\\scoped_dir28400_1955656845'}, 'goog:chromeOptions': {'debuggerAddress': 'localhost:49896'}, 'networkConnectionEnabled': False, 'pageLoadStrategy': 'normal', 'platformName': 'windows', 'proxy': {}, 'setWindowRect': True, 'strictFileInteractability': False, 'timeouts': {'implicit': 0, 'pageLoad': 300000, 'script': 30000}, 'unhandledPromptBehavior': 'dismiss and notify', 'webauthn:extension:credBlob': True, 'webauthn:extension:largeBlob': True, 'webauthn:virtualAuthenticators': True, 'webdriver.remote.sessionid': '287f14c5789390e0570ae8c5ae62dc9f'}}}

每一条 Selenium 脚本,

一个 http 请求会被创建并且发送给浏览器,

浏览器执行具体的测试步骤后再将步骤执行结果返回给 Remote Server,

Remote Server 又将结果返回给 Selenium 的脚本,

如果是错误的 http 代码我们就会在控制台看到对应的报错信息。
 

from selenium import webdriver
import logging
from selenium.webdriver.common.by import Bylogging.basicConfig(level=logging.DEBUG)
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
logging.info("Start to test!!!!!!!!!!!!!")
driver.find_element(By.ID,"kw").send_keys("python")
logging.info("Start to click!!!!!!!!!!!!!")
driver.find_element(By.ID,"su").click()
print("OKOKOKO")

我们可以通过log来分析上面的代码具体有什么操作

查找元素并sendkeys执行log

INFO:root:Start to test!!!!!!!!!!!!!

#携带参数发送请求
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element {"using": "css selector", "value": "[id=\"kw\"]"}

#返回状态码

DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element HTTP/1.1" 200 88

#响应数据

DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"element-6066-11e4-a52e-4f735466cecf":"68c631e2-3c2f-4d21-84cd-09939da46e28"}} | headers=HTTPHeaderDict({'Content-Length': '88', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})

#查找元素完成
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

#发起sendkey请求,携带查找元素时的返回数据
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element/68c631e2-3c2f-4d21-84cd-09939da46e28/value {"text": "python", "value": ["p", "y", "t", "h", "o", "n"], "id": "68c631e2-3c2f-4d21-84cd-09939da46e28"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element/68c631e2-3c2f-4d21-84cd-09939da46e28/value HTTP/1.1" 200 14

#执行sendkey动作
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})

#执行完成
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

查找元素并click执行log

INFO:root:Start to click!!!!!!!!!!!!!

DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element {"using": "css selector", "value": "[id=\"su\"]"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element HTTP/1.1" 200 88
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"element-6066-11e4-a52e-4f735466cecf":"52336fcb-f3c8-4c74-a545-2a30ebe94034"}} | headers=HTTPHeaderDict({'Content-Length': '88', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:51369/session/adb3143b146fe78c0ee16cdbded4d459/element/52336fcb-f3c8-4c74-a545-2a30ebe94034/click {"id": "52336fcb-f3c8-4c74-a545-2a30ebe94034"}
DEBUG:urllib3.connectionpool:http://localhost:51369 "POST /session/adb3143b146fe78c0ee16cdbded4d459/element/52336fcb-f3c8-4c74-a545-2a30ebe94034/click HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'Content-Length': '14', 'Content-Type': 'application/json; charset=utf-8', 'cache-control': 'no-cache'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

OKOKOKO

相关内容

热门资讯

首次获奖!官方:28岁法国前锋... 北京时间9月23日凌晨,2025年金球奖颁奖典礼进行,28岁的法国前锋登贝莱荣膺金球奖,生涯首次获奖...
除非进行交易 否则火箭无法签约... 北京时间2025年9月23日,薪资专家鲍比-马克斯分析了火箭目前的薪资状况。 早些时候,范弗利特遭遇...
中央气象台:台风“桦加沙”逐步... 本文转自【中央气象台】; “桦加沙”逐步逼近 预计明天将于广东沿海登陆 今年第18号台风“桦加沙”(...
老人称在亡妻遗物中发现存折,起... 妻子去世后,七旬老人崔某称在遗物中发现了一个存折,并以此向法院提起诉讼,要求中国某有限公司长春朝阳支...
FBI警告假冒网络犯罪举报网站... 2025-09-23 01:40:57 作者:狼叫兽 9月22日获悉,美国联邦调查局于9月19日...
每日互动:数据安全相关法律法规... 有投资者在深交所互动平台向每日互动提问:"董秘您好,随着数据安全法律法规日趋严格,这对公司的数据源合...
原创 福... 在现代海军发展的舞台上,中国的福建舰无疑是成为了一个耀眼的明星。就在9月22日,这艘首艘电磁弹射型航...
住建部原副部长:探索公务人员与... 近日,《国家治理》杂志2025年第17期刊发了住房和城乡建设部原副部长仇保兴的署名文章《稳步提升新型...