Selenium (软件):修订间差异

无编辑摘要
 
(未显示同一用户的16个中间版本)
第12行: 第12行:
Grid:
Grid:


===安装===
===安装 Selenium===
====安装 Selenium====
使用不同的语言,安装Selenium方式不同。
使用不同的语言,安装Selenium方式不同。


第25行: 第24行:
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/selenium_installation/installing_selenium_libraries/ Selenium 文档:安装 Selenium 库]}}
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/selenium_installation/installing_selenium_libraries/ Selenium 文档:安装 Selenium 库]}}


====安装浏览器和浏览器驱动====
===安装浏览器和浏览器驱动===
{| class="wikitable"  
{| class="wikitable"  
|-
|-
第43行: 第42行:
| Windows/macOS/Linux
| Windows/macOS/Linux
| Mozilla
| Mozilla
|  
| geckodriver
| 下载
| [https://github.com/mozilla/geckodriver/releases 下载]
|-
|-
| Edge
| Edge
| Windows 10
| Windows 10
| 微软
| 微软
|  
| msedgedriver
| 下载
| [https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ 下载]
|-
|-
| Internet Explorer
| Internet Explorer
第90行: 第89行:
</syntaxhighlight>
</syntaxhighlight>


验证是否成功,以[[Python]]语言示例:
在命令行输入驱动名,验证是否添加成功。
<syntaxhighlight lang="bash" >
chromedriver  # chrome
geckodriver  # firefox
</syntaxhighlight>
 
===检测安装成功===
以Python语言示例:
<syntaxhighlight lang="python" >
from selenium import webdriver
 
driver = webdriver.Firefox()
driver.get('https://www.baidu.com')
</syntaxhighlight>
 
如果不将驱动加入环境变量,需要在每次使用时,指定驱动路径。以Python使用为例:
<syntaxhighlight lang="python" >
# executable_path 在selenium 4 已弃用
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
 
s = Service(r'D:\geckodriver-v0.31.0-win6\geckodriver.exe')
driver = webdriver.Firefox(service=s)
driver.get('https://www.baidu.com')
</syntaxhighlight>
 
常见错误:
加入环境变量后,在代码中还是显示找不到
重启编辑器即可。
 
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/driver_requirements/ Selenium 文档:WebDriver > 驱动要求]}}
 
==快速入门==
===浏览器===
{| class="wikitable"
! 名称
! 描述
! 示例
|-
|Chrome
|
| <syntaxhighlight lang="python" >
from selenium import webdriver
driver = webdriver.Chrome()
</syntaxhighlight>
|-
| firefox
|
| <syntaxhighlight lang="python" >
from selenium import webdriver
driver = webdriver.Firefox()
</syntaxhighlight>
|-
|
|
|
|}
 
===无头浏览器===
以[[Python]]语言chrome示例:
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
from selenium import webdriver
from selenium import webdriver
第102行: 第160行:
driver.get("https://www.baidu.com")
driver.get("https://www.baidu.com")
print(driver.page_source)
print(driver.page_source)
client.quit()
driver.quit()
</syntaxhighlight>
 
firefox示例:
<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
 
op = Options()
op.headless = True
 
driver = webdriver.Firefox(options=op)
driver.get(url)
print(driver.title)
 
driver.close()
</syntaxhighlight>
</syntaxhighlight>
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/driver_requirements/ Selenium 文档:WebDriver > 驱动要求]}}


==操控浏览器==
===下载文件===
firefox示例:
<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
 
 
op = Options()
op.set_preference("browser.download.folderList",2)
op.set_preference("browser.download.manager.showWhenStarting", False)
op.set_preference("browser.download.dir",save_path)  # 设置下载位置
op.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream")
op.headless = True  # 设置无头模式
 
driver = webdriver.Firefox(options=op)
# 需要先在浏览器中设置该文件直接保存
driver.get(r'https://test.com/test.jpg')
driver.close()
 
</syntaxhighlight>
 
==浏览器设置==
===浏览器参数===
<syntaxhighlight lang="python">
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
 
options = Options()
options.add_argument('--headless')  # 无头模式(无界面)
options.add_argument("--incognito") # 隐私模式
driver = webdriver.Chrome(options=options)
 
driver.get("https://www.baidu.com")
print(driver.page_source)
driver.quit()
</syntaxhighlight>
 
 
一些常用参数:
{| class="wikitable"
! style="width:20%" | 参数名
! style="width:50%" | 描述
! style="width:30%" | 示例
|-
| <code>--headless</code> || 无头模式(无界面)|| <code>options.add_argument('--headless')</code>
|-
| <code>--incognito</code> || 隐私模式|| <code>options.add_argument('--incognito')</code>
|-
| <code>--window-size</code> || 浏览器窗口大小 || <code>options.add_argument('--window-size=1920,1080')</code>
|-
| <code>--user-agent</code> || 浏览器User Agent || <code>options.add_argument('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"')</code>
|-
| <code>--disable-extensions</code> || 禁用扩展程序 || <code>options.add_argument('--disable-extensions')</code>
|-
| <code>--disable-gpu</code> || 禁用GPU加速 || <code>options.add_argument('--disable-gpu')</code>
|-
| <code>--ignore-certificate-errors</code> || 忽略证书错误 || <code>options.add_argument('--ignore-certificate-errors')</code>
|-
| <code>--proxy-server</code> || 设置代理服务器 || <code><nowiki>options.add_argument('--proxy-server=http://username:password@proxyserver:port')</nowiki></code>
|}
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/browsers/chrome/ selenium 文档:browsers/chrome]
|[https://peter.sh/experiments/chromium-command-line-switches/ Peter Beverloo:List of Chromium Command Line Switches]
}}
 
