>>> from env_helper import info; info()
页面更新时间: 2024-01-14 09:31:07
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

4.6. selenium 模块控制浏览器

selenium 模块让Python直接控制浏览器, 实际点击链接,填写登录信息,几乎就像是 有一个人类用户在与页面交互。与 RequestsBeautiful Soup 相比, Selenium 允许你用高级得多的方式与网页交互。 但因为它启动了Web浏览器,假如你只是想从网络 上下载一些文件,会有点慢,并且难以在后台运行。

附录 A 有安装第三方模块的详细步骤。

4.6.1. 启动 selenium 控制的浏览器

对于这些例子,你需要FireFox浏览器。它将成为 你控制的浏览器。如果你还没有FireFox,可以从 http://getfirefox.com/ 免费下载它。

导入 selenium 的模块需要一点技巧。不是 import selenium ,而是要运行 from selenium import webdriver (为什么 selenium 模块要使用这种方式设置? 答案超出了本书的范围)。之后,你可以用 selenium 启动 FireFox 浏览器。 在交互式环境中输入以下代码:

>>> from selenium.webdriver.chrome.options import Options
>>>
>>>
>>> from selenium import webdriver
>>> # browser = webdriver.Firefox()
>>> # type(browser)
>>>
>>>
>>> #第一步输入这个:去除开头警告
>>> # warnings.simplefilter('ignore',ResourceWarning)
>>>
>>>
>>> #控制台打印
>>> print("开始执行你的测试用例!")
>>>
>>>
>>> #第二个输入这个:隐藏式启动谷歌浏览器执行UI测试用例
>>> chrome_options = Options()
>>> chrome_options.add_argument('--headless')
>>> browser  = webdriver.Chrome(options=chrome_options)
>>>
开始执行你的测试用例!
>>> browser.get('http://inventwithpython.com')

你会注意到,当 webdriver.Firefox() 被调用时, FireFox浏览器启动了。对值 webdriver.Firefox() 调用 type() ,揭示它具有 WebDriver 数据类型。 调用 browser.get('http://inventwithpython.com') 将浏览器指向 http://inventwithpython.com/

4.6.2. 在页面中寻找元素

WebDriver 对象有好几种方法,用于在页面中寻找元素。 它们被分成 find_element_*find_elements_*方法。 find_element_* 方法返回-个 WebElement_* 对象, 代表页面中匹配查询的第一个元素。find_elements_* 方法 返回 WebElement_* 对象的列表,包含页面中所有匹配的元素。

表11-3展示了 find_element_*find_elements_*方法的 几个例子,它们在变量 browser 中保存的 WebDriver 对象上调用。

seleniumWebDriver 方法,用于寻找元素

方法名 | 返回的WebElement对象/列表
-------------------------|---------------------------
browser.find_element_by_class_name(name) | 使用CSS类name的元素
browser.find_elements_by_class_name(name) | 使用CSS类name的元素
browser.find_element_by_css_selector(selector)| 匹配CSSre/ertor的元素
browser.find_elements_by_css_selector(selector) | 匹配CSSre/ertor的元素
browser.find_element_by_id(id) | 使用CSS类name的元素
browser.find_elements_by_id(id) |  使用CSS类name的元素
browser.flnd_element_by_link_text(text)| 完全匹配提供的text的``<a>``元素
browser.find_elements_by_link_text(text) | 完全匹配提供的text的``<a>``元素
browser.find_element_by_partial_link_text(text) | 包含提供的text的``<a>``元素
browser.find_elements_by_partial_link_text(text) | 包含提供的text的``<a>``元素
browser.find_element_by_name(name) | 匹配name属性值的兀素
browser.find_elements_by_name(name) | 匹配name属性值的兀素
browser.find_element_by_tag_name(name) | 匹配标签name的元素
browser.find_elements_by_tag_name(name) | (大小写无关,``<a>``元素匹配W和’A’)

除了 *_ by_tag_name() 方法,所有方法的参数都是 区分大小写的。如果页面上没有元素匹配该方法要查找的元素, selenium 模块就会抛出 NoSuchElement 异常。 如果你不希望这个异常让程序崩溃,就在代码中添加 tryexcept 语句。

一旦有了WebElement 对象,就可以读取表11-4中的属性, 或调用其中的方法,了解它的更多功能。

表11-4 WebElement的属性和方法

属性或方法 | 描述
----------------|------------------------
tag_name  |  标签名,例如'a'表示``<a>``元素 该元素name属性的值
get_attribute(name)  |  该元素内的文本,例如``<span>hello</span>``中的'hello'
clear()  |  对于文本字段或文本区域元素,清除其中输入的文本
is_displayed()   |  如果该元素可见,返回True,否则返回False
is_enabled()   |  对于输入元素,如果该元素启用,返回True,否则返回False
is_selected ()  |  对于复选框或单选框元素,如果该元素被选中,选择True,否则返回False
location  |  一个字典,包含键Y和y,表示该元素在页面上的位置

例如,打开一个新的文件编辑器,输入以下程序:

>>> from selenium import webdriver
>>> browser = webdriver.Firefox()
>>> browser.get('http://inventwithpython.com')
>>> try:
>>>     elem = browser.find_element_by_class_name('bookcover')
>>>     print('Found <%s> element with that class name!' % (elem.tag_name))
>>> except:
>>>     print('Was not able to find an element with that name.')
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

Cell In [4], line 1
----> 1 from selenium import webdriver
      2 browser = webdriver.Firefox()
      3 browser.get('http://inventwithpython.com')


ModuleNotFoundError: No module named 'selenium'

