Selenium3 Python WebDriver API源码探析(20)WebDriver协议概述

WebDriver协议

早期SeleniumWebDriver是两个独立的项目,Selenium早期主要依靠将操作转换为JavaScript然后注入浏览器实现浏览器的自动化,WebDriver将浏览器原生API封装成一套更加面向对象的API,但是由于不同浏览器内核的差异,因此为了适配,必须对不同浏览器实现不同的API。在Selenium2之后两个项目合并,我们常说的Selenium其实主要指的就是WebDriver API。当前Selenium稳定版本的主版本为3,beta版本的Selenium4已经在路上。

Selenium或者WebDriver与浏览器交互的基础是WebDriver协议(W3C推荐标准)。WebDriver协议是一个与操作系统、编程语言无关的通过HTTP协议使用JSON作为传输格式的RESTful Web服务。

WebDriver协议目前有两个版本:

WebDriver协议之前还有一个废弃的JsonWireProtocol协议,具体见https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol

WebDriver协议模型中牵扯三个对象:

  • 客户端(Client或local end):可以简单认为就是调用WebDriver API的程序或机器。我们常用的Python WebDriver API就是客户端的一个Python语言绑定。
  • 服务端(Server或remote end):运行RemoteWebDriver的机器,或者支持WebDriver协议的浏览器,比如支持geckodriver的Firefox浏览器、支持chromedriver的Chrome浏览器。WebDriver协议其实只定义了服务端的行为。
  • WebDriver:即各种浏览器的WebDriver协议实现,比如geckodriverchromedriverWebDriver则相当于客户端和服务端的中介,提供WebDriver协议RESTful 服务。客户端通过WebDriver操控服务端(浏览器)。比如Firefox依靠webdriver.xpi扩展来控制浏览器。

客户端运行后,启动1个会话(session),客户端在该会话中通过WebDriver协议 RESTful 服务端点(endpoint,可简单理解为url)向服务端请求,服务器端接受请求后向客户端返回响应。
!在这里插入图片描述

