Selenium webdriver常用操作
目录
- 常用类与方法
- 元素定位
- selenium其它操作
- 窗口切换
- 截图
常用类、方法、属性
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/30 12:01' # software: PyCharm import time from selenium import webdriver # 浏览器驱动 from selenium.webdriver import ActionChains # 鼠标事件 from selenium.webdriver.common.by import By # 选择器,以什么方式选择标签元素 from selenium.webdriver.common.keys import Keys # 键盘事件 from selenium.webdriver.support import expected_conditions as EC # 各种判断, from selenium.webdriver.support.wait import WebDriverWait # 等待事件 # 实例化Chrome浏览器对象 # selenium通过控制浏览器,所以获取的数据都是elements中的内容 driver = webdriver.Chrome() # Chrome浏览器驱动放在解释器文件夹中,所以不用指定驱动路径 driver.get("https://www.baidu.com") # 访问百度 # 常用属性 # current_title = driver.title #获取当前页面的title # driver.current_url # 获取当前windows的url # driver.page_source # 获取页面的内容,即html页面 # driver.current_window_handle # 获取当前窗口对象 # 常用方法 # driver.get_window_size()# 获取浏览器窗口的大小 # driver.get_cookies() # 获取cookies # 截图(截取可见区域) # driver.save_screenshot("bad.png") # 指定截图名,已图片格式结尾 # driver.set_window_size(800, 600) # 设置浏览器的宽800px,高600px # driver.execute_script("alert('你好!');") #执行js代码 # driver.refresh()# 刷新 # driver.back() # 后退 # driver.forward()# 前进 # driver.close() #只关闭当前窗口 # driver.quit() #退出浏览器驱动,关闭所有关联窗口
元素定位
目标:
- 掌握selenium定位元素的方法
- 掌握selenium从元素中获取文本和属性方法
1、selenium定位操作
1-1、定位元素两种写法:
直接调用
ele = driver.find_element_by_xxx(value) # xxx是定位方式,value该方式对应的值
使用By类型(需要导入By)建议使用这种方式
from selenium.webdriver.common.by import By driver.find_element(By.xxx,value)
1-2、元素定位的两种方式:
精确定位一个元素,返回一个element对象,定位不到会报错
from selenium.webdriver.common.by import By driver.find_element(By.xxx,valus) driver.find_element_by_xpath(value)
定位一组元素,返回一个element对象列表,定位不到返回空列表
from selenium.webdriver.common.by import By driver.find_elements(By.xxx,valus) # 定位不到返回空列表 driver.find_elements_by_xpath(value)# 定位不到返回空列表/
1-3、元素定位的八种方法:
以下方法在element之后添加s就变成能够获取一组元素的方法
By.ID 使用id值定位
from selenium.webdriver.common.by import By driver.find_element(By.ID,'') driver.find_element_by_id()
By.XPATH使用xpath定位
el = driver.find_element(By.XPATH,'') el = driver.find_element_by_xpath()
By.TAG_NAME使用标签名定位
el = driver.find_element(By.TAG_NAME,'') el = driver.find_element_by_tag_name()
By.LINK_TEXT使用超链接文本定位
el = driver.find_element(By.LINK_TEXT, '') el = driver.find_element_by_link_text()
By.PARTIAL_LINK_TEXT 使用部分超链接文本定位
el = driver.find_element(By.PARTIAL_LINK_TEXT , '') el = driver.find_element_by_partial_link_text()
By.NAME 使用name属性值定位
el = driver.find_element(By.NAME, '') el = driver.find_element_by_name()
By.CLASS_NAME 使用class属性值定位
el = driver.find_element(By.CLASS_NAME, '') el = driver.find_element_by_class_name()
By.CSS_SELECTOR 使用css选择器定位
el = driver.find_element(By.CSS_SELECTOR, '') el = driver.find_element_by_css_selector()
注意:
- 2、find_element与find_elements
的区别;
- 3、by_link_text和by_partial_link_text的区别:
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/30 14:54' # software: PyCharm import time from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) # 等待节点加载完成 driver.get("https://www.douban.com/search?q=%E5%BA%B7%E6%9C%89%E4%B8%BA") time.sleep(2) # 使用id方式获取右上角的搜索框,然后输入搜索关键字 # ret1 = driver.find_element(By.ID, 'inp-query') # 搜索输入框使用find_elements进行获取 # ret2 = driver.find_elements(By.ID,'inp-query') # 返回列表 # 搜索按钮使用xpath进行获取 # ret3 = driver.find_elements(By.XPATH,'//*[@id="inp-query"]') # 匹配图片,获取图片的src属性执行 # ret4 = driver.find_elements(By.TAG_NAME, 'img') # print(ret4) # for url in ret4: # print(url.get_attribute("src")) # 匹配超链接文本 # ret5 = driver.find_elements(By.LINK_TEXT,"浏览发现") # 超链接文本包含指定关键字即可 # ret6 = driver.find_elements(By.PARTIAL_LINK_TEXT,"浏览") # print(ret5) # print(ret6) # class名查找 # ret7 = driver.find_elements(By.CLASS_NAME,"nbg") # print(ret7) time.sleep(5) driver.quit()
注意
find_element与find_elements区别:
- 1、只查找一个元素的时候:可以使用find_element()或find_elements(),find_element()会返回一个WebElement节点对象,但是没找到会报错,而find_elements()不会,之后返回一个空列表;
- 3、找到都是节点(标签);
- 4、如果想要获取相关内容(只对find_element()有效,列表对象没有这个属性) 使用 .text;
- 5、如果想要获取相关属性的值(如href对应的链接等,只对find_element()有效,列表对象没有这个属性):使用 .get_attribute("href");
2、元素的操作
find_element_by_xxx方法仅仅能够获取元素对象,接下来就可以对元素执行以下操作 从定位到的元素中提取数据的方法;
2-1 从定位到的元素中获取数据
el.get_attribute(key) # 获取key属性名对应的属性值 el.text # 获取开闭标签之间的文本内容
2-2 对定位到的元素进行操作
el.click() # 对元素执行点击操作 el.submit() # 对元素执行提交操作 el.clear() # 清空可输入元素中的数据 el.send_keys(data) # 向可输入元素输入数据
使用示例:
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/30 16:12' # software: PyCharm import time from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) driver.get("https://www.douban.com/") # 打印页面内容 (获取到以后可以进行后续的xpath,bs4 或者存储等) print(driver.page_source) ret = driver.find_elements(By.TAG_NAME,"h1") print(ret[0].text) # 输出:豆瓣 ret1 = driver.find_elements(By.LINK_TEXT,"下载豆瓣 App") print(ret1[0].get_attribute("href")) # 输出:https://www.douban.com/doubanapp/app?channel=nimingye time.sleep(5) driver.close()
小结
根据xpath定位元素:driver.find_elements(By.XPATH,"//*[@id='s']/h1/a")
根据class定位元素:driver.find_elements(By.CLASS_NAME, "box")
根据link_text定位元素:driver.find_elements(By.LINK_TEXT, "下载豆瓣 App")
根据tag_name定位元素:driver.find_elements(By.TAG_NAME, "h1")
获取元素文本内容:element.text
获取元素标签属性:element.get_attribute("href")
向输入框输入数据:element.send_keys(data)
selenium其他操作
目标
掌握 selenium处理cookie等方法
掌握 selenium中switch的使用
掌握selenium中无头浏览器的设置
键盘、鼠标事件
页面滚动条操作、窗口切换
1、无头浏览器
我们已经基本了解了selenium的基本使用了. 但是呢, 不知各位有没有发现, 每次打开浏览器的时间都比较长. 这就比较耗时了. 我们写的是爬虫程序. 目的是数据. 并不是想看网页. 那能不能让浏览器在后台跑呢? 答案是可以的
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
opt = Options()
opt.add_argument("--headless")
opt.add_argument('--disable-gpu')
opt.add_argument("--window-size=4000,1600") # 设置窗口大小
web = Chrome(options=opt)
2、selenium处理cookie
通过driver.get_cookies()获取所有的cookie
获取cookie
dictCookies = driver.get_cookies()
设置cookie
driver.add_cookie(dictCookies)
删除cookie
#删除一条cookie driver.delete_cookie("CookieName") # 删除所有的cookie driver.delete_all_cookies()
3、页面等待
import time time.sleep(n) # 阻塞等待设定的秒数之后再继续往下执行
显示等待(自动化web测试使用)
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC WebDriverWait(driver, 10,0.5).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) # 显式等待指定某个条件,然后设置最长等待时间10,在10秒内每隔0.5秒使用指定条件去定位元素,如果定位到元素则直接结束等待,如果在10秒结束之后仍未定位到元素则报错
隐式等待
隐式等待设置之后代码中的所有元素定位都会做隐式等待
driver.implicitly_wait(10) # 在指定的n秒内每隔一段时间尝试定位元素,如果n秒结束还未被定位出来则报错
注意:
Selenium显示等待和隐式等待的区别:
selenium的显示等待
原理:显示等待,就是明确要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,就会跳出异常Exception
(简而言之,就是直到元素出现才去操作,如果超时则报异常)
原理:隐式等待,就是在创建driver时,为浏览器对象创建一个等待时间,这个方法是得不到某个元素就等待一段时间,直到拿到某个元素位置。 注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间内部断的刷新页面去寻找我们需要的元素。
4、switch方法切换操作
使用 window_handles 方法来获取每个窗口的操作对象。例如: # 1. 获取当前所有的窗口 current_windows = driver.window_handles # 2. 根据窗口索引进行切换 driver.switch_to.window(current_windows[1]) driver.switch_to.window(web.window_handles[-1]) # 跳转到最后一个窗口 driver.switch_to.window(current_windows[0]) # 回到第一个窗口
4-2、
driver.switch_to.frame(name/el/id) 传入的参数可以使iframe对应的id值,也可以是用元素定位之后的元素对象
4-3、
alert = driver.switch_to_alert()
4-4、页面前进和后台
driver.forward() # 前进 driver.back() # 后退 driver.refresh() # 刷新 driver.close() # 关闭当前窗口
4-5、设置浏览器最大窗口
driver.maximize_window() #最大化浏览器窗口
5、键盘事件
需求:用户名文本框中输入test,然后复制test粘贴到密码文本框中点击回车;
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/2/2 9:28' # software: PyCharm import time from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) driver.get("https://pythonav.com/login/") user_element = driver.find_element(By.ID, "id_username") user_element.send_keys("test") # 全选 user_element.send_keys(Keys.CONTROL, "a") time.sleep(2) # 复制 user_element.send_keys(Keys.CONTROL, "c") # 粘贴到密码框 time.sleep(1) driver.find_element(By.ID, "id_password").send_keys(Keys.CONTROL, "v") # 回车 driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER) time.sleep(10) driver.quit()
6、上传文件
from selenium import webdriver driver = webdriver.Chrome() driver.get("http://127.0.0.1:8002/upload/1") # 文件上传的url #send_keys()参数为文件路径 driver.find_element_by_id("alaxFile").send_keys(r"D:\pythonscript\selenium_stendert\note\geckodriver.log") driver.find_element_by_id("ajaxBtn").click() # 点击上传按钮 driver.quit()
7、滚动条操作
7-1、相对移动
import time from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(time_to_wait=10) driver.get("https://www.cnblogs.com/") time.sleep(3) driver.execute_script("window.scrollBy(0, 700)") # 相对移动,从当前位置移动700像素 time.sleep(3) driver.execute_script("window.scrollBy(0, 700)") # 相对移动,从当前位置移动700像素,即:上次移动700+本次的700=1400像素 time.sleep(3) driver.quit()
7-2、移动到底部/顶部
方法1:
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/30 17:39' # software: PyCharm from selenium import webdriver from selenium.webdriver.common.by import By import time from selenium import webdriver driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(time_to_wait=10) driver.get("https://www.cnblogs.com/") time.sleep(3) # 获取当前窗口对象 element_body = driver.find_element(By.TAG_NAME, "body") # 从顶部下拉到底部 driver.execute_script("arguments[0].scrollIntoView(false);", element_body) # 默认为true time.sleep(3) # 从底部拉到顶部 driver.execute_script("arguments[0].scrollIntoView(true);", element_body) time.sleep(10) driver.quit()
方法2:
使用windows对象
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/30 17:39' # software: PyCharm from selenium import webdriver from selenium.webdriver.common.by import By import time from selenium import webdriver driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(time_to_wait=10) driver.get("https://www.cnblogs.com/") time.sleep(3) # 从顶部下拉到底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") # 从底部拉到顶部 time.sleep(5) driver.execute_script("window.scrollTo(document.body.scrollHeight,0)") time.sleep(10) driver.quit()
8、常用鼠标事件
常用方法
ethod
|
Description
|
---|---|
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)
|
鼠标左键单击不松开,移动到指定坐标后松开
|
move_by_offset(xoffset, yoffset)
|
鼠标移动到某个坐标
|
move_to_element(to_element)
|
鼠标移动到某个元素
|
move_to_element_with_offset(to_element, xoffset, yoffset)
|
鼠标移动到距离某个元素的某个距离
|
pause(seconds)
|
暂停输入
|
release(on_element=None)
|
在某个元素松开鼠标左键
|
send_keys(*keys_to_send)
|
在当前元素中输入值
|
send_keys_to_element(element, *keys_to_send)
|
给某个元素输入值
|
perform()
|
相应存储的动作
|
reset_actions()
|
清除所有已存储的动作
|
8-1 鼠标左键双击&右键单击
import time from selenium import webdriver from selenium.webdriver import ActionChains driver = webdriver.Chrome() driver.get("http://sahitest.com/demo/clicks.htm") time.sleep(1) # 鼠标左键双击 ActionChains(driver).double_click(driver.find_element_by_xpath("/html/body/form/input[2]")).perform() # perform是执行 # 鼠标右击单击 ActionChains(driver).context_click(driver.find_element_by_xpath("/html/body/form/input[4]")).perform()
8-2 鼠标悬浮后选择条目点击
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/31 12:36' # software: PyCharm import time from selenium import webdriver from selenium.webdriver import ActionChains as AC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("https://www.baidu.com/") # 悬浮 driver.maximize_window() driver.implicitly_wait(10) # 悬浮 a_element = driver.find_element(By.ID,"s-usersetting-top") # 移动到指定设置按钮 AC(driver).move_to_element(a_element).perform() time.sleep(2) # 选择高级搜索点击 AC(driver).move_to_element(driver.find_element(By.XPATH,'//*[@id="s-user-setting-menu"]/div/a[2]/span')).click().perform() time.sleep(10) driver.quit()
淘宝官网实例
循环悬浮分类列表。
悬浮【 女装/内衣/ 奢品】并点击【奢品】
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/31 12:36' # software: PyCharm import time from selenium import webdriver from selenium.webdriver import ActionChains as AC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) # 悬浮 driver.get("https://www.taobao.com/") driver.maximize_window() driver.implicitly_wait(5) menu_list = driver.find_elements(By.CLASS_NAME,"J_Cat") print(len(menu_list)) for i in menu_list: AC(driver).move_to_element(i).perform() time.sleep(0.5) AC(driver).move_to_element(menu_list[0]).perform() time.sleep(2) obj = driver.find_element(By.XPATH,"/html/body/div[3]/div[1]/div/ul/li[1]/a[3]") print(obj.text) obj.click() time.sleep(10) driver.quit()
8-3 拖拽
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'tian' __data__ = '2023/1/31 12:36' # software: PyCharm import time from selenium import webdriver from selenium.webdriver import ActionChains as AC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) # 拖拽 driver.get("https://www.jq22.com/demo/pintu20151229/") time.sleep(2) driver.find_element_by_id("start").click() # 起始元素 start = driver.find_element(By.XPATH,'//*[@id="container"]/div[1]') # 终止元素 end = driver.find_element(By.XPATH,'//*[@id="container"]/div[25]') AC(driver).drag_and_drop(start, end).perform() time.sleep(10) driver.quit()
窗口切换
一般的窗口切换就是浏览器打开多个窗口,使用selenium在多个窗口中相互切换。
除此之外,还会遇到iframe窗口,这种相当于大盒子中嵌套小盒子,对于这种窗口切换,重点就是进入某个盒子,退出某个盒子。知道当前在哪个盒子中,就好搞操作了。
重点:
driver.switch_to系列,切换窗口,包括三个常用的方法&1个属性:
1、switch_to.window,切换窗口,替换switch_to_window
2、switch_to.frame,进入iframe,替换switch_to_frame
3、switch_to.default_content,退出iframe,替换原方法switch_to_default_content
4、window_handles属性,获取当前所有打开的窗口列表形式存储
根据这两个方法组合,就达到切换窗口的目的了。我们来演示一个,从百度入口输入关键字并且点击某个结果(因为点击某个链接,会在新的窗口中打开),然后再切换回来。
代码如下:
例1:切换标签页:
import time from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.implicitly_wait(20) try: # 发请求 driver.get("https://www.baidu.com") # 定位标签并深入值然后点击 driver.find_element_by_id("kw").send_keys("python") time.sleep(1) driver.find_element_by_id("su").click() # 在新窗口中,点击结果标签 wait.until(EC.presence_of_element_located((By.LINK_TEXT, 'python解析器'))).click() # 所有打开的窗口都存在这个数组中 print(driver.window_handles) # 根据数组下标索引切换窗口 time.sleep(3) driver.switch_to_window(driver.window_handles[1]) time.sleep(3) driver.switch_to_window(driver.window_handles[0]) except Exception as er: print(er) finally: # 关闭浏览器 time.sleep(3) driver.quit()
iframe窗口切换
iframe记住两个方法:
- switch_to.frame(iframe),进入窗口
- switch_to.default_content(),退出窗口
我们完成一个使用selenium自动发163邮件的程序。
import time from selenium import webdriver driver = webdriver.Chrome()
drrver.implicityl_wait(20) try: # 切换iframe # https://email.163.com/ driver.get("https://email.163.com/") div = driver.find_element_by_id("urs163Area") iframe = div.find_element_by_tag_name("iframe") driver.switch_to.frame(iframe) # 切换到iframe里面 driver.find_element_by_name("email").send_keys("tian") driver.switch_to.default_content() # 切出去iframe except Exception as er: print(er) finally: # 关闭浏览器 time.sleep(3) driver.quit()
例2:切换ifram和鼠标拖拽
import time from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(20) try: # 切换iframe和拖拽 driver.get("https://jqueryui.com/droppable/") driver.switch_to.frame(driver.find_element_by_tag_name("iframe")) # 页面只有1个iframe,就这样写 t1 = driver.find_element_by_id("draggable") t2 = driver.find_element_by_id("droppable") from selenium.webdriver import ActionChains ActionChains(driver).drag_and_drop(t1, t2).perform() time.sleep(2) driver.switch_to.default_content() #切换出来 driver.find_element_by_link_text("jQuery UI").click() except Exception as er: print(er) finally: # 关闭浏览器 time.sleep(3) driver.quit()
截图
截取当前可见页面的图
import time from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.baidu.com") time.sleep(2) # 截取当前可见页面的图 driver.save_screenshot("a.png") # 保存当前url页面屏幕截图,保存图片的类型必须是.png,命名a.png的图片 driver.quit()
截取指定区域图
方法1:利用--->from PIL import Image
需求:只截取验证码图片的大小,保存当前目录下命名b.png
步骤:先截取当前可见区域的图片,保存在当前目录下命名a.png
利用你Image再次截取a.png中验证码区域的图片,保存在当前目录下命名b.png
import time from PIL import Image # pillow模块这样导入 from selenium import webdriver full_img = "./a.png" code_img = "./b.png" driver = webdriver.Chrome() driver.implicitly_wait(10) driver.maximize_window() driver.get("https://pythonav.com/login/") driver.save_screenshot(full_img) # 截取可见区域的图片 # 需求:只截取验证码图片的大小,保存当前目录下命名b.png imageCode = driver.find_element_by_id("image_code") print(imageCode.size) # {'height': 30, 'width': 120} left = imageCode.location['x'] * 1.28 # 执行当前代码电脑的屏幕的缩放x top = imageCode.location['y'] * 1.26 # 执行当前代码电脑的屏幕的缩放y right = imageCode.size['width'] + left height = imageCode.size['height'] + top temp = Image.open(full_img) temp = temp.crop((left, top, right, height)) temp.save((code_img)) time.sleep(5) driver.quit()
PS:截图不准确时,可以查看自己当前电脑的屏幕缩放然后在x和y处进行相乘。或者将当前电脑的屏幕缩放调整100%即可。
方法2:
需求和方法1是一样:
截取图片验证码,保存在当前目录命名为b.png
import time from selenium import webdriver full_img = "./a.png" code_img = "./b.png" driver = webdriver.Chrome() driver.implicitly_wait(10) driver.maximize_window() driver.get("https://pythonav.com/login/") driver.save_screenshot(full_img) # 截取可见区域的图片 imageCode = driver.find_element_by_id("image_code") imageCode.screenshot(code_img) time.sleep(5) driver.quit()
3、截取整个网页的图
需求:原因:当网页内容过多时,需要通过滚动条下拉查看。如何截取整个网页的图片呢?
通过无头浏览器PhantomJS来截取:
# 网页需要下拉浏览器滚动条才能查看完毕,截取整个长网页的图 from selenium import webdriver driver = webdriver.PhantomJS(executable_path=r"C:\Python\Python37\Scripts\phantomjs\bin\phantomjs.exe") # 无头浏览器安装路径 driver.implicitly_wait(time_to_wait=10) driver.get("https://pythonav.com/project/detail/1/") driver.save_screenshot("a.png") driver.quit()