Selenium 入门(基于 Python)

自从转岗以来,我充分接触 Selenium 已经有一年了。在此期间,主管一直想让我出一些关于自动化测试的教育训练,但是由于工作太忙,加上一开始是要从 Python 开始做的,所以我找资料找了很久,都没有什么头绪。

最近,主管又催我做一套自动化测试的 PPT,于是我花了两天的时间,把 Selenium 最基础的东西做成了 PPT。但是主管和其他同事看了一下,觉得 PPT 介绍得太详细,已经不需要我去讲了,所以最后也没有让我讲它。

总之,我现在把它放出来,加上我的讲稿(虽然是我后来写的)。之后的内容在做了,不过也不知道什么时候做好——也许永远也做不好,也许明天就能做好。

在开始之前,我假定你们了解 Python 和 HTML、CSS、JS 的基础知识。

介绍

Selenium 是一款 Web 自动化框架,它适用于多种语言,包括 Python。

它并非直接控制浏览器,而是通过操作浏览器驱动(由浏览器厂家提供),实现对浏览器的操作。

除了 Web 自动化测试之外,它也可用于自动化和爬虫——我大三的时候爬 QQ 空间的数据,模拟登录就用了 Selenium。

Selenium 的替代产品也有一些,最近比较有名的是微软出品的 Playwright,也支持 Python 在内的很多语言。我研究过这个工具,虽然它对元素的自动等待比较好,不过它在处理提示框上面不尽人意,而且它也不支持元素的嵌套。对于 Playwright,中文的资料不多,我可能会在以后出一期关于它的介绍。总之,这次还是讲 Selenium 的。

安装

Python 中,Selenium 的安装方式和其他模块一样,用 pip 安装:

pip install selenium

然后,根据自己使用的浏览器和版本下载浏览器驱动。

将下载的浏览器驱动的可执行文件放到 Path 下。注意,不要放在网络文件夹下,一些驱动无法在网络文件夹下使用。如果你不知道什么是 Path,看一下下面的介绍。

关于 Path

简单来说,在终端执行命令时,如果不指定路径,系统会在系统环境变量中的 Path 里面的路径中找命令所属的可执行文件。

在 Windows 中,可以在“设置 - 系统 - 关于 - 高级系统设置 - 环境变量”中更改环境变量。

如果因为管理员权限,无法通过上述方式更改环境变量,可在 PowerShell 中执行下面的命令:

  1. $env:Path 返回目前的环境变量,复制下来;
  2. 在复制的环境变量中(一般为末尾)添加新的路径,参照已有环境变量写,末尾有英文分号;
  3. 重新写入环境变量:[environment]::SetEnvironmentvariable("Path", "新的环境变量字符串", "User")

讲解

接下来我们用一个示例来学习 Selenium 的基础知识。虽然很简单,但也覆盖了绝大部分内容。

示例

import time

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')
driver.find_element(By.ID, 'kw').send_keys('Selenium')
driver.find_element(By.ID, 'su').click()
time.sleep(1)
print(driver.title)
results = driver.find_elements(By.XPATH, '//div[@id="content_left"]/div[not(@tpl="recommend_list")]//h3')
title_list = [result.text for result in results]
for index, title in enumerate(title_list):
    print(index, title)

driver.close()
driver.quit()

以下是该代码的执行效果:

执行效果

实际上就是在百度中搜索“Selenium”,再打印出第一页的标题和搜索结果标题。

接下来,我们看一下它是怎么运行的吧。

创建 WebDriver 实例

代码的第 3 行和第 6 行:

from selenium import webdriver
...
driver = webdriver.Chrome()

第6行创建了一个基于 Chrome 的 WebDriver 实例。接下来的所有操作在该实例上进行。

如果要用其他的浏览器,把 Chrome 换成别的浏览器名称,如 Firefox。具体的可以看源码。

访问网页

代码第 8 行:

driver.get('https://www.baidu.com/')