==浏览器操作==
以下[[Python]]编程语言示例:
以下[[Python]]编程语言示例:
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
第152行: 第289行:
! Python示例
! Python示例
|-
|-
| 窗口句柄
| 当前窗口句柄
| 获得当前窗口的窗口句柄
| 获得当前窗口的窗口句柄,返回一个字符串
| driver.current_window_handle
| driver.current_window_handle
|-
| 所有窗口句柄
| 获得所有窗窗口的窗口句柄,返回一个列表
| driver.window_handles
|-  
|-  
| 切换窗口或标签页
| 切换窗口或标签页
|  
| WebDriver没有当前活动窗口,要使用某个窗口需要使用<code>switch_to.window('窗口句柄')</code>切换。
|  
| <syntaxhighlight lang="python" >
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://seleniumhq.github.io")
# 存储原始窗口的 ID
original_window = driver.current_window_handle
# 单击在新窗口中打开的链接
driver.find_element(By.LINK_TEXT, "new window").click()
# 等待浏览器加载完毕
driver.implicitly_wait(7)
 
# 循环执行,直到找到一个新的窗口句柄
for window_handle in driver.window_handles:
    if window_handle != original_window:
        driver.switch_to.window(window_handle)
        break
print(driver.title)
</syntaxhighlight>
|-  
|-  
| 创建新窗口或新标签页,并且切换
| 创建新窗口或新标签页,并且切换
| 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 +
| 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 +
|  
| <code>driver.switch_to.new_window('tab')</code> # 打开新标签页并切换到新标签页  <br /><code>driver.switch_to.new_window('window')</code> # 打开新标签页并切换到新标签页
|-  
|-  
| 关闭窗口或标签页
| 关闭窗口或标签页
第175行: 第333行:




{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/browser_manipulation/ Selenium 文档:WebDriver - 操控浏览器]}}
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/interactions/windows/ Selenium 文档:WebDriver - 同窗口和标签一起工作]
|[https://www.selenium.dev/documentation/zh-cn/webdriver/browser_manipulation/ Selenium 文档:WebDriver - 操控浏览器]}}
 
===使用Cookie===
[[Cookie]]是从网站发送并存储在您的计算机中的一小段数据,主要用于识别用户并加载存储的信息。


==网络元素==
{| class="wikitable"
! 名称
! 描述
! 示例
|-
| 添加Cookie <br /><code>add_cookie()</code>
| 添加Cookie,然后手动或自动刷新浏览器。  <br /><br /> <code>driver.add_cookie({"name": "key", "value": "value"})</code>  <br /><br />获取cookie可以在浏览器Web开发者工具,或使用selenium函数获取。
| <syntaxhighlight lang="python" >
cookie = {
    'version':'1.1.0',
    'username' : 'auser',
    'impress':'df88568486969',
    'fim': 'mikllf',
}
cookies  = [{'name':k, 'value':v} for k,v in cookie.items()]
for item in cookies:
    driver.add_cookie(item)
</syntaxhighlight>
|-
|
|
|
|-
|
|
|
|}
{{了解更多
|[https://www.selenium.dev/documentation/webdriver/interactions/cookies/ Selenium 文档:使用 Cookie]
}}
 
==元素==
WebElement表示DOM元素。
WebElement表示DOM元素。


第205行: 第399行:
|}
|}


WebDriver API提供了内置方法来查找基于不同属性的WebElement (例如ID, Name, Class, XPath, CSS选择器, 链接文本等)
WebDriver API提供了内置方法来查找基于不同属性的WebElement (例如ID, Name, Class, XPath, CSS选择器, 链接文本等)。以下使用查找单个元素Find Element示例,查找多个元素Find Elements同样适用。 Python版本的<code>find_element_by_* </code>系列的方法,在新版本中以弃用
 
