官方文档
https://www.selenium.dev/selenium/docs/api/py/api.html
安装
pip install selenium
下载浏览器驱动
谷歌驱动
http://chromedriver.storage.googleapis.com/index.html
chrome与谷歌驱动版本对应表
https://www.cnblogs.com/yfacesclub/p/8482681.html
火狐驱动
https://github.com/mozilla/geckodriver/releases
驱动配置
以下两个方法都可以。
- chromedriver目录配置到环境变量 ,不需要配置executable_path
- chromedriver放任意地方,使用时配置放置的目录。
CHROMEDRIVER_PATH = "d:/chromedriver.exe"
driver = webdriver.Chrome(executable_path=CHROMEDRIVER_PATH)
元素定位
xpath定位:
参考:
https://www.w3school.com.cn/xpath/xpath_intro.asp
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3 ] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
轴定位
轴名称 | 结果 |
---|---|
ancestor | 选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute | 选取当前节点的所有属性。 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点。 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
实例
例子 | 结果 |
---|---|
child::book | 选取所有属于当前节点的子元素的 book 节点。 |
attribute::lang | 选取当前节点的 lang 属性。 |
child::* | 选取当前节点的所有子元素。 |
attribute::* | 选取当前节点的所有属性。 |
child::text() | 选取当前节点的所有文本子节点。 |
child::node() | 选取当前节点的所有子节点。 |
descendant::book | 选取当前节点的所有 book 后代。 |
ancestor::book | 选择当前节点的所有 book 先辈。 |
ancestor-or-self::book | 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点) |
child::* /child::price | 选取当前节点的所有 price 孙节点。 |
css定位
https://www.w3school.com.cn/cssref/css_selectors.asp
常用的 css selector
选择器 | 例子 | 例子描述 |
---|---|---|
.class | .intro | 选择class=“intro”的所有元素 |
#id | #name | 选择id=“name”的所有元素 |
* | * | 选择所有元素 |
element | p | 选择所有<p> 元素 |
element,element | p,div | 选择所有 <p> 元素和所有<div> 元素 |
element>element | div>p | 选择父元素为<div> 元素的所有<p> 元素 |
element+element | div+p | 选择紧接在<div> 元素的所有<p> 元素 |
element element | div p | 选择<div> 元素内部所有<p> 元素 |
[attribute] | [target] | 选择所有带target属性的元素 |
[attribute=value] | [target=_blank] | 选择target=_blank的所有元素 |
:nth-child(n) | p:nth-child(2) | 选择属于其父元素的第二个子元素的每个<p> 元素 |
element1~ element2 | p~ul | 选择前面有<p> 元素的每个<ul> 元素 |
元素等待:
直接等待
import time
time.sleep(2)
隐式等待
设置一个等待时间,轮询查找,没有找到就抛出异常
dirver.implicitly_wait(3)
显示等待
定义等待条件,当条件发生时才继续执行代码
WebdriverWait 配合until() 和 until_not(),程序每隔一段时间(默认0.5s)进行条件判断。,如果条件成立则执行下一步,。直到超过设置的最长时间
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome(executable_path="../tools/chromedriver.exe")
driver.get("https://image.baidu.com/")
WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.ID,"sttb")))
弹窗处理
switch_to.alert():获取当前页面上的告警框
text :返回alert/comfirm/prompt中的文字信息
accept() 接受现有告警框
dissmiss() 解散当前告警框
send_keys(KeyToSend) 发送文本至警告框。
driver.switch_to.alert.accept()#接受弹窗
driver.switch_to.alert.dismiss()#忽略弹窗
driver.switch_to.alert.send_keys("yes")#弹出框输入yes
ifame
分类iframe、frameset、frame
除frameset外,iframe和frame定位需要使用selenium的一组方法进行
切换iframe
driver.switch_to.frame() #根据元素定位切换frame
driver.switch_to.default_content()) #切换到默认的iframe
driver.switch_to.parent_frame() #切换到父级iframe
iframe_demo
测试地址:https://www.w3school.com.cn/tiy/t.asp?f=js_alert
(1)定位右边的button按钮。发现它在iframe中,这时需切换到iframe中,才能定位到
(2)定位到“w3school”下面的切换主题按钮,需要切换出iframe才能定位到
代码示例
#test_iframe.py
# @File : test_iframe.py
import time
from selenium import webdriver
SLEEP_TIME = 1
driver = webdriver.Chrome(executable_path="../tools/chromedriver.exe")
driver.get("https://www.w3school.com.cn/tiy/t.asp?f=js_alert")
driver.implicitly_wait(5)
time.sleep(SLEEP_TIME)
# 点击切换主题按钮
driver.find_element_by_xpath('//li[@id="tiy_btn_theme"]/a').click()
time.sleep(SLEEP_TIME)
#切换进iframe
driver.switch_to.frame(driver.find_element_by_id("iframeResult"))
#点击“试一试”按钮
driver.find_element_by_tag_name("button").click()
time.sleep(SLEEP_TIME)
# 点击确定,接受弹窗
driver.switch_to.alert.accept()
time.sleep(SLEEP_TIME)
#切换出iframe
driver.switch_to.default_content()
time.sleep(SLEEP_TIME)
#点击切换主题按钮
driver.find_element_by_xpath('//li[@id="tiy_btn_theme"]/a').click()
time.sleep(SLEEP_TIME)
#关闭浏览器
driver.quit()
效果如下
js处理
js处理dom
https://www.w3school.com.cn/htmldom/dom_properties.asp
https://www.w3school.com.cn/jsref/dom_obj_all.asp
js可以解决一下click不生效的问题、页面滚动、处理富文本、时间控件输入等
js = "return document.getElementById("kw").value"
ele = driver.execute_script(js)
滑动页面
document.documentElement.scrollTop=1000
测试地址:https://www.12306.cn/index/
处理时间控件
(1)定位日期输入框,取消日期框readonly属性
(2)赋值一个新的日期给日期框
#test_js.py
import time
from selenium import webdriver
SLEEP_TIME = 3
URL = "https://www.12306.cn/index/"
driver = webdriver.Chrome(executable_path="../tools/chromedriver.exe")
driver.get(URL)
time.sleep(SLEEP_TIME )
#去掉readonly属性,直接输入日期
data_js = 'document.getElementById("train_date").removeAttribute("readonly")'
driver.execute_script(data_js)
#赋值一个新日期
data_js_2 = "document.getElementById('train_date').value='2021-12-32'"
driver.execute_script(data_js_2)
time.sleep(SLEEP_TIME )
driver.quit()
最终效果
input标签上传文件
测试地址:百度图片 https://image.baidu.com/
(1)定位搜索框旁边,上传图标小图标
(2)定位选择【选择文件】按钮,这是一个input标签
(3)向input标签发送一个图片。
代码示例:test_input.py
#test_input.py
# @File : test_input.py
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
SLEEP_TIME = 2
URL = "https://image.baidu.com/"
driver = webdriver.Chrome(executable_path="../tools/chromedriver.exe")
driver.get(URL)
driver.implicitly_wait(5)
time.sleep(SLEEP_TIME)
#点击上传图片的小图标
driver.find_element(By.ID,"sttb").click()
time.sleep(SLEEP_TIME)
#向【选择文件】input标签 发送图片
jpg_path = os.path.join(os.path.split(os.path.abspath(__file__))[0],"piying.jpg")
driver.find_element_by_id("stfile").send_keys(jpg_path)
# 通过页面title是否变化,判断页面是否跳转
WebDriverWait(driver, 30).until(EC.title_is("百度识图搜索结果"))
driver.quit()
最终效果
ActionChains
官方文档:
https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains
ActionChains:执行PC端的鼠标点击,双击,右键,拖拽等事件
执行原理:
调用ActionChains不会立即执行,而是将所有的操作,按顺序放在一个队列里,当你调用perfrom()方法时,队列中的事件会一次执行
基本用法:
- 生成一个动作action=ActionChains(driver)
- 动作添加方法1 action.方法1
- 动作添加方法2 action.方法2
- 调用perform()方法执行(action.perform())
常用方法
方法 | 释义 |
---|---|
click(on_element=None) | 单击鼠标左键 |
click_and_hold(on_element=None) | 点击鼠标左键,不松开 |
context_click(on_element=None) | 点击鼠标右键 |
double_click(on_element=None) | 双击鼠标左键 |
drag_and_drop(source, target) | 拖拽到某个元素然后松开 |
drag_and_drop_by_offset(source, xoffset, yoffset) | 拖拽到某个坐标然后松开 |
key_down(value, element=None) | 按下某个键盘上的键 |
key_up(value, element=None) | 松开某个键 |
move_by_offset(xoffset, yoffset) | 鼠标从当前位置移动到某个坐标,注意这里的位移是指从鼠标当前坐标移动的大小移动多少加减多少就行 |
move_to_element(to_element) | 鼠标移动到某个元素 |
move_to_element_with_offset(to_element, xoffset, yoffset) | 移动到距某个元素(左上角坐标)多少距离的位置 |
perform() | 执行链中的所有动作 |
release(on_element=None) | 在某个元素位置松开鼠标左键 |
send_keys(*keys_to_send) | 发送某个键到当前焦点的元素 |
send_keys_to_element(element, *keys_to_send) | 发送某个键到指定元素 |
代码示例:
#test_ActionChains.py
import time
from selenium import webdriver
from selenium.webdriver import ActionChains
SLEEP_TIME = 3
URL = "https://www.runoob.com/try/try.php?filename=tryhtml5_ev_onmousedown"
driver = webdriver.Chrome(executable_path="../tools/chromedriver.exe")
driver.get(URL)
driver.implicitly_wait(5)
# 切换iframe
driver.switch_to.frame(driver.find_element_by_id("iframeResult"))
# 定位p元素
p = driver.find_element_by_id("p1")
actions = ActionChains(driver)
#点击并保持
actions.click_and_hold(p)
# 执行
actions.perform()
time.sleep(SLEEP_TIME)
driver.quit()
效果如下
TouchActions
文档
https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.touch_actions
类似ActionChains,ActionChains对h5页面无效,可以用TouchAction对h5页面操作。通过TouchAction可以实现点击,滑动,拖拽,多点触控,以及模拟手势的操作。
操作 | 释义 |
---|---|
tap | 在指定元素上敲击 |
double_tap | 在指定元素上双击 |
move | 收拾一定指定偏移(未释放) |
tap_and_hold | 在指定元素上点击但不释放 |
release | 释放手势 |
scroll | 手势点击并滚动 |
scroll_from_element | 从某个元素位置开始手势点击并滚动 |
long_press | 长按元素 |
flick | 手势滑动 |
flick_element | 从某个元素位置开始手势滑动 |
perform | 执行 |
谷歌浏览器复用
1.谷歌浏览器目录配置到环境变量(桌面右键谷歌浏览器图标->属性,可以找到路径)
2.关闭所有谷歌浏览器标签
3.谷歌以调试模式启动chrome --remote-debugging-port=9222
4.手动点击以调试模式打开的谷歌浏览器,进入要调试的页面,页面保持不关闭
5.添加代码,浏览器启动设置为调式模式
import time
# pip install -U selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
CHROMEDRIVER_PATH = "./chromedriver.exe"
LOGIN_URL = "https://work.weixin.qq.com/wework_admin/loginpage_wx?from=myhome"
URL = "https://work.weixin.qq.com/wework_admin/frame"
COOKIES_YAML = "./cookies.yaml"
class TestChromeDebug:
def test_remote(self):
option = webdriver.ChromeOptions()
option.debugger_address = "127.0.0.1:9222" #确保设置的端口不被占用
self.driver = webdriver.Chrome(executable_path=CHROMEDRIVER_PATH,chrome_options=option)
self.driver.implicitly_wait(10)
#前提:企业微信页面停留在主页面
# 点击添加员工
self.driver.find_element(By.CSS_SELECTOR, "[node-type='addmember']").click()
# 输入员工名称
self.driver.find_element(By.CSS_SELECTOR, "[id='username']").send_keys("新员工小菜")
# 输入工号
self.driver.find_element(By.CSS_SELECTOR, "[id='memberAdd_acctid']").send_keys("002")
# 输入邮箱
self.driver.find_element(By.CSS_SELECTOR,"[id='memberAdd_mail']").send_keys("1222222222@qq.com")
# 点击保存按钮
self.driver.find_element(By.CSS_SELECTOR,"a.qui_btn.ww_btn.js_btn_save").click()
time.sleep(4)