(一)判断元素是否存在
self.driver.find_element(By.ID, 'name').size != 0
(二)智能延时/等待指定节点加载
当需要获取的元素节点是由 JavaScript
动态生成时,需要让获取节点的代码“等一等”再运行
通过 time.sleep(5)这种方式,当需要等待网络请求比较多时,会导致完成一次运行需要等待很久,如下是一些代码及使用场景
每次点击事件后都应该添加智能延时代码,它会等待时间为0~5秒
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.get("http://www.example.com/")
driver.find_element(By.ID, "submit").click()
driver.implicitly_wait(5)
一般来讲,稍稍设置大一些的等待时间即可加载出相应节点的数据,有一种更为确定的方法,可以在指定的时间内等待,直到我们需要的节点加载出来,相比于 implicitly_wait
它更加的精确,节省时间,因为它不必等待我们不关心的节点加载
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
driver = webdriver.Firefox()
driver.get("http://www.example.com/")
wait = WebDriverWait(self.driver, 10)
wait.until(
EC.presence_of_element_located((By.ID, "submit"))
).click()
如上的写法是针对于获取到节点就点击的,如果一个登陆表单时动态加载的,并且里面的元素也是动态加载的,那么首先需要先获取登陆表单,然后在表单的基础上再选择节点,示例代码段如下
# 等待登录页加载完成
wait = WebDriverWait(driver, WAIT_TIME)
formElement = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".sign-in-form"))
)
# 填写邮箱与密码登陆
emailElement = formElement.find_element(By.ID, 'email')
emailElement.send_keys(username)
passwordEmement = formElement.find_element(By.ID, 'password')
passwordEmement.send_keys(password)
# 点击登陆
formElement.find_element(By.CSS_SELECTOR, '[type="button"]').click()
driver.implicitly_wait(WAIT_TIME)
(三)元素个数(Elements Counts)
一些情况下,获取元素下子节点的数量有助于帮助程序判断节点的状态,简化代码,而且有时数量信息也是很重要的数据
counts = self.driver.find_elements(By.CLASS_NAME, 'img')
print len(counts)
为了这个问题,我Google了有一会,有说需要使用xpath才能返回列表的,有的是java的代码,尝试好久,最后我才在一个问题下边猛然的发现我的方法少了一个s
,是find_elements_by_xxx()
而不是find_element_by_xxx()
(四)处理iframe的情况
driver.switch_to_frame(self, frame_reference) 这个方法已经废弃
新的函数如下:
def frame_switch(css_selector):
driver.switch_to.frame(driver.find_element_by_css_selector(css_selector))
def frame_switch(name):
driver.switch_to.frame(driver.find_element_by_name(name))
处理完iframe,回到之前的界面
driver.switch_to.default_content()
(五)Firefox与Chrome的driver差异
当写完Login()函数后,加载其它函数,比如或许用户详情页的时候,Firefox Driver或自动带上Cookies,Chrome Driver 不会自动加载Cookies,所以使用Chrome比Firefox需要多两行代码,手动加载Cookies
# 登陆后获取cookies
cookies = driver.get_cookies()
# 在加载新的页面后倒入Cookies
for cookie in cookies:
driver.add_cookie(cookie)
如果有些网站的Cookies有效期很长,那么可以将Cookies保存到文件
# 保存Cookies到文件
import pickle
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get("http://www.google.com")
pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
# 从文件加载Cookies
import pickle
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get("http://www.google.com")
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
(六)滚动加载
有些数据一页展示不完,当侧边栏向下拉或者鼠标滚动的时候才会继续加载数据,这种模式在瀑布流的图片展示站点非常常见,不过也很好解决
# 回到顶部
js="var q=document.body.scrollTop=0"
driver.execute_script(js)
# 拉到底部
js="var q=document.body.scrollTop=10000"
driver.execute_script(js)
在网上搜索的时候有这样的写法document.documentElement.scrollTop=10000
,我在测试的时候发现body的写法是工作的,这可能跟网站/浏览器 有一定关系,在测试的时候哪种能工作就用哪种吧