{| class="wikitable"  style="width: 100%;
! 操作
! 描述
! Python 示例
|-
| By ID
| 通过ID查找元素。适用元素如:<code><nowiki><div id="q">...</div></nowiki></code>
| driver.find_element(By.ID, "q")
|-
| By Name
| 通过Name查找元素。适用元素如:<code><nowiki><input name="btnK">...</input></nowiki></code>
| driver.find_element(By.NAME, 'btnK')
|-
| By Class Name
| 通过Class Name查找元素。适用元素如:<code><nowiki><p class="rk">...</p></nowiki></code>
| driver.find_element(By.CLASS_NAME, 'rk')
|-
|By Tag Name
|通过标签名查找元素
| driver.find_element(By.TAG_NAME, "div")
|-
|By Link Text
|通过链接文本查找元素
|driver.find_element(By.LINK_TEXT, "更多信息...")
|-
|By Partial Link Text
|通过部分链接文本查找元素
|driver.find_element(By.PARTIAL_LINK_TEXT, "更多信")
|-
|By CSS
|通过[[CSS]]选择器查找元素
|driver.find_element(By.CSS_SELECTOR, "h1")
|-
|By XPath
| 通过[[XPath]]查找元素。
|driver.find_element(By.XPATH, "//form[1]")
|-
|}
 


===元素属性和方法===
===元素属性和方法===
第214行: 第448行:
! Python示例
! Python示例
|-
|-
|元素是否被启用或禁用
|元素是否被启用或禁用  
|Is Enabled
|is_enabled()
|此方法用于检查网页上连接的元素是否被启用或禁用. 返回一个布尔值, 如果在当前浏览上下文中启用了连接的元素, 则返回True; 否则返回false 。
|此方法用于检查网页上连接的元素是否被启用或禁用. 返回一个布尔值, 如果在当前浏览上下文中启用了连接的元素, 则返回True; 否则返回false 。
|driver.find_element(By.NAME, 'btnK').is_enabled()
|driver.find_element(By.NAME, 'btnK').is_enabled()
|-
|-
|元素是否被选中
|元素是否被选中
|Is Selected
|is_selected()
|此方法确定是否 已选择 引用的元素. 此方法广泛用于复选框, 单选按钮, 输入元素和选项元素.返回一个布尔值, 如果在当前浏览上下文中 已选择 引用的元素, 则返回 True, 否则返回 False。
|此方法确定是否 已选择 引用的元素. 此方法广泛用于复选框, 单选按钮, 输入元素和选项元素.返回一个布尔值, 如果在当前浏览上下文中 已选择 引用的元素, 则返回 True, 否则返回 False。
|driver.find_element(By.CSS_SELECTOR, "input[type='checkbox']:first-of-type").is_selected()
|driver.find_element(By.CSS_SELECTOR, "input[type='checkbox']:first-of-type").is_selected()
|-
|-
|元素标签名
|元素标签名
|Get TagName
|tag_name
|获取元素的TagName(标签名)。
|获取元素的TagName(标签名)。
|driver.find_element(By.CSS_SELECTOR, "h1").tag_name
|driver.find_element(By.CSS_SELECTOR, "h1").tag_name
|-
|-
|元素的尺寸和坐标
|元素的尺寸和坐标
|Get Rect
|rect
|用于获取参考元素的尺寸和坐标,提取的数据主体包含以下详细信息:1.元素左上角的X轴位置,2.元素左上角的y轴位置,3.元素的高度,4.元素宽度
|用于获取参考元素的尺寸和坐标,提取的数据主体包含以下详细信息:1.元素左上角的X轴位置,2.元素左上角的y轴位置,3.元素的高度,4.元素宽度
|driver.find_element(By.CSS_SELECTOR, "h1").rect
|driver.find_element(By.CSS_SELECTOR, "h1").rect
|-
|-
|元素CSS值
|元素CSS值
|Get CSS Value
|value_of_css_property()
|获取当前浏览上下文中元素的特定计算样式属性的值。
|获取当前浏览上下文中元素的特定计算样式属性的值。
|ddriver.findElement(By.LINK_TEXT, "More information...").value_of_css_property('color')
|ddriver.findElement(By.LINK_TEXT, "More information...").value_of_css_property('color')
|-
|-
|获取元素文本
|获取元素文本
|Get Text
|text
|获取特定元素渲染后的文本
|获取特定元素渲染后的文本
|driver.find_element(By.CSS_SELECTOR, "h1").text
|driver.find_element(By.CSS_SELECTOR, "h1").text
|-
|-
|获取元素属性的值
|get_attribute()
|
|<code>element.get_attribute('href')</code>获取元素的href值 <br /><code>element.get_attribute('innerHTML')</code>获取元素的内部HTML代码 <br /> <code>ele.get_atrribute("outerHTML")</code>获取元素的HTML代码
|-
|获取元素属性的值
|get_property()
|
|<code>element.get_property('href')</code>
|}
{{了解更多
|[https://www.selenium.dev/documentation/zh-cn/webdriver/web_element/ Selenium 文档:WebDriver - 网络元素]
|[https://selenium-python.readthedocs.io/locating-elements.html baijum/selenium python文档:Locating Elements]}}
===选择列表元素===
选择列表元素相比普通元素,提供了一系列方法,方便与<select> 元素进行交互。该类仅适用于用于 HTML 元素 select 和 option。
Python为例,点击某个选择列表的所有选项:
<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
driver = webdriver.Firefox()
driver.get('https://example.com')
select_element = driver.find_element(By.TAG_NAME, 'select')
select = Select(select_element)
for option in select.options:
    print(option.text) # 打印选项文本
    option.click()    # 点击选项
</syntaxhighlight>
以下是select元素类提供的特别方法,其他属性方法见同普通元素的属性方法如元素可见文本<code>elem.text</code>,点击元素<code>elem.click()</code>。
{| class="wikitable"
! 名称
! 描述
! 示例
|-
| 构建类
| 生成选择列表元素对象。定位 <select> 元素,然后使用Select()初始化一个Select 对象。Selenium 4.5 开始, 您无法针对禁用的 <select> 元素构建 Select 对象.
| <syntaxhighlight lang="python" >
select_element = driver.find_element(By.NAME, 'selectomatic')
select = Select(select_element)
</syntaxhighlight>
|-
| 全部选项
| 获取 <select> 元素中所有选项列表
| <code>select.options</code>
|-
| 所选中的选项列表
| 获取 <select> 元素中所选中的选项列表。对于单选列表,返回只包含一个元素的列表,对于复选列表则表示包含的零个或多个元素。
| <code>select.all_selected_options</code>
|-
| 通过文本选择选项
| 根据其可见文本选择选项
| <code> select.select_by_visible_text('2021年')</code>
|-
| 通过value值选择选项
| 根据其值属性选择选项
| <code>select.select_by_value('2021')</code>
|-
| 通过序号值选择选项
| 根据其在列表中的位置选择选项
| <code> select.select_by_index(3)</code>
|-
| 通过value值的disabled选择选项
| 具有 disabled 属性的选项可能无法被选择。Selenium v4.5 + 支持
| <syntaxhighlight lang="python" >
with pytest.raises(NotImplementedError):
    select.select_by_value('disabled')
</syntaxhighlight>
|-
| 取消选择选项
| 只有复选类型的选择列表才能取消选择选项. 您可以对要选择的每个元素重复使用这些方法.
| <code>select.deselect_by_value('eggs')</code>
|}
|}


{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/web_element/ Selenium 文档:WebDriver - 网络元素]}}
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/support_features/select_lists/ Selenium 文档: 使用选择列表元素]
}}
 


