Shell操作
- 从虚拟环境启动IDLE:
python -m idlelib.idle
- 启动Chrome:
driver = webdriver.Chrome(r'D:\Google\Chrome\Application\chromedriver.exe')
元素选择
选择元素方法
id
# 返回一个WebElement对象
element = driver.find_element_by_id('wd')
element.send_keys('Unity\n') # 输入字符串,不要忘记回车
class
# 返回【第一个】找到的WebElement对象
# 找不到,抛出异常
driver.find_element_by_class_name('wd')
# 返回所有WebElement对象组成的【列表】
# 找不到,返回空列表[]
driver.find_elements_by_class_name('wd')
tag标签名
# 选择第一个
driver.find_element_by_tag_name('wd')
# 选择列表
driver.find_elements_by_tag_name('wd')
css
# 选择第一个
driver.find_element_by_css_selector(选择器)
# 选择列表
driver.find_elements_by_css_selector(选择器)
超链接文本
# 选择第一个
driver.find_element_by_link_text(text) # a标签的文字必须是text
driver.find_element_by_partial_link_text(text) # a标签的文字含有text
# 选择列表
driver.find_elements_by_link_text(text) # a标签的文字必须是text
driver.find_elements_by_partial_link_text(text) # a标签的文字含有text
name属性
# 选择第一个
driver.find_element_by_name(val)
# 选择列表
driver.find_elements_by_name(val)
选择语法
Xpath
-
选取包含某个属性的标签:
//div[@class] #选取包含class属性的div标签。
-
属性值包含字符串:
- 通配:
//*[contains(@class,'big')] #class属性值包含'big'的所有标签
- 以…开头:
//*[starts-with(@class,'big')] #class属性值以'big'开头的所有标签
- 以…结束:【没有】!!
- 通配:
-
按序号选取last():
- 序号:
//p[2] #从1开始,所以这是第1个
- 倒数:
//p[last()] #最后一个 //p[last()-1] #倒数第二个...以此类推...
- 序号:
-
范围选择:
#选取a的前两个元素 //a[position()<=2] //a[position()<3]: #选取a的最后3个元素 //a[position()>=last()-2] //a[position()>last()-3]:
-
选择多个:
#选择class属性值为'a'或'b'的div标签 //div[@class='a'] | //div[@class='b']
-
关系节点:
- 父节点:
../
- 当前节点:
./
- 注意:
find_element_by_xpath
找到之后还可以对WebElement对象再进行xpath寻找时就必须使用当前节点。
- 注意:
- 后面兄弟节点:
#选择class="ww"的元素的所有后续兄弟节点 //*[@class="ww"]/following-sibling::*
- 前边兄弟节点(css选择器没有):
#选择class="ww"的元素的所有前边兄弟节点 //*[@class="ww"]/preceding-sibling::*
- 父节点:
CSS选择器
- 选取属性包含某…的标签:
a[href*="baidu"] #选取href属性中含有"baidu"的a标签。
- 选取属性包含以某…开头的标签:
a[href$="https://"] #选取href属性开头是"https://"的a标签
- 选取属性包含以某…结束的标签:
a[href^=".cn"] #选取href属性中末尾是".cn"的a标签。
- 属性:“[属性=‘属性值’]”
a[href="www.baidu.com"] #选择href属性是"www.baidu.com"的a标签
- 按标签正索引:
:nth-child(n) #第n个节点 :nth-child(even) #偶数节点
- 按标签负索引:
:nth-last-child(n) #倒数第n个节点
- 按类型正索引:
:nth-of-type() #选择的元素是父元素的第几个某类型的子节点
- 按类型负索引:
:nth-last-of-type() #选择的元素是父元素的倒数第几个某类型的子节点
- 兄弟节点:
"元素0+元素1" #如h3和span并列,选取的话就是'h3+span' "元素0~元素1" #选取元素0后面和元素0同级的所有元素1.
元素操控
浏览器操作
属性
driver.title
:页面标题Title。driver.current_url
:当前的url。driver.page_source
: 网页源码。
方法
-
窗口大小:
- 指定宽高:
driver.set_window_size(W,H)
- 最大化:
driver.maximize_window()
- 指定宽高:
-
访问url:
driver.get(url)
-
前进后退:
- 前进:
driver.forward()
- 后退:
driver.back()
- 前进:
-
刷新:
driver.refresh()
-
关闭:
- 退出驱动并关闭所有关联窗口:
driver.quit()
- 关闭当前控制窗口:
driver.close()
,【基本不用】
- 退出驱动并关闭所有关联窗口:
-
保存截图:
driver.save_screenshot('xxx.png')
- 仅支持
.png
格式的图片
- 仅支持
-
执行JS脚本:
driver.execute_script(script)
#下拉到页面底部 driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
-
cookie操作:
- 添加:
driver.add_cookies(['name':name,'value':val])
- 获取所有:
driver.get_cookies()
- 返回值:列标签套字典
[{...},{...},{...}]
- 返回值:列标签套字典
- 根据key获取某个:
driver.get_cookie(key)
- 删除所有:
driver.delete_cookie(key)
- 根据key删除某个:
driver.delete_all_cookies()
- 添加:
网页元素操作
属性
ele.text
:两个标签中间的文字。ele.size
:元素大小
方法
ele.send_keys(keywords)
:给输入框输入字符串。ele.click()
:点击找到的元素。ele.clear()
:清除输入框内容。ele.submit()
:提交表单。ele.is_display()
:元素是否可见。ele.is_enabled()
:元素是否可用。ele.get_attribte(attr)
:获取元素属性。属性值如下:outerHTML
:获取整个元素对应的html,即一对标签的中间内容。innerHTML
:获取某个元素内部的html文本。value
:获取输入框里已输入文字。innerText
:text只获取展示到界面上的文字,而有些没有展示的想要获取到应该是用这个方法
事件
鼠标事件
模块:
from selenium.webdriver.common.action_chains import ActionChains
生成行为:ActionChains(driver)
执行行为:perform()
例子:
#鼠标移动到元素
ActionChains(driver).move_to_element(ele).perform()
行为:
context_click(ele)
:右击。double_click(ele)
:双击。drag_and_drop(ele0,ele1)
:拖动ele0到ele1的位置。drag_and_drop_by_offset(ele,x,y)
:元素ele拖动到指定坐标(x,y)move_to_element(ele)
:鼠标悬停在元素上。click_and_hold(ele)
:按下鼠标左键在元素上。
键盘事件
模块:
from selenium.webdriver.common.keys import Keys
方法:
ele.send_keys(Keys.BACKSPACE)
:按下退格,即删除一个send_keys()的字符。ele.send_keys(Keys.ENTER)
:按下回车。ele.send_keys(Keys.F1)
:按下F1。ele.send_keys(Keys.TAB)
:按下Tab。ele.send_keys(Keys.SPACE)
:按下空格。ele.send_keys(Keys.CONTROL,'a')
:按下’Ctrl+A’,即全选操作。ele.send_keys(Keys.CONTROL,'c')
:按下’Ctrl+C’,即复制操作。ele.send_keys(Keys.CONTROL,'v')
:按下’Ctrl+V’,即粘贴操作。ele.send_keys(Keys.CONTROL,'x')
:按下’Ctrl+X’,即剪贴操作。
JS执行事件
滚动条事件:
- 滚动到底部:
driver.execute_script(window.scrollTo(0,document.body.offsetHeight))
- 置顶:
driver.execute_script(window.scrollTo(0,0))
聚焦到元素:
#将滚动条滚动到目标元素位置
driver.execute_script('arguments[0].scrollIntoView();',ele)
信息对话框的关闭:
driver.execute_script('doucment.getElementById(id).style.display="none";')
特殊操作
隐式等待
-
以下代码可能会报错:
driver = webdriver.Chrome() driver.get('https://www.baidu.com') element = driver.find_element_by_id('kw') element.send_keys('北方工业大学\n') elements = driver.find_elements_by_tag_name('a') for e in elements: print(element.text)
-
原因:请求服务器并返回数据需要时间,在空白页面寻找元素当然找不到
-
解决方案:
-
利用time模块进行
sleep()
操作。 -
selenium方案:当发现元素未找到时,并不立即报错,而是周期性(每隔0.5s)
重新寻找该元素,直到找到或超过最大等待时长才抛出异常或返回空列表。
其中,使用方法driver.implicitly_wait(10)
设置最大等待时长(一般5-10s)。- 语法:
driver.implicitly_wait(time)
- 范围:影响范围为【整个页面】,此方法可影响所有"find_element?_by???"。
- 语法:
-
-
异常捕获—一般为超时错误:
try: driver.find_element_by_id() except Exception as e: print('未找到元素!'+e)
显示等待
-
模块:
from selenium.webdriver.support.wait import WebDriverWait
-
方法:
WebDriverWait(driver,timeout,poll_frequency=0.5).until(method)
-
参数:
timeout
:最大等待时间poll_frequency
: 轮询时间,默认0.5s
method
:传入一个方法,一般都是lambda表达式
-
例子:
WebDriverWait(driver,10).until(lambda x:x.find_element_by_id('kw'))
-
注意:
unitl_not
()和until()
一摸一样,区别是:.until()
是当某元素出现或什么条件成立继续执行。.until_not()
是当元素消失或什么条件不成立时执行。
- 范围: 显示等待的范围是【某一元素】,而不是整个网页。
窗口切换
当脚本控制切换到另一个页面时,当前代码控制的页面不是弹出的新页面,而是原来的页面。
语法:driver.switch_to.window(handle)
-
其中,对handle的传入方案如下:WebDriver对象有window_handles属性,这是一个列表,里面包括了浏览器所有的窗口句柄。例如:
for handle in driver.window_handles: driver.switch_to.window(handle) if 'ncut' in driver.title: break #如果找到了新的窗口,就跳出循环
注意:
- 如果想要再次切回原窗口,有两种方案:
- 在for循环之前用一个变量保存原窗口,即
origin_handle = driver.current_window_handle driver.switch_to.window(origin_handle) #切换回去
- 依然使用for循环以同样的方法break
- 在for循环之前用一个变量保存原窗口,即
- 当前窗口句柄:
driver.current_window_handle
iframe操作
方法:
driver.switch_to.iframe(arg)
: 切换到某一iframe- 参数
arg
: frame元素的name
或id
属性
- 参数
driver.switch_to.parent_frame()
:返回上一层iframedriver.switch_to.default_content()
:回到主html。
注意:
- 若frame无name和id,可以传入WebElement对象,比如:
driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))
- 若代码中写了这个,那么后续的操作都是对iframe里面的html进行的,
要想再转回底层html,使用driver.switch_to.default_content()
- 若页面只有一个iframe,则
parent_frame()
和default_content()
是等效
选择框
单选框
- 点击(选取):WebElement的
ele.click()
- 获取文本:
ele.get_attribte('value')
复选框
- 点击:
ele.click()
- 获取文本:
ele.get_attribte('value')
- 判断是否选中:
ele.is_selected()
- 注意:这里点击和选中不是等效,只有当原来的box未被选中时"点击=选中",
但如果原来被选中了,再次执行click()会取消选中。解决方案如下for ele in eles: #遍历所有选项 if not ele.is_selected(): #如果未被选中 ele.click() #点击一下
下拉菜单
- 模块:
from selenium.webdriver.support.select import Select
- 初始化:
select = Select(ele)
- 方法:
select.select_by_value(val)
:根据value属性值选择select.select_by_index(i)
:根据索引。select.select_by_visible_text(text)
:根据选项可见文本(尖括号之间的内容)select.deselect_by_value(val)
:根据value属性值取消select.deselect_by_index(i)
:根据【从0开始】的索引取消select.deselect_by_visible_text(text)
:根据可见文本取消sel.deselect_all()
:去除选中所有元素,一般用于checkbox先清除所有,再选中
冻结界面
- 操作:在开发者工具界面的console里输入以下js代码:
setTimeout(function(){debugger},5000)
- 分析:在5s之后,执行debugger命令,此时界面就会被’冻住’。
弹窗操作
- alert:
- 点击OK:
driver.switch_to.alert.accept()
- 获取对话框信息:
driver.switch_to.alert.text
- 点击OK:
- confirm:
- 点击OK:
driver.switch_to.alert.accept()
- 点击Cancel:
driver.switch_to.alert.dismiss()
- 获取对话框信息:
driver.switch_to.alert.text
- 点击OK:
- prompt:
- 输入内容:
driver.switch_to.alert.send_keys()
- 点击OK:
driver.switch_to.alert.accept()
- 点击Cancel:
driver.switch_to.alert.dismiss()
- 获取对话框信息:
driver.switch_to.alert.text
- 输入内容:
文件上传
- 语法:
ele.send_keys(path)
- 参数
path
: 传入文件的【绝对路径】
- 参数
- 注意:
- 基本都是针对
<input type="file">
的表单有效。 - 如果不是input的上传文件,可使用
SendKeys
库,不过基本用不到。
- 基本都是针对
验证码问题
利用cookie改变登陆状态来解决。
- 获取登陆后的cookie:
cookies = [{'name':n1,'value':v1},{'name':n2,'value':v2}]
- 添加cookies(如果有多个,循环添加):
for cookie in cookies: driver.add_cookie(cookie)
- 刷新页面:
driver.refresh()
- 完成!
EC模块
判断元素是否存在、可点击。
-
模块:
from selenium.webdriver.support import expected_conditions as EC
-
方法:
- title_is(text):判断网页Title是否等于text
- title_contains(text):Title是否包含text
- presence_of_element_located(locator):元素是否存在于页面中。
如果存在,返回元素本身,不存在报错。 - visibility_of_element_located(locator):判断元素是否存在且可见(宽高>0)。
如果存在返回元素本身,不存在返回False。 - visibility_of(ele):和上面一样,只是参数为元素。
- presence_of_all_elements_located(locater):和(2)一样,只是判断多个。
- text_to_be_present_in_element(locater,text):元素是否包含text。
- text_to_be_present_in_element_value(locater,text):元素value值包含text。
-
参数
locator
:- 元组
(by,val)
,by
是selenium.webdriver.common.by.By
。 by
类包括:CLASS_NAME``CSS_SELECTOR
,ID
,LINK_TEXT
,NAME
,
PARTIAL_LINK_TEXT
,TAG_NAME
,XPATH
。- 但一般用小写字符串即可,如
("class name","dv")
,("id","kw")
- 元组
-
注意:一般配合
WebDriverWait
显式等待模块使用WebDriverWait(driver,10).until(EC.方法)
配置加载项
user_data_dir = r'--user-resource-dir=C:\Users\林在超\AppData\Local\Google\Chrome\User Data'
options = webdriver.ChromeOptions()
options.add_argument(user_data_dir)
driver = webdriver.Chrome(options=options)