Selenium 介绍
Selenium 是一个 Web 的自动化测试工具,最初是为网站自动化测试而开发的。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。
它支持所有主流的浏览器(包括 IE、Firefox、Safari、Opera 和 Chrome 等)。可以使用它对浏览器进行各种各样的模拟操作,包括爬取一些网页内容。
支持多种操作系统(包括 Windows、Linux、MAC 等)
环境配置
- 在 Python 环境下安装 Selenium。
- 下载浏览器的 WebDriver。
- 复制 WebDriver 到 python 路径。
本文使用的的环境 浏览器:Google Chrome, python版本:3.8
需要导入的包
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
1)启动 Chrome 浏览器
browser = webdriver.Chrome() # browser 是一个 Chrome.WebDriver 类对象
browser.get('http://www.baidu.com/') # 访问百度
Headless 方式启动
Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。
相比于现代浏览器,Headless Chrome 更加方便测试 web 应用,获得网站的截图,做爬虫抓取信息等。
chrome_options = webdriver.ChromeOptions()
# 增加无界面选项
chrome_options.add_argument('--headless')
# 也可通过如下方式增加无界面选项
# chrome_options.headless = True
# 如果不加这个选项,有时定位会出现问题
chrome_options.add_argument('--disable-gpu')
browser = webdriver.Chrome(options=chrome_options)
browser.get('http://www.baidu.com/')
# 打印网页的标题
print(browser.title) # 百度一下,你就知道
元素定位
某些博主示例使用的方.find_element_by_xxx,但这些方法在新版本的selenium已经弃用(实际还能用),使用时会警告,但为了避免某天真的被弃用,在此介绍新的推荐方法
DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead
通过 id 属性定位 , html 中 id 属性是唯一的
browser = webdriver.Chrome()
browser.get('http://www.baidu.com/')
ele = driver.find_element(By.ID,'kw')
ele.send_keys('python') # 搜索python
在实际定位中,一般有id属性会优先选择id,但是有些id属性是动态id,在每次打开网页时都会改变,这点需要注意
By 类介绍
class By(object):
"""
Set of supported locator strategies.
"""
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
通过 name 属性定位
driver=webdriver.Chrome()
driver.get(r'D:\学习\笔记\python笔记\pages\pages\s1.html') #这里使用的是本地url
eles=driver.find_element(By.NAME,"button")
通过 XPath 定位(XPath是XML文档中查找结点的语法)
先找到网页上定位元素,然后查看并找到元素源代码,右键copy->xpath
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
ele=driver.find_element(By.XPATH,'//*[@id="kw"]') # 单引号里是Xpath
ele.send_keys('python')
通过 class 类名定位元素
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
ele=driver.find_element(By.CLASS_NAME,'mnav')
ele.click() # 点击搜索
由于class属性不唯一,默认只会匹配第一个
还有一点需要注意的是class属性值可能会有多个,多个 class 属性会用空格隔开,如果都写上会报错,因此只能单个寻找
通过link_text定位元素
1.通过完整链接文本定位超链接,如果未定位到超链接或链接文本为子元素会报错
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
#定位不到,不是a标签,而是a标签下的span子标签
whole_link=driver.find_element(By.LINK_TEXT,'为何有人出现“白肺”?专家回应')
whole_link.click()
2.通过模糊匹配定位
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
# 可以定位a标签下的子标签,且模糊匹配文本
part_link=driver.find_element(By.PARTIAL_LINK_TEXT,'白肺')
part_link.click()
本案例是定位百度热搜,由于热搜内容实时更新,所以请读者在试验时自行替换
通过tag_name 标签名定位元素
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
driver.find_element(By.TAG_NAME,'a') #匹配第一个a标签
通过css_selector css选择器定位元素
1.通过class查找 , 一定要写上 .style ,如果只写style会报错
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
driver.find_element(By.CSS_SELECTOR,'.s_ipt').send_keys('python')
2.通过id查找: #idname
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
driver.find_element(By.CSS_SELECTOR,'#kw').send_keys('通过id查找')
3.通过标签查找 : lablename[attributename=value]
driver=webdriver.Chrome()
driver.get('http:www.baidu.com')
driver.find_element(By.CSS_SELECTOR,'input[name="wd"][maxlength="255"]').send_keys('通过标签加多个属性值查找')
selenium 的三种等待方式
为什么要等待,一些博主的解释是: 现在的大多数的 Web 应用程序是使用Ajax技术。当一个页面被加载到浏览器时, 该页面内的元素可以在不同的时间点被加载。
翻译成大白话就是由于你的python程序运行的很快,而网页加载需要一些时间,所以在python程序运行时需要等待网页加载,否则会定位不到元素甚至会抛出异常.
1.强制等待: 使用time.sleep()方法
time.sleep(4) # 睡4秒时间
2.隐式等待: 使用 selenium.webdriver.chrome 对象的 imlicitly_wait() 方法
隐式等待需设置一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则,一直等到时间截止,然后执行下一步.
隐式等待值的设置对 WebDriver 的整个生命周期有效,所以只要设置一次即可,不需要像 time.sleep() 在每个地方都进行设置。
driver.get('http:\\www.baidu.com') # 进入百度
driver.find_element(By.ID,'s-top-loginbtn').click() # 点击登录
driver.implicitly_wait(5) # 设置最长等待时长为5s
隐式等待仍然有一个弊端,那就是程序会一直等待整个页面加载完成,也就是一般情况下浏览器标签栏那个小圈不再转,才会执行下一步。
可能会出现这种情况:个别 js 之类的东西特别慢,即使我们想要定位的元素早就已经加载完成了,程序仍然会继续等待,直到整个页面加载完成或时间截止,然后执行下一步。
3.显式等待: 显式等待是在代码中定义等待一定条件发生后再进一步执行你的代码.
显式等待,可以提高代码运行效率。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
try:
# 判断id值为 TANGRAM__PSP_11__userName 的元素是否被添加在 dom 树里面(并不代表该元素一定可见)
# 间隔 0.5 秒进行一次判断,直到条件成立或超过 6 秒。
element = WebDriverWait(driver, 6).until(EC.presence_of_element_located((By.ID,'TANGRAM__PSP_11__userName')))
# element 是一个webelement对象
element.send_keys('12345678') # 百度账号
print(element.get_attribute('name'))
except Exception:
print('超时')
finally:
driver.quit()
当设置了几种加载方式时,默认以最长等待时间的加载方式为主
更多显示等待方法:
WebDriverWait(WebDriver_instance,timeout,poll_frequency,ignored_exceptions)
# poll_frequency 为调用 until() 或 until_not() 的间隔时间,默认为0.5s
# ignored_exceptions 忽略执行 until() 或 until_not() 的异常, 默认值为 None, 可以设为指定异常名
until(method,message)
# method 参数一定要是可以调用的,使用driver.find_element(By.ID,'kw') 会报错,常用 expected_conditions 模块中的方法
# message 为超时时传给超时异常的参数
# 一些常见 method
# title_is 页面的标题是某内容,返回bool值 EC.title_is('百度一下,你就知道')
# title_contains 页面的标题包含某内容,返回bool值 EC.title_contains('百度')
# url_to_be 当前的 url 是否为指定的内容,返回bool值
# presence_of_element_located 某元素出现在 DOM 树里面(不表示其是可见的),如果存在的话,返回单个 WebElement 对象,否则报错
EC.presence_of_element_located((By.ID,'TANGRAM__PSP_11__userName')) #注意参数为元组
# visibility_of_element_located 常用
# visibility_of_all_elements_located 判断某元素出现在 DOM 树里面,且元素可见,及元素宽高都大于0,如果存在返回对象,否则返回 False
# text_to_be_present_in_element 某个元素文本包含某文字
# element_to_be_clickable 某元素是可见的,并且可点击
# element_to_be_selected 某元素是可选择的
# alert_is_present 出现一个弹框
窗口切换
打开新窗口后句柄仍停留在原来窗口,需要切换到最新窗口
webdriver 提供了如下方法供窗口切换:
# current_window_handle 获取当前窗口的句柄
# window_handles 获取当前会话中所有的窗口句柄,返回的是一个列表
# switch_to.window 切换到指定句柄的窗口
示例:
driver.get('http://www.baidu.com')
home=driver.current_window_handle # 获取当前窗口句柄
driver.find_element(By.ID,'kw').send_keys('python\n') # 搜索框输入python并回车
windows=driver.window_handles # 获取所有窗口句柄
for i in windows:
driver.switch_to.window(i) # 切换到百度首页
if driver.title=='百度一下,你就知道':
break
# """ switch_to.window() 方法的参数为窗口句柄,为 -1 时表示切换到最新窗口 """
其它常见问题:
1.滚动条操作:如果要操作的元素在页面靠下位置,无法定位,就需要先操作滚动条
""" .excute_script() 执行js代码 """
driver.execute_script('window.scrollTo(0,10000)') # 0代表横向滚动,10000代表纵向滚动,滚动到最底部,
# 只要滚动到最底部后便可定位到页面的任何内容
2.关闭辅助搜索框,可以点击其它不会跳转的文本关闭,这里介绍另一种方法
driver.get('https://www.51job.com/')
driver.find_element(By.CSS_SELECTOR,'.more').click()
sleep(0.5)
driver.find_element(By.ID,'kwdselectid').send_keys('python')
sleep(0.5)
driver.execute_script('document.getElementById("KwdSearchResult").style.display="none"') # 把可见元素关掉