这里我们打开FireFox,让它指向一个URL。在这个页面上, 我们试图找到带有类名 'bookcover' 的元素。如果 找到这样的元素,我们就用 tag_name 属性将它的标 签名打印出来。如果没有找到这样的元素,就打印不同的信息。

这个程序的输出如下:

>>> Found <img> element with that class name!
  Cell In [5], line 1
    Found <img> element with that class name!
                        ^
SyntaxError: invalid syntax

我们发现了一个元素带有类名 'bookcover' , 它的标签名是'img'

4.6.3. 点击页面

find_element_*find_ elements_* 方法返回的 WebElement 对象有一个 click()方法,模拟鼠标在 该元 i 上点击。这个方法可以用于链接跳转,选择单 选按钮,点击提交按钮,或者触发该元素被鼠标点击时发生 的任何事情。例如,在交互式环境中输入以下代码:

>>> from selenium import webdriver
>>> browser = webdriver.Firefox()
>>> browser.get('http://inventwithpython.com')
>>> linkElem = browser.find_element_by_link_text('Read It Online')
>>> type(linkElem)
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

Cell In [6], line 1
----> 1 from selenium import webdriver
      2 browser = webdriver.Firefox()
      3 browser.get('http://inventwithpython.com')


ModuleNotFoundError: No module named 'selenium'
>>> linkElem.click()     # follows the "Read It Online" link
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

Cell In [7], line 1
----> 1 linkElem.click()     # follows the "Read It Online" link


NameError: name 'linkElem' is not defined

这段程序打开FireFox,指向 http://inventwithpython.com/, 取得<a>元素的WebElement 对象,它的文本是 “Read It Online”,然后模拟点击这个元素。 就像你自己点击这个链接一样,浏览器将跳转到这个链接。

4.6.4. 填写并提交表单

向Web页面的文本字段发送击键,只要找到那个文本字段的 <input><textarea>元素,然后调用 send_key()方法。例如,在交互式环境中输入以下代码:

>>> from selenium import webdriver
>>> browser = webdriver.Firefox()
>>> browser.get('http://gmail.com')
>>> emailElem = browser.find_element_by_id('Email')
>>> emailElem.send_keys('not_my_real_email@gmail.com')
>>> passwordElem = browser.find_element_by_id('Passwd')
>>> passwordElem.send_keys('12345')
>>> passwordElem.submit()
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

Cell In [8], line 1
----> 1 from selenium import webdriver
      2 browser = webdriver.Firefox()
      3 browser.get('http://gmail.com')


ModuleNotFoundError: No module named 'selenium'

只要 Gmail 没有在本书出版后改变Username和 Password文本字段的 id ,上面的代码就会用 提供的文本填写这些文本字段(你总是可以用浏览器 的开发者工具验证 id )。在任何元素上调用 submit() 方法,都等同于点击该元素所在表单 的 Submit 按钮(你可以很容易地调用 emailElem.submit(),代码所做的事情一样)。

4.6.5. 发送特殊键

selenium 有一个模块,针对不能用字符串值 输入的键盘击键。它的功能非常类似于转义字符。 这些值保存在 selenium.webdriverxommon.keys 模块的 属性中。由于这个模块名非常长,所以在程序顶部运行 from selenium.webdriver.common.keys import Keys 就比较容易。如果这么做,原来需要写 from selenium.webdriver.common.keys 的 地方,就只要写 Keys 。表11-5列出了 常用的 Keys 变量。

表 11 -5 selenium.webdriver.common.keys 模块 中常用的变量

属性 | 含义
---------|---------
Keys.DOWN, Keys.UP, Keys.LEFT,Keys.RIGHT | 键盘箭头键
Keys.ENTER, Keys.RETURN | 回车和换行键
Keys.HOME, Keys.END,Keys.PAGE_DOWN,Keys.PAGE_UP | Home 键、End 键、PageUp 键和Page Down 键
Keys.ESCAPE, Keys.BACK_SPACE,Keys.DELETE | Esc、Backspace和字母键
Keys.F1, Keys.F2, . . . , Keys.F12 | 键盘顶部的F1 到F12 键
Keys.TAB | Tab 键

例如,如果光标当前不在文本字段中,按下 homeend 键,将使浏览器滚动到页面的顶部或底部。 在交互式环境中输入以下代码,注意 seml_keys() 调用是如何滚动页面的:

>>> from selenium import webdriver
>>> from selenium.webdriver.common.keys import Keys
>>> browser = webdriver.Firefox()
>>> browser.get('http://nostarch.com')
>>> htmlElem = browser.find_element_by_tag_name('html')
>>> htmlElem.send_keys(Keys.END)  # scrolls to bottom
>>> htmlElem.send_keys(Keys.HOME)  # scrolls to top
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

Cell In [9], line 1
----> 1 from selenium import webdriver
      2 from selenium.webdriver.common.keys import Keys
      3 browser = webdriver.Firefox()


ModuleNotFoundError: No module named 'selenium'

<html> 标签是HTML文件中的基本标签: HTML文件的完整内容包含在<html></html> 标签之内。调用 browser.find_element_by_tag_name('html') 是像一般Web页面发送按键的好地方。当你滚动 到该页的底部,新的内容就会加载,这可能会有用。

4.6.6. 点击浏览器按钮

利用以下的方法,selenium 也可以模拟点击各种浏览器按钮:

browser.back()点击“返回”按钮。

browser.forward() 点击“前进”按钮。

browser.refresh() 点击“刷新”按钮。

browser.quit() 点击“关闭窗口”按钮。

4.6.7. 关于 selenium 的更多信息

selenium 能做的事远远超出了这里描述的功能。 它可以修改浏览器的 cookie ,截取页面快照, 运行定制的JavaScript。要了解这些功能的更多信息, 请参考文档: http://selenium-python.readthedocs.org/