==键盘操作==
==操作==
键盘操作通过使用底层接口允许我们向web浏览器提供虚拟设备输入。
===键盘操作===
===键盘输入===
键盘操作通过使用底层接口允许我们向web浏览器提供虚拟设备输入。以下示例为Python版,打开百度网页,在输入框输入”webdriver“并按回车键:
sendKeys用于模拟键盘输入。不同语言版本中函数名有一些差别,如Java中使用sendKeys()函数,Python中使用send_keys()函数。以下示例为Python版,打开百度网页,在输入框输入”webdriver“并按回车键:
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
from selenium import webdriver
from selenium import webdriver
第269行: 第582行:
</syntaxhighlight>
</syntaxhighlight>


===按下按键===
{| class="wikitable"
keyDown用于模拟按下辅助按键(CONTROL, SHIFT, ALT)的动作。
! 名称
! 描述
! 示例
|-
| 键盘输入 <br />sendKeys
| 用于模拟键盘输入。
|
|-
| 按下按键 <br />keyDown
| 用于模拟按下辅助按键(CONTROL, SHIFT, ALT)的动作。
|
|-
| 按键弹起 <br />keyUp
| 用于模拟辅助按键(CONTROL, SHIFT, ALT)弹起或释放的操作。
|
|-
| 清除<br />clear
| 用于清除可编辑元素的内容。
|
|}
 
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/keyboard/ Selenium 文档:WebDriver - Keyboard]}}
 
===鼠标操作===
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/actions_api/mouse/  Selenium 文档:Mouse actions]
}}
===笔操作===


===按键弹起===
===滚轮操作===
keyUp用于模拟辅助按键(CONTROL, SHIFT, ALT)弹起或释放的操作。


===清除===
==等待==
clear用于清除可编辑元素的内容。
网页加载有大量异步内容,某些元素可能在程序运行后才出现,导致查找时出现找不到。
{| class="wikitable"
! 名称
! 描述
! 示例
|-
| 显式等待
| 条件为假时一直尝试,条件真时继续执行。 
| <syntaxhighlight lang="python" >
from selenium.webdriver.support.wait import WebDriverWait


{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/keyboard/ Selenium 文档:WebDriver - Keyboard]}}
WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))
</syntaxhighlight>
|-
| 隐式等待
| WebDriver在查找元素时先等待设置的时间,默认时间为0,表示禁用。不要混合使用隐式和显式等待,这样做会导致不可预测的等待时间。
|<syntaxhighlight lang="python" >
from selenium import webdriver
 
driver = Firefox()
driver.implicitly_wait(10)
</syntaxhighlight>
|-
| 流畅等待
| 流畅等待实例定义了等待条件的最大时间量,以及检查条件的频率。用户可以配置等待来忽略等待时出现的特定类型的异常,例如在页面上搜索元素时出现的NoSuchElementException。
|<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
 
driver = Firefox()
driver.get("http://www.baidu.com")
wait = WebDriverWait(driver, timeout=10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))
</syntaxhighlight>
|}
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/waits/ selenium 文档:等待 ]
}}
===显式等待===
<syntaxhighlight lang="python" >
from selenium.webdriver.support.wait import WebDriverWait
 
WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))
</syntaxhighlight>
 
每个语言的selenium都附带了一些常用的预期的条件,方便使用:
* Python:https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html
{| class="wikitable"
! 名称
! 描述
|-
| invisibility_of_element_located()
| 检查元素是否可见
|-
| presence_of_element_located()
| 检查元素是否存在
|-
|
|
|-
|
|
|}
 
 
示例:
<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
 
# Selenium WebDriver 3.13+
with webdriver.Firefox() as driver:
    wait = WebDriverWait(driver, 10)
    driver.get("https://www.baidu.com")
    driver.find_element(By.NAME, "wd").send_keys("hello world" + Keys.RETURN)
    first_result = wait.until(EC.presence_of_element_located((By.ID, "1")))
    print(first_result.text)
</syntaxhighlight>
 
{{了解更多
|[https://www.selenium.dev/zh-cn/documentation/webdriver/waits/ selenium 文档:等待 ]
|[https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html  selenium Python API:selenium.webdriver.support.expected_conditions]
}}
 
==扩展==
{| class="wikitable"
! 名称
! 描述
! 网站
|-
| Selenium Wire
| 支持Python,可以访问或修改浏览器发出的底层请求。 <br />安装<code>pip install selenium-wire</code>
| https://github.com/wkeeling/selenium-wire
|-
|
|
|
|-
|
|
|
|}
 
== 检测与防检测 ==
=== 防检测 ===
有些网站会使用js检测浏览器是否为webdriver,检测出来就会访问不正常,所以需要隐藏webdriver指纹特征。
{| class="wikitable"
! 方法
! 描述
|-
| execute_cdp_cmd()隐藏指纹特征
| 先运行cdp命令清除webdriver,再浏览。
<syntaxhighlight lang="python" >
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
 
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_argument("--incognito")  # 可选,配置隐私模式
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': 'Object.defineProperty(navigator,"webdriver",{get: () => undefined})'
})


driver.get('https://www.baidu.com')
</syntaxhighlight>
|-
| 使用stealth.min.js隐藏指纹特征
|
|-
| 控制正在运行的浏览器
|
|}


==资源==
==资源==
第288行: 第762行:
*PyPI:https://pypi.python.org/pypi/selenium
*PyPI:https://pypi.python.org/pypi/selenium


