>>> 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直接控制浏览器,
实际点击链接,填写登录信息,几乎就像是 有一个人类用户在与页面交互。与
Requests
和 Beautiful 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
对象上调用。
表 selenium
的 WebDriver
方法,用于寻找元素
方法名 | 返回的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
异常。
如果你不希望这个异常让程序崩溃,就在代码中添加 try
和 except
语句。
一旦有了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 键
例如,如果光标当前不在文本字段中,按下 home
和 end
键,将使浏览器滚动到页面的顶部或底部。 在交互式环境中输入以下代码,注意
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/。