WebDriver协议将端点映射为命令(command)。端点与命令的关系如下(https://www.w3.org/TR/webdriver/#endpoints):

MethodURI TemplateCommand
POST/sessionNew Session
DELETE/session/{session id}Delete Session
GET/statusStatus
GET/session/{session id}/timeoutsGet Timeouts
POST/session/{session id}/timeoutsSet Timeouts
POST/session/{session id}/urlNavigate To
GET/session/{session id}/urlGet Current URL
POST/session/{session id}/backBack
POST/session/{session id}/forwardForward
POST/session/{session id}/refreshRefresh
GET/session/{session id}/titleGet Title
GET/session/{session id}/windowGet Window Handle
DELETE/session/{session id}/windowClose Window
POST/session/{session id}/windowSwitch To Window
GET/session/{session id}/window/handlesGet Window Handles
POST/session/{session id}/window/newNew Window
POST/session/{session id}/frameSwitch To Frame
POST/session/{session id}/frame/parentSwitch To Parent Frame
GET/session/{session id}/window/rectGet Window Rect
POST/session/{session id}/window/rectSet Window Rect
POST/session/{session id}/window/maximizeMaximize Window
POST/session/{session id}/window/minimizeMinimize Window
POST/session/{session id}/window/fullscreenFullscreen Window
GET/session/{session id}/element/activeGet Active Element
POST/session/{session id}/elementFind Element
POST/session/{session id}/elementsFind Elements
POST/session/{session id}/element/{element id}/elementFind Element From Element
POST/session/{session id}/element/{element id}/elementsFind Elements From Element
GET/session/{session id}/element/{element id}/selectedIs Element Selected
GET/session/{session id}/element/{element id}/attribute/{name}Get Element Attribute
GET/session/{session id}/element/{element id}/property/{name}Get Element Property
GET/session/{session id}/element/{element id}/css/{property name}Get Element CSS Value
GET/session/{session id}/element/{element id}/textGet Element Text
GET/session/{session id}/element/{element id}/nameGet Element Tag Name
GET/session/{session id}/element/{element id}/rectGet Element Rect
GET/session/{session id}/element/{element id}/enabledIs Element Enabled
GET/session/{session id}/element/{element id}/computedroleGet Computed Role
GET/session/{session id}/element/{element id}/computedlabelGet Computed Label
POST/session/{session id}/element/{element id}/clickElement Click
POST/session/{session id}/element/{element id}/clearElement Clear
POST/session/{session id}/element/{element id}/valueElement Send Keys
GET/session/{session id}/sourceGet Page Source
POST/session/{session id}/execute/syncExecute Script
POST/session/{session id}/execute/asyncExecute Async Script
GET/session/{session id}/cookieGet All Cookies
GET/session/{session id}/cookie/{name}Get Named Cookie
POST/session/{session id}/cookieAdd Cookie
DELETE/session/{session id}/cookie/{name}Delete Cookie
DELETE/session/{session id}/cookieDelete All Cookies
POST/session/{session id}/actionsPerform Actions
DELETE/session/{session id}/actionsRelease Actions
POST/session/{session id}/alert/dismissDismiss Alert
POST/session/{session id}/alert/acceptAccept Alert
GET/session/{session id}/alert/textGet Alert Text
POST/session/{session id}/alert/textSend Alert Text
GET/session/{session id}/screenshotTake Screenshot
GET/session/{session id}/element/{element id}/screenshotTake Element Screenshot
POST/session/{session id}/printPrint Page

WebDriver Python API执行流程(反推)

WebDriver客户端API其实就是实现属性或方法到命令,再到WebDriver协议端点的变换过程。

例如:WebDriver类的current_url特性

  1. current_url特性其实是命令Command.GET_CURRENT_URL的执行结果。

    @property
    def current_url(self):
         return self.execute(Command.GET_CURRENT_URL)['value']
    
  2. WebDriver类的execute方法通过command_executor.execute(driver_command, params)执行命令。
    command_executor是一个字符串(服务器url)或者remote_connection.RemoteConnection对象。

  3. remote_connection.RemoteConnection类位于selenium\webdriver\remote\remote_connection.py
    remote_connection.RemoteConnection类的_commands属性定义了命令和端点之间的关系。
    Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url')
    remote_connection.RemoteConnection类的execute方法控制服务端执行命令。

  4. WebDriver类在实例化时会传入command_executor参数,command_executor参数即服务端地址。

WebDriver Python API执行流程(正推)

from selenium import webdriver

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
# 服务端地址
url = driver.command_executor._url  
print(url)

上述代码的执行流程大致如下:

  1. driver = webdriver.Firefox()即对selenium\webdriver\firefox\webdriver.py中的WebDriver类实例化,WebDriver类继承自selenium\webdriver\remote\webdriver.py中的WebDriver类。WebDriver类构造方法中command_executor参数即服务端地址。
    此时WebDriver启动浏览器,加载webdriver.xpi扩展,监听基于WebDriver协议的请求。
    在日志文件geckodriver.log中可以看到类似1116855012551 geckodriver INFO Listening on 127.0.0.1:54499的记录。

  2. driver.get("http://www.baidu.com")相当于执行Command.GET命令。 WebDriver对象依靠remote_connection.RemoteConnection对象command_executor执行命令。 remote_connection.RemoteConnection类中实现了命令到WebDriver协议的映射Command.GET: ('POST', '/session/$sessionId/url')。执行命令相当于向浏览器发送对应请求。WebDriver将请求发送给浏览器。

     def get(self, url):
         self.execute(Command.GET, {'url': url})
    
  3. 浏览器在接受请求后执行操作(打开百度页面)并返回响应(服务端地址)。WebDriver将响应结果传递给代码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值