==参考资料==
===相关网站===
*[https://en.wikipedia.org/wiki/Selenium_(software) 维基百科:Selenium (software)]
*[https://en.wikipedia.org/wiki/Selenium_(software) 维基百科:Selenium (software)]
*[https://developer.mozilla.org/zh-CN/docs/Web/WebDriver MDN:WebDriver]
*[https://developer.mozilla.org/zh-CN/docs/Web/WebDriver MDN:WebDriver]
*baijum/selenium python文档:https://selenium-python.readthedocs.io/index.html

2023年4月9日 (日) 07:18的最新版本

Selenium 是一个Web应用测试的开源框架,提供一系列Web浏览器自动化工具,可以模拟用户与浏览器的交互。Selenium IDE是一个Firefox插件,使用图形界面录制和测试。也可以通过Selenium WebDriver,使用多种语言来编写测试,包括:JavaPythonC#RubyJavaScriptKotlin

简介

主要工具

以下为Selenium提供的主要工具:

Selenium WebDriver:

Selenium IDE:

Grid:

安装 Selenium

使用不同的语言,安装Selenium方式不同。

Python中可以使用 pip 安装Selenium:

pip install selenium

也可以下载源代码安装。

JavaScript中可以使用 npm 安装 :

npm install selenium-webdriver

了解更多 >> Selenium 文档:安装 Selenium 库


安装浏览器和浏览器驱动

浏览器 支持的操作系统 维护者 驱动 驱动下载
Chromium/Chrome Windows/macOS/Linux 谷歌 ChromeDriver 下载
火狐 Windows/macOS/Linux Mozilla geckodriver 下载
Edge Windows 10 微软 msedgedriver 下载
Internet Explorer Windows Selenium 项目组 下载
Safari macOS El Capitan 及更高版本 苹果 内置
Opera Windows/macOS/Linux Opera 下载

Debian/Ubuntu下安装Chrome浏览器和ChromeDriver驱动为例:

#安装Chrome浏览器
#官网下载Chrome稳定版的deb包
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
#安装Chrome
sudo apt install ./google-chrome-stable_current_amd64.deb
#验证成功,查看chrome版本,结果如:Google Chrome 87.0.4280.88
google-chrome --version

#chromedriver驱动官网:https://chromedriver.storage.googleapis.com/index.html
#在官网查找下载chrome版本对应的chromedriver驱动。如Google Chrome 87.0.4280.88
wget https://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip
#解压缩
unzip chromedriver_linux64.zip
#可以将chromedriver文件放置在环境变量路径(通过echo $PATH查看)上。
mv chromedriver /usr/bin

在命令行输入驱动名,验证是否添加成功。

chromedriver  # chrome
geckodriver  # firefox

检测安装成功

以Python语言示例:

from selenium import webdriver

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

如果不将驱动加入环境变量,需要在每次使用时,指定驱动路径。以Python使用为例:

# executable_path 在selenium 4 已弃用
from selenium import webdriver
from selenium.webdriver.firefox.service import Service

s = Service(r'D:\geckodriver-v0.31.0-win6\geckodriver.exe')
driver = webdriver.Firefox(service=s)
driver.get('https://www.baidu.com')

常见错误:

加入环境变量后,在代码中还是显示找不到

重启编辑器即可。

了解更多 >> Selenium 文档:WebDriver > 驱动要求


快速入门

浏览器

名称 描述 示例
Chrome
from selenium import webdriver
driver = webdriver.Chrome()
firefox
from selenium import webdriver
driver = webdriver.Firefox()

无头浏览器

Python语言chrome示例:

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')  #
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(chrome_options=chrome_options) #如果chromedriver没有添加到环境变量中,就需要添加参数指明路径executable_path='/path/to/chromedriver'

driver.get("https://www.baidu.com")
print(driver.page_source)
driver.quit()

firefox示例:

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

op = Options()
op.headless = True

driver = webdriver.Firefox(options=op)
driver.get(url)
print(driver.title)

driver.close()

下载文件

firefox示例:

from selenium import webdriver
from selenium.webdriver.firefox.options import Options


op = Options()
op.set_preference("browser.download.folderList",2)
op.set_preference("browser.download.manager.showWhenStarting", False)
op.set_preference("browser.download.dir",save_path)  # 设置下载位置
op.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream")
op.headless = True  # 设置无头模式

driver = webdriver.Firefox(options=op)
# 需要先在浏览器中设置该文件直接保存
driver.get(r'https://test.com/test.jpg')
driver.close()

浏览器设置

浏览器参数

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')  # 无头模式(无界面)
options.add_argument("--incognito") # 隐私模式
driver = webdriver.Chrome(options=options)

driver.get("https://www.baidu.com")
print(driver.page_source)
driver.quit()


一些常用参数:

参数名 描述 示例
--headless 无头模式(无界面) options.add_argument('--headless')
--incognito 隐私模式 options.add_argument('--incognito')
--window-size 浏览器窗口大小 options.add_argument('--window-size=1920,1080')
--user-agent 浏览器User Agent options.add_argument('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"')
--disable-extensions 禁用扩展程序 options.add_argument('--disable-extensions')
--disable-gpu 禁用GPU加速 options.add_argument('--disable-gpu')
--ignore-certificate-errors 忽略证书错误 options.add_argument('--ignore-certificate-errors')
--proxy-server 设置代理服务器 options.add_argument('--proxy-server=http://username:password@proxyserver:port')

了解更多 >> selenium 文档:browsers/chrome Peter Beverloo:List of Chromium Command Line Switches


浏览器操作

以下Python编程语言示例:

from selenium import webdriver

driver = webdriver.Chrome()

浏览器导航

操作 描述 Python示例
打开网站 浏览器输入地址,打开网站 driver.get("https://www.baidu.com")
获取当前 URL 从浏览器的地址栏读取当前的 URL driver.current_url
后退 按下浏览器的后退按钮 driver.back()
前进 按下浏览器的前进键 driver.back()
刷新 刷新当前页面 driver.refresh()
获取标题 从浏览器中读取当前页面的标题 driver.title

窗口和标签页

WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。

操作 描述 Python示例
当前窗口句柄 获得当前窗口的窗口句柄,返回一个字符串 driver.current_window_handle
所有窗口句柄 获得所有窗窗口的窗口句柄,返回一个列表 driver.window_handles
切换窗口或标签页 WebDriver没有当前活动窗口,要使用某个窗口需要使用switch_to.window('窗口句柄')切换。
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://seleniumhq.github.io")
# 存储原始窗口的 ID
original_window = driver.current_window_handle
# 单击在新窗口中打开的链接
driver.find_element(By.LINK_TEXT, "new window").click()
# 等待浏览器加载完毕
driver.implicitly_wait(7)

# 循环执行,直到找到一个新的窗口句柄
for window_handle in driver.window_handles:
    if window_handle != original_window:
        driver.switch_to.window(window_handle)
        break
print(driver.title)
创建新窗口或新标签页,并且切换 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 + driver.switch_to.new_window('tab') # 打开新标签页并切换到新标签页
driver.switch_to.new_window('window') # 打开新标签页并切换到新标签页
关闭窗口或标签页 当你完成了一个窗口或标签页的工作时,_并且_它不是浏览器中最后一个打开的窗口或标签页时,你应该关闭它并切换回你之前使用的窗口。 driver.close()
退出浏览器 调用quit退出浏览器。退出将会关闭所有与 WebDriver 会话相关的窗口和选项卡,结束浏览器进程,结束后台驱动进程,通知 Selenium Grid 浏览器不再使用,以便可以由另一个会话使用 driver.quit()


了解更多 >> Selenium 文档:WebDriver - 同窗口和标签一起工作 Selenium 文档:WebDriver - 操控浏览器


使用Cookie

Cookie是从网站发送并存储在您的计算机中的一小段数据,主要用于识别用户并加载存储的信息。

名称 描述 示例
添加Cookie
add_cookie()
添加Cookie,然后手动或自动刷新浏览器。

driver.add_cookie({"name": "key", "value": "value"})

获取cookie可以在浏览器Web开发者工具,或使用selenium函数获取。
cookie = {
    'version':'1.1.0',
    'username' : 'auser',
    'impress':'df88568486969', 
    'fim': 'mikllf', 
}
cookies  = [{'name':k, 'value':v} for k,v in cookie.items()]
for item in cookies:
    driver.add_cookie(item)

了解更多 >> Selenium 文档:使用 Cookie


元素

WebElement表示DOM元素。

查找元素

可以通过使用WebDriver实例从文档根节点进行搜索,或者在另一个WebElement下进行搜索来找到WebElement。

操作 方法 描述 Python示例
查找单个元素 Find Element 此方法用于查找元素并返回第一个匹配的单个WebElement引用。 driver.find_element(By.NAME, "q")
查找多个元素 Find Elements 与"Find Element"相似, 但返回的是匹配WebElement列表。要使用列表中的特定WebElement,您需要遍历元素列表以对选定元素执行操作。 driver.find_elements(By.TAG_NAME, 'p')
查找当前页面上下文中具有焦点的元素 Active Element 此方法用于追溯或查找当前页面上下文中具有焦点的DOM元素 driver.switch_to.active_element

WebDriver API提供了内置方法来查找基于不同属性的WebElement (例如ID, Name, Class, XPath, CSS选择器, 链接文本等)。以下使用查找单个元素Find Element示例,查找多个元素Find Elements同样适用。 Python版本的find_element_by_* 系列的方法,在新版本中以弃用

操作 描述 Python 示例
By ID 通过ID查找元素。适用元素如:<div id="q">...</div> driver.find_element(By.ID, "q")
By Name 通过Name查找元素。适用元素如:<input name="btnK">...</input> driver.find_element(By.NAME, 'btnK')
By Class Name 通过Class Name查找元素。适用元素如:<p class="rk">...</p> driver.find_element(By.CLASS_NAME, 'rk')
By Tag Name 通过标签名查找元素 driver.find_element(By.TAG_NAME, "div")
By Link Text 通过链接文本查找元素 driver.find_element(By.LINK_TEXT, "更多信息...")
By Partial Link Text 通过部分链接文本查找元素 driver.find_element(By.PARTIAL_LINK_TEXT, "更多信")
By CSS 通过CSS选择器查找元素 driver.find_element(By.CSS_SELECTOR, "h1")
By XPath 通过XPath查找元素。 driver.find_element(By.XPATH, "//form[1]")


元素属性和方法

操作 方法或属性 描述 Python示例
元素是否被启用或禁用 is_enabled() 此方法用于检查网页上连接的元素是否被启用或禁用. 返回一个布尔值, 如果在当前浏览上下文中启用了连接的元素, 则返回True; 否则返回false 。 driver.find_element(By.NAME, 'btnK').is_enabled()
元素是否被选中 is_selected() 此方法确定是否 已选择 引用的元素. 此方法广泛用于复选框, 单选按钮, 输入元素和选项元素.返回一个布尔值, 如果在当前浏览上下文中 已选择 引用的元素, 则返回 True, 否则返回 False。 driver.find_element(By.CSS_SELECTOR, "input[type='checkbox']:first-of-type").is_selected()
元素标签名 tag_name 获取元素的TagName(标签名)。 driver.find_element(By.CSS_SELECTOR, "h1").tag_name
元素的尺寸和坐标 rect 用于获取参考元素的尺寸和坐标,提取的数据主体包含以下详细信息:1.元素左上角的X轴位置,2.元素左上角的y轴位置,3.元素的高度,4.元素宽度 driver.find_element(By.CSS_SELECTOR, "h1").rect
元素CSS值 value_of_css_property() 获取当前浏览上下文中元素的特定计算样式属性的值。 ddriver.findElement(By.LINK_TEXT, "More information...").value_of_css_property('color')
获取元素文本 text 获取特定元素渲染后的文本 driver.find_element(By.CSS_SELECTOR, "h1").text
获取元素属性的值 get_attribute() element.get_attribute('href')获取元素的href值
element.get_attribute('innerHTML')获取元素的内部HTML代码
ele.get_atrribute("outerHTML")获取元素的HTML代码
获取元素属性的值 get_property() element.get_property('href')

了解更多 >> Selenium 文档:WebDriver - 网络元素 baijum/selenium python文档:Locating Elements


选择列表元素

选择列表元素相比普通元素,提供了一系列方法,方便与<select> 元素进行交互。该类仅适用于用于 HTML 元素 select 和 option。

Python为例,点击某个选择列表的所有选项:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select

driver = webdriver.Firefox()
driver.get('https://example.com')

select_element = driver.find_element(By.TAG_NAME, 'select')
select = Select(select_element)
for option in select.options:
    print(option.text) # 打印选项文本
    option.click()     # 点击选项

以下是select元素类提供的特别方法,其他属性方法见同普通元素的属性方法如元素可见文本elem.text,点击元素elem.click()

名称 描述 示例
构建类 生成选择列表元素对象。定位 <select> 元素,然后使用Select()初始化一个Select 对象。Selenium 4.5 开始, 您无法针对禁用的 <select> 元素构建 Select 对象.
select_element = driver.find_element(By.NAME, 'selectomatic')
select = Select(select_element)
全部选项 获取 <select> 元素中所有选项列表 select.options
所选中的选项列表 获取 <select> 元素中所选中的选项列表。对于单选列表,返回只包含一个元素的列表,对于复选列表则表示包含的零个或多个元素。 select.all_selected_options
通过文本选择选项 根据其可见文本选择选项 select.select_by_visible_text('2021年')
通过value值选择选项 根据其值属性选择选项 select.select_by_value('2021')
通过序号值选择选项 根据其在列表中的位置选择选项 select.select_by_index(3)
通过value值的disabled选择选项 具有 disabled 属性的选项可能无法被选择。Selenium v4.5 + 支持
with pytest.raises(NotImplementedError):
    select.select_by_value('disabled')
取消选择选项 只有复选类型的选择列表才能取消选择选项. 您可以对要选择的每个元素重复使用这些方法. select.deselect_by_value('eggs')

了解更多 >> Selenium 文档: 使用选择列表元素



操作

键盘操作

键盘操作通过使用底层接口允许我们向web浏览器提供虚拟设备输入。以下示例为Python版,打开百度网页,在输入框输入”webdriver“并按回车键:

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

driver = webdriver.Chrome() 

# 打开百度页面
driver.get("http://www.baidu.com")

# 输入"webdriver"文本和输入"ENTER"按键
driver.find_element(By.ID, "kw").send_keys("webdriver" + Keys.ENTER)

# 查看页面代码
driver.page_source
名称 描述 示例
键盘输入
sendKeys
用于模拟键盘输入。
按下按键
keyDown
用于模拟按下辅助按键(CONTROL, SHIFT, ALT)的动作。
按键弹起
keyUp
用于模拟辅助按键(CONTROL, SHIFT, ALT)弹起或释放的操作。
清除
clear
用于清除可编辑元素的内容。

了解更多 >> Selenium 文档:WebDriver - Keyboard


鼠标操作

了解更多 >> Selenium 文档:Mouse actions


笔操作

滚轮操作

等待

网页加载有大量异步内容,某些元素可能在程序运行后才出现,导致查找时出现找不到。

名称 描述 示例
显式等待 条件为假时一直尝试,条件真时继续执行。
from selenium.webdriver.support.wait import WebDriverWait

WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))
隐式等待 WebDriver在查找元素时先等待设置的时间,默认时间为0,表示禁用。不要混合使用隐式和显式等待,这样做会导致不可预测的等待时间。
from selenium import webdriver

driver = Firefox()
driver.implicitly_wait(10)
流畅等待 流畅等待实例定义了等待条件的最大时间量,以及检查条件的频率。用户可以配置等待来忽略等待时出现的特定类型的异常,例如在页面上搜索元素时出现的NoSuchElementException。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC

driver = Firefox()
driver.get("http://www.baidu.com")
wait = WebDriverWait(driver, timeout=10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))

了解更多 >> selenium 文档:等待


显式等待

from selenium.webdriver.support.wait import WebDriverWait

WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))

