Python + Selenium(二十七)WebDriver 原理

如果要精通一门工具,一定要了解其原理。

在早期的 Selenium RC 加载浏览器后,它将JavaScript代码注入浏览器,通过 JavaScript 代码在浏览器中驱动自动化运行。

Selenium WebDriver 使用每个浏览器的内置的自动化支持来直接驱动浏览器。这些自动化的支持来源于浏览器厂商,更原生更稳定。

这些对浏览器的驱动来源于浏览器厂商遵循 WebDriver 中的 WP(WebDriver wire protocol)协议。通过 WebDriver 实现对遵循 WP 协议的浏览器驱动的远程调用。

形象的来说,也就是浏览器的驱动是一个服务(接口服务),通过 HTTP 协议可访问这些接口。访问不同的接口可以实现不同的功能。

在这个过程中,Python 解释器就相当于客户端,WebDriver 会先将你写的操作代码(如 find_element, click等)封装成 HTTP 请求发送给浏览器驱动生成的远程服务,再由浏览器驱动将请求内容转化为浏览器内置的自动化命令来具体对浏览器实现操作。

我们可以打开 DEBUG 日志,查看每句代码做了什么。

打开你的 IDLE,输入以下代码用以开启 DEBUG 日志信息:

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)

然后再输入:

>>> from selenium import webdriver
>>> driver = webdriver.Chrome()
>>> driver.get('http://baidu.com')
>>> driver.find_element_by_id('kw').send_keys('测试')

是不是每句代码下面都会显示很多日志信息,我们先看webdriver.Chrome()这一句做了什么:

>>> driver = webdriver.Chrome()
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:6591/session {"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "platformName": "any", "goog:chromeOptions": {"extensions": [], "args": []}}}, "desiredCapabilities": {"browserName": "chrome", "version": "", "platform": "ANY", "goog:chromeOptions": {"extensions": [], "args": []}}}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 127.0.0.1:6591
DEBUG:urllib3.connectionpool:http://127.0.0.1:6591 "POST /session HTTP/1.1" 200 680
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

向远程服务器 http://127.0.0.1:6591/session(其实就是浏览器驱动监听的端口)发起了一个创建会话的请求,后面大括号中的内容是一系列配置信息。
通过 urllib3 请求库,建立了一个 HTTP 连接。

再看看第二句 get() 方法又干了什么:

>>> driver.get('http://baidu.com')
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:6591/session/7abcfa599b992583320cb5aa98dd31aa/url {"url": "http://baidu.com"}
DEBUG:urllib3.connectionpool:http://127.0.0.1:6591"POST /session/7abcfa599b992583320cb5aa98dd31aa/url HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

通过 urllib3 请求库发起了一个 POST 请求,请求接口为 /session/bd1b818ff33e54bba080e2424705f7fd/url ,接口信息中包含了前面创建的会话信息。
/url 接口告诉浏览器需要访问一个 url 地址。

接下来看看我们最常见的find_element()

>>> driver.find_element_by_id('kw').send_keys('测试')
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:6591/session/7abcfa599b992583320cb5aa98dd31aa/element {"using": "css selector", "value": "[id=\"kw\"]"}
DEBUG:urllib3.connectionpool:http://127.0.0.1:6591 "POST /session/7abcfa599b992583320cb5aa98dd31aa/element HTTP/1.1" 200 88
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:6591/session/7abcfa599b992583320cb5aa98dd31aa/element/f076eafe-f301-4790-bc0a-a0c38503d770/value {"text": "\u6d4b\u8bd5", "value": ["\u6d4b", "\u8bd5"], "id": "f076eafe-f301-4790-bc0a-a0c38503d770"}
DEBUG:urllib3.connectionpool:http://127.0.0.1:6591 "POST /session/7abcfa599b992583320cb5aa98dd31aa/element/f076eafe-f301-4790-bc0a-a0c38503d770/value HTTP/1.1" 200 14
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

这一句,我们先 find_element(),再 send_keys() ,所以实际上是发送了两个请求:
第一个请求是查找元素:

  • POST /element {“using”: “css selector”, “value”: “[id=“kw”]”} 向 /element 接口发送了一个请求,通过 json 格式的数据告诉浏览器,使用的定位方式是css selector,定位的值是[id=\"kw\"]

第二个请求是发送文本:

  • POST /element/f076…770/value {“text”: “\u6d4b\u8bd5”, “value”: ["\u6d4b", “\u8bd5”], “id”: “f076…d770”} 同样以 json 格式的数据向找到的元素的value接口发送两个 Unicode 字符。

你甚至可以通过 Postman 来模拟这些元素操作过程:

如果你有耐心,可以遵照 WP 协议自己写一套工具😀。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值