Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。
Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。
目前,selenium不再支持phantomjs,虽然还可以用,但还是推荐使用firefox或chrome的无头浏览器配合selenium。
学习环境
python3.6+selenium+firefox
selenium要使用firefox或谷歌浏览器需要使用geckodriver的驱动,贴上百度网盘下载
链接: https://pan.baidu.com/s/1FbaBzz3llsP56tdxT0Ye9Q 提取码: t4w7
下载解压后在环境变量path中添加geckdriver的安装路径
基本使用
from selenium import webdriver
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
browser = webdriver.Firefox() # 通过web驱动声明浏览器对象
try: # 捕捉异常
browser.get('https://www.baidu.com') # 请求的url
inputs = browser.find_element_by_id('kw') # kw是百度的搜索框的id
inputs.send_keys('Python') # 向上面得到的输入框对象发送字符串Python
inputs.send_keys(Keys.ENTER) # 发送回车键
wait = WebDriverWait(browser, 10) # 让驱动等待
wait.until(EC.presence_of_element_located((By.ID, 'content_left'))) # 驱动在上一句设置的10秒内默认每0.5秒调用 一次括号中的方法。
# 输出url,cookie,和页面源代码
print(browser.current_url)
print(browser.get_cookies())
print(browser.page_source)
finally: # 关闭驱动
browser.close()
声明浏览器对象
from selenium import webdriver
# 环境变量设置好geckdriver的路径之后,可以如下声明各浏览器对象,否则就需要在方法内添加executable_path参数,值为geckdriver的安装目录
browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()
查找元素
- 单个元素
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://www.taobao.com')
input_first = browser.find_element_by_id('q')
input_second = browser.find_element_by_css_selector('#q')
input_third = browser.find_element_by_xpath('//*[@id="q"]')
print(input_first, input_second, input_third)
browser.close()
除以上方法外还有
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
等方法,并且
find_element(BY.ID,‘id_name’)方法与以上等效,但需要通过BY指定取的元素的方式
- 多个元素
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://www.taobao.com')
lis = browser.find_elements_by_css_selector('.service-bd li')
print(lis)
browser.close()
其中
browser.find_elements_by_css_selector(’.service-bd li’)
也可以用
browser.find_elements(By.CSS_SELECTOR, ‘.service-bd li’)
代替
取多个元素的方法还有以下
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
元素交互操作
from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('iPhone')
time.sleep(1) # 休眠进程1秒
input.clear()
input.send_keys('iPad')
button = browser.find_element_by_class_name('btn-search')
button.click()
交互动作
from selenium import webdriver
from selenium.webdriver import ActionChains
browser = webdriver.Firefox()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
actions.drag_and_drop(source, target)
actions.perform()
ActionChains是动作链:有些时候,我们需要再页面上模拟一些鼠标操作,比如双击、右击、拖拽甚至按住不动等,我们就可以通过导入 ActionChains 类来做到这一点;
关于switch_to:用于定位,可以是定位到另一个页面,或者定位到一个页面中的frame中 driver.switch_to.window(window_name): 切换到制定的window_name页面
driver.switch_to.alert() : 切换到alert弹窗
driver.switch_to.active_element() : 定位到当前聚焦的元素上
driver.switch_to.default_content() : 切换到最上层页面(主文档?)
driver.switch_to.frame(frame_reference) : 通过id、name、element(定位的某个元素)、索引来切换到某个framedriver.switch_to.parent_frame() : 切换到上一层的frame,对于层层嵌套的frame很有用
执行JavaScript
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
获取元素信息
- 获取属性
from selenium import webdriver
from selenium.webdriver import ActionChains
browser = webdriver.Firefox()
url = 'https://www.zhihu.com/explore'
browser.get(url)
logo = browser.find_element_by_id('zh-top-link-logo')
print(logo) # 打印该元素
print(logo.get_attribute('class')) # 取得class 的值并打印
- 获取文本值
from selenium import webdriver
browser = webdriver.Firefox()
url = 'https://www.zhihu.com/explore'
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question')
print(input.text)
- 获取ID、位置、标签吗、大小
from selenium import webdriver
browser = webdriver.Firefox()
url = 'https://www.zhihu.com/explore'
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question')
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)
等待
- 隐式等待
from selenium import webdriver
browser = webdriver.Firefox()
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常, 换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0
- 显式等待
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
browser = webdriver.Firefox()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
title = EC.title_is('淘宝')
title2 = EC.title_contains('淘宝')
print(input, button)
print(title(browser),"----",title2(browser))
结果为:
<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="0b20f97a-c408-4add-9be6-3ccd939485e2", element="7181a6df-4acd-4ddc-bf3c-0448574e7469")> <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="0b20f97a-c408-4add-9be6-3ccd939485e2", element="1dfa7365-021f-4376-aa9b-2baa265fe01f")>
False ---- True
EC中的方法
title_is 标题是某内容
title_contains 标题包含某内容
presence_of_element_located 元素加载出,传入定位元组,如(By.ID, ‘p’)
visibility_of_element_located 元素可见,传入定位元组
visibility_of 可见,传入元素对象
presence_of_all_elements_located 所有元素加载出
text_to_be_present_in_element 某个元素文本包含某文字
text_to_be_present_in_element_value 某个元素值包含某文字
frame_to_be_available_and_switch_to_it frame加载并切换
invisibility_of_element_located 元素不可见
element_to_be_clickable 元素可点击
staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新
element_to_be_selected 元素可选择,传元素对象
element_located_to_be_selected 元素可选择,传入定位元组
element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False
element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False
alert_is_present 是否出现Alert
前进后退
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(1)
browser.forward()
browser.close()
相当于浏览器中中的前进和后退
Cookies
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies()) 取得cookies
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'}) 添加cookies
print(browser.get_cookies())
browser.delete_all_cookies() 删除cookies
print(browser.get_cookies())