访问给定的网页。给定的 URL 需要写明协议(就是上例中的 https://),否则会报错。

寻找单个元素

代码第 4 行和第 9 行:

from selenium.webdriver.common.by import By
...
driver.find_element(By.ID, 'kw').send_keys('Selenium')

要想对网页上的元素进行操作,首先要寻找网页中的元素。Selenium 中寻找元素的最基础的方法,是对 WebDriver 实例调用 find_element() 方法。

该方法需要两个参数:

  1. 定位方式
  2. 查找文本

如果查询到元素,会返回一个 WebElement 实例,表示符合查询条件的第一个元素。如果查不到,会抛出 NoSuchElementException 异常。

对于 WebElement 实例,我们可以继续调用该方法,以查找隶属于该元素的元素。

定位方式

Selenium 提供 8 种定位方式:

  • 使用元素 ID 定位
  • 使用 XPath 定位
  • 使用链接文本定位
  • 使用链接文本的一部分定位
  • 使用元素的 name 属性定位
  • 使用元素的标签名定位
  • 使用元素 class 定位
  • 使用 CSS 选择器定位

传入 find_element() 方法的第一个参数决定定位方式,为字符串。不过通常情况下,我们会导入 Selenium 提供的定位方式包(见代码第 4 行),从中调用值。

每一个定位方式都有对应的别名方法,也就是定义了名称不同的方法,实质仍然是调用之前提到的的方法。这些别名方法的名称其实就是在原方法的名称后面加上 _by_...,调用它们只需要传入查找文本就行了。比如:

driver.find_element(By.ID, 'kw')
driver.find_element_by_id('kw')

上面两行代码等价。

所有定位方式的值和别名方法见下表:

定位方式 字面量 含义 对应别名方法
By.ID 'id' 使用元素 ID 定位,默认值 find_element_by_id()
By.XPATH 'xpath' 使用 XPath 定位 find_element_by_xpath()
By.LINK_TEXT 'link text' 使用链接文本定位 find_element_by_link_text()
By.PARTIAL_LINK_TEXT 'partial link text' 使用链接文本的一部分定位 find_element_by_partial_link_text()
By.NAME 'name' 使用元素的 name 属性定位 find_element_by_name()
By.TAG_NAME 'tag name' 使用元素的标签名定位 find_element_by_tag_name()
By.CLASS_NAME 'class name' 使用元素 class 定位 find_element_by_class()
By.CSS_SELECTOR css selector 使用 CSS 选择器定位 find_element_by_css_selector

上述定位方式中,我们要重点关注 XPath 和 CSS 选择器定位,这两种定位方式能够实现的功能非常强大,而且很常用。关于这两个选择器,我之后应该会出一期专门讲。

查看页面元素定位

通过浏览器的开发人员工具,能够方便地查看页面上的元素定位。

调用开发人员工具,一般按 F12 即可。

我们以 Chrome 的开发人员工具为例:

按工具窗口左上角的按钮(或按 Ctrl + Shift + C),在页面上选取元素,能够查看元素在源代码中的位置,以及元素的参数等信息,方便定位。

选取元素

在 Elements(元素)选项卡中,按 Ctrl + F 调出查询栏,输入文本、XPath、CSS 选择器文本,可以查询对应的元素。

查询对应的元素

切换到 Console(控制台),输入 $x('XPath 文本')$$('CSS 选择器文本'),回车,可以返回对应的元素。有时候,输入完毕,也可以先不用回车,根据是否能看到结果来初步判断文本是否正确。

在控制台返回对应的元素

右键点击元素,选择 Copy,可复制元素的信息,包括 XPath 和 CSS 选择器文本。不过,考虑到层级关系可能会变化,这种方式得到的查找文本仅供临时使用,不推荐将此作为主要的获取选择器文本的方式。

复制元素的信息

元素的方法

获取元素后,可以对元素进行操作。

WebElement 类的常用方法如下:

  • click():单击
  • clear():清除文本框的内容
  • get_attribute(name):返回元素参数(HTML 方面的)
  • get_property(name):返回元素属性(JS 方面的)
  • is_selected():是否选择(对于单选框或复选框)
  • is_enabled():是否启用
  • send_keys(*keys):输入文本或按键
  • is_displayed():是否显示
  • screenshot(filename):输出屏幕截图(PNG)到给定文件。错误返回 False,成功返回 True
  • value_of_css_property(property_name):返回元素的给定 CSS 属性值

由此可以得出,代码第 9、10 行

driver.find_element(By.ID, 'kw').send_keys('Selenium')
driver.find_element(By.ID, 'su').click()

的含义为:

  1. 找到 ID 为 kw 的元素,输入 Selenium
  2. 找到 ID 为 su 的元素,单击

等待

由于网页的元素加载有一定的时间需求,一些元素可能在请求完毕后不会立即显示,而是要一段时间后显示。如果贸然查找或操作还没有加载完毕的元素,会报错。因此,等待在 Web 自动化测试中非常重要。

最简单的方法是硬等待,使用 time.sleep() 方法。如代码第 11 行:

time.sleep(1)

就是等待 1 秒。

此外,Selenium 也提供隐式等待和显式等待等方法,不过比较复杂,如果有时间的话,我以后会出一期讲这个。

驱动的属性

WebDriverWebElement 类有一些属性可以使用。WebDriver 类常用的属性有下面几个:

  • title:标题
  • current_url:当前 URL
  • page_source:页面源码

所以代码第 12 行:

print(driver.title)

就是打印出页面的标题。

寻找多个元素

除了寻找一个元素外,Selenium 也可以同时寻找所有符合条件的元素。

对应的方法,只是名称中把 element 改成了 elements,包括那些别名方法。比如:

driver.find_element(By.ID, 'kw')
driver.find_element_by_id('kw')

>>>

driver.find_elements(By.ID, 'kw')
driver.find_elements_by_id('kw')

有人可能觉得:一个页面中就只有一个 ID,不会有多个元素吧。实际上,ID 说是只能有一个,但是如果你给多个元素赋同样的ID,页面还是能显示的,就是会在控制台有警告。当然,如果 CSS 和 JS 中涉及到这个 ID,那么会出现一些异常。

寻找多个元素的方法,返回一个列表,列表各项为 WebElement 实例,表示每一个符合条件的元素。如果没找到元素,则不会报错,返回空列表。

所以代码第 13 行:

results = driver.find_elements(By.XPATH, '//div[@id="content_left"]/div[not(@tpl="recommend_list")]//h3')

就是查找页面所有符合所给的 XPath 的元素,存到 results 中。

元素的属性

WebElement 类常用的属性有下面几个:

  • tag_name:标签名
  • text:文本信息(不包括输入框里面的值,对于这种值,请使用 get_property('value') 获取)
  • size:尺寸(返回字典 {'height': H, 'width', W}
  • location:坐标(返回字典 {'x': X, 'y', Y}
  • screenshot_as_base64:截图,返回 Base64 数据
  • screenshot_as_png:截图,返回 PNG 二进制数据

所以代码第 14 ~ 16 行:

title_list = [result.text for result in results]
for index, title in enumerate(title_list):
    print(index, title)

表示:

  1. 遍历 results,取其中各元素的文本,返回一个列表;
  2. 打印列表各项的序号和值

关闭浏览器

所有操作完成之后,记得关闭浏览器驱动。

代码最后两行:

driver.close()
driver.quit()

分别表示:

  1. 关闭页面
  2. 退出浏览器驱动

课件

本文课件地址:https://static.a4ding.com/doc/auto_test/0001_selenium_python_basic.pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342