安装配置教程自行搜索
所用驱动chromedriver应与chrome浏览器版本相对应
pip install selenium
笔者selenium所用版本为4.11.2,新旧版之间会有差别
from selenium import webdriver
driver = webdriver.Chrome()
实例化driver对象后,driver对象有一些常用的属性和方法
driver.page_source #当前标签页浏览器渲染之后的网页源代码
driver.current_url #当前标签页的url
driver.close() #关闭当前标签页,如果只有一个标签页则关闭整个浏览器
driver.quit() #关闭浏览器
driver.forward() #页面前进
driver.back() #页面后退
driver.refrash() #页面刷新
driver.save_screenshot("img_name") #页面截图
我们使用Selenium时会觉得浏览器加载很慢,这和它的页面加载策略有关
Selenium的页面加载策略(pageLoadStrategy)
本段摘自:https://blog.csdn.net/momoda118/article/details/120624777
- normal:等待整个页面加载完毕再开始执行操作(默认为此)
- eager:等待整个dom树加载完成,即DOMContentLoaded这个事件完成,也就是只要 HTML完全加载和解析完毕就开始执行操作。放弃等待图片、样式、子帧的加载。
- none:等待html下载完成,哪怕还没开始解析就开始执行操作。
加载策略设置为eager
配置代码如下:
chrome_options = Options()
chrome_options.page_load_strategy = 'eager'
driver = webdriver.Chrome(options=chrome_options)
加载策略设置为none
加载策略设置为none,并引入retry做重试(目的是为了防止报错,当然设置隐式等待也可,但没retry稳妥)可以只用2s左右就能执行完成,完整代码如下:
import datetime
from retrying import retry # 需第三方库,需pip进行安装
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By@retry(wait_fixed=10, stop_max_attempt_number=1)
def click(path):driver.find_element(By.XPATH, path).click()chrome_options = Options()
chrome_options.page_load_strategy = 'none'
driver = webdriver.Chrome(options=chrome_options)
start_time = datetime.datetime.now()
driver.get('https://www.iqiyi.com/')
click('//*[@id="block-C"]/div/div/div/div[1]/div[1]/div/div[1]/div/div/a/span[2]')
end_time = datetime.datetime.now()
print(end_time - start_time)
元素定位
本段参考:https://blog.csdn.net/qq_18298049/article/details/117136214
element = driver.find_element(By.ID, 'kw') # 通过ID定位搜索框element = driver.find_element(By.NAME, 'wd') # 通过name定位搜索框element = driver.find_element(By.CLASS_NAME, 's_ipt') # 获取百度首页搜索框element = driver.find_element(By.TAG_NAME, 'input') # 查找标签名称是input的元素element = driver.find_element(By.LINK_TEXT, '贴吧') # 定位贴吧element = driver.find_element(By.PARTIAL_LINK_TEXT, '贴') # 定位贴吧
头尾匹配写法:其中,头尾匹配可以是部分字符,部分匹配需要是按空格分隔的完整字符。
条件 | html | values 写法1 (头部匹配) | values 写法2 (尾部匹配) | values 写法3 (部分匹配) |
---|---|---|---|---|
class | < button class=“el-button el-button–primary”> | ‘[class^=“el-button”]’ | ‘[class$=“–primary”]’ | ‘[class~=“el-button”]’ |
css selector
element = driver.find_element(By.CSS_SELECTOR, '#kw') # #kw id选择器
element = driver.find_element(By.CSS_SELECTOR, '.s_ipt') # .s_ipt class选择器
element = driver.find_element(By.CSS_SELECTOR, 'form #kw') # 后代元素选择器
element = driver.find_element(By.CSS_SELECTOR, "input[name='wd']") # 属性值定位选择器# 同时包含两个条件
# 包含type='text'与maxlength='50'两个条件的元素,语法上不需要and进行连接
driver.find_element(By.CSS_SELECTOR, '[type="text"][maxlength="50"]')
# 包含一个条件且不包含另一条件
# 包含type='text'且不包含maxlength='50'的元素,语法上使用:not()进行连接
driver.find_element(By.CSS_SELECTOR, '[type="text"]:not([maxlength="50"])')
xpath
相对路径
// #查找页面根元素
//input #查找页面上所有的input元素
//form[1]/input #查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝对路径表示,单/号)
//form[1]//input #查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)
//form[1] #查找页面上第一个form元素
//form[@id='loginForm'] #查找页面上id为loginForm的form元素
//input[@name='username'] #查找页面上具有name属性为username的input元素
//form[@id='loginForm']/input[1] #查找页面上id为loginForm的form元素下的第一个input元素
//input[@name='continue'][@type='button'] #查找页面具有name属性为contiune并且type属性为button的input元素
//form[@id='loginForm']/input[4] #查找页面上id为loginForm的form元素下第4个input元素
写法为:element = driver.find_element(By.XPATH, '路径')
绝对路径
调试模式找到元素右键复制
不建议写绝对路径!!!
定位模糊匹配
contains关键字://a[contains(@href, ‘logout’)]
寻找页面中href属性值包含有logout这个单词的所有a元素
start-with关键字://a[starts-with(@name, ‘start)])
寻找name属性以start开头的a元素。其中@后面的name可以替换成元素的任意其他属性
text关键字://*[text()=’确定’]
一个简单粗暴的定位方式,无需知道属于什么标签元素,常用于纯文字查找,也可用于链接元素文本查找
//a[contains(text(), ’退出’)]
用于知道超链接上显示的部分或全部文本信息时
find_element和find_elements:
- find_element返回匹配到的第一个标签对象;find_elements返回列表
- find_element匹配不到抛出异常;find_elements匹配不到返回空列表
元素操作
示例1:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import timechrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
driver.find_element(By.ID, 'kw').send_keys('python')
driver.find_element(By.ID, 'su').click()
time.sleep(5)
driver.close()
示例2:
el_list: list = driver.find_elements(By.XPATH, "/html/body/div[6]/div[2]/ul/li/div[2]/h2/a")
for el in el_list:print(el.text)print(el.get_attribute('href'))
标签页(窗口)切换
我们在使用浏览器的时候,会自动转到新的标签页,但selenium不会这样,我们需要进行操作来实现
利用窗口句柄切(指向标签页对象的标识)换到句柄指向的标签页
driver.get("url")
time.sleep(3)
print(driver.current_url) #获取当前页面的url
print(driver.window_handles) #获取当前所有存在的窗口句柄,多个句柄以列表方式存储
driver.find_element(By.XPATH, "/html/body/div[6]/div[2]/ul/li[1]/div[2]/h2").click()
print(driver.current_url)
print(driver.window_handles)
time.sleep(3)
driver.switch_to.window(driver.window_handles[-1]) #切换至新窗口
print(driver.current_url)
time.sleep(3)
driver.close() #关闭当前窗口
driver.switch_to.window(driver.window_handles[0]) #切换至原窗口
print(driver.current_url)
iframe切换
<iframe src="1.html" id="hogwarts_id" name="hogwarts_name"></iframe>
实现:
# index:传入整型的参数,从 0 开始,这里的 0 就是第一个 frame
driver.switch_to.frame(0)
#id:iframe 的 id
driver.switch_to.frame("hogwarts_id")
#name: iframe 的 name
driver.switch_to.frame("hogwarts_name")
#WebElement: 传入 `selenium.webelement` 对象
driver.switch_to.frame(driver.find_element(By.TAG_NAME,"iframe"))
在切换页面之后,如果还想操作原页面,则可以使用:
driver.switch_to.default_content()
嵌套多层iframe的切换:
<html><iframe src="a.html" id="frame1"><iframe src="b.html" id="frame2" ><input id="kw" / ></iframe></iframe>
</html>
多层嵌套的情况下,如果要从主界面切换到第二层iframe,则需要一层一层的切换进去,即先切换到frame1,再切换到frame2,而不是直接切换进入frame2
driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")
selenium还提供了一个切换到父frame的方法,比如我们切换到frame2之后,要想切换到frame1操作,则不需要先切回主界面再切换到frame,而是使用如下方法:
driver.switch_to.parent_frame()
需要注意的是,如果当前已经是主页面,则使用此方法无效
cookies操作
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import timechrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
#print(driver.get_cookies())
#转换为字典格式
cookies = {}
for data in driver.get_cookies():cookies[data['name']] = data['value']
#字典推导式
cookies1= {data['name']: data['value']for data in driver.get_cookies()}
print(cookies)
print(cookies1)
driver.delete_cookie('CookieName') #删除一条cookie
driver.delete_all_cookies() #删除所有cookie
页面等待
强制等待
time.sleep()
缺点:不智能:设置的时间短,元素还没有加载出来;设置的时间长,则会浪费时间
隐式等待
隐式等待针对的是元素定位(设置一次,所有元素定位都会按照设定),隐式等待设置了一个时间,在一段时间内判断元素是否定位成功,如果完成了,就进行下一步;如果在设置的时间内没有定位成功,则会报超时加载
#隐式等待
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import timechrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')driver = webdriver.Chrome(service=service, options=chrome_options)
driver.implicitly_wait(5) #设置隐式等待时间为5秒
driver.get("https://www.baidu.com")
driver.find_element(By.ID, 'kkww') #5秒钟内定位不到元素,报错
显式等待
明确等待某一个元素
每经过多少秒就查看一次等待条件是否达成,如果达成就停止等待,继续执行后续代码;如果没有达成就继续等待直到超过规定的时间后报超时异常
多用于软件测试,想要了解请自行查找
Chrome无界面模式
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import timechrome_options = Options()
chrome_options.page_load_strategy = 'eager'
service = Service('chromedriver.exe路径')
chrome_options.add_argument("--headless") #添加开启无界面模式的命令
chrome_options.add_argument("--disable-gpu") #添加开启禁用gpu的命令driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get("https://www.baidu.com")
driver.save_screenshot('baidu.png')
配置代理:chrome_options.add_argument("--proxy-server=http://113.254.44.242:8382")
注意:更换ip代理必须重启浏览器
配饰UserAgent:``chrome_options.add_argument(“–user-agent=XXXX”)`