每个语言的selenium都附带了一些常用的预期的条件,方便使用:

名称 描述
invisibility_of_element_located() 检查元素是否可见
presence_of_element_located() 检查元素是否存在


示例:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC

# Selenium WebDriver 3.13+
with webdriver.Firefox() as driver:
    wait = WebDriverWait(driver, 10)
    driver.get("https://www.baidu.com")
    driver.find_element(By.NAME, "wd").send_keys("hello world" + Keys.RETURN)
    first_result = wait.until(EC.presence_of_element_located((By.ID, "1")))
    print(first_result.text)

了解更多 >> selenium 文档:等待 selenium Python API:selenium.webdriver.support.expected_conditions


扩展

名称 描述 网站
Selenium Wire 支持Python,可以访问或修改浏览器发出的底层请求。
安装pip install selenium-wire
https://github.com/wkeeling/selenium-wire

检测与防检测

防检测

有些网站会使用js检测浏览器是否为webdriver,检测出来就会访问不正常,所以需要隐藏webdriver指纹特征。

方法 描述
execute_cdp_cmd()隐藏指纹特征 先运行cdp命令清除webdriver,再浏览。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_argument('--disable-blink-features=AutomationControlled') 
options.add_argument("--incognito")  # 可选,配置隐私模式
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': 'Object.defineProperty(navigator,"webdriver",{get: () => undefined})'
})

driver.get('https://www.baidu.com')
使用stealth.min.js隐藏指纹特征
控制正在运行的浏览器

资源

官网

相关网站