python - selenium模块简介

为什么要使用Selenium?

很多浏览器渲染页面的方式都很难找出其规律, 但是利用Selenium来驱动加载网页就可以直接拿到javaScript渲染后的结果了, 不需要再担心其相关的加密系统


声明浏览器对象

from selenium import webdriver
browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()

访问页面 -> get()

browser.get("页面网址")
print(browser.page_source())
browser.close()

获取单个节点 -> find_element() [只能获取单个节点]

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)

更通用的方式 -> find_element()

  • 传入两个参数: 查找方式By和值
from selenium import webdriver
from selenium.webdriver.common.by import By

# 两者完全一致
browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
input_first = browser.find_element(By.ID, 'q')
input_afirst = browser.find_element_by_id('q')
print(input_first)
print(input_afirst)
browser.close()

获取多个节点

在楼上的基础上, 每一个element后面都跟上一个s
eg:
find_elements_by_id()
find_elements()


节点交互

  1. 输入文字 -> send_keys()
  2. 清空文字 -> clear()
  3. 点击按钮 -> click()

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
input = browser.find_element_by_id('q')
# send_keys() -> 输入文字
input.send_keys('iPhone')
time.sleep(1)
# 清空输入的文字
input.clear()
input.send_keys('iPad')
button = browser.find_element_by_class_name('btn-search')
button.click()

动作链 -> ActionChain()

比如: 鼠标的拖拽、键盘按键等等

browser = webdriver.Chrome()
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)
# .drag_and_drop()方法指定要拖拽的节点和拖拽的目标结点
actions.drag_and_drop(source, target)
# perform()方法才是真正的执行动作
actions.perform()

JavaScript -> execute_script('执行js代码')

模拟下拉进度条

browser = webdriver.Chrome()
url = 'https://www.zhihu.com/explore'
browser.get(url)
# 利用execute_script('执行相关的js代码')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')

获取节点信息

  1. 获取属性 -> get_attribute()
  2. 获取文本值 -> text()
  3. 获取其他属性 -> 获取id(id) / 位置(location) / 标签名(tag_name) / 大小(size), 直接使用对应的属性即可

切换Frame

Iframe就是子Frame, 相当于页面的子页面
Selenium打开页面后, 默认是在父级的Frame里面操作, 如果此时页面中还有子Frame是获取不到子Frame中的节点的, 所以就使用switch_to.frame()方法来切换Frame

browser = webdriver.Chrome()
url = 'http://runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
# 切换frame, 同时页面中iframe的id为iframeResult
browser.switch_to.frame('iframeResult')
try:
    logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
    print('NO LOGO')
# 再次切换到父级的frame中去
browser.switch_to.parent_frame()
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)

当页面中包含子Frame时, 如果想要获取子Frame中的节点的时候, 首先需要调用switch_to.frame('iframe的id名'), 再进行相应的操作的.

想要再次切换回原始的父级Frame使用 -> browser.switch_to.parent_frame()


延时等待

selenium中, get()方法会在网页框架结束后结束执行, 此时去获取page_source可能并不是浏览器完全加载完成出来的页面, 如果某些页面有额外的Ajax请求, 在网页的源代码中也不一定能成功获取到. 所以需要延时等待一定时间, 确保节点以及被加载出来了.

等待分为两种:

  1. 隐式等待
  2. 显示等待
隐式等待

使用隐式等待, 则selenium在DOM中找到节点时, 将会继续进行等待, 等待一段时间后在查找DOM, 直到超出设定的时间.

browser.implicitly_wait(10)
显式等待

隐式等待, 我们只能固定等待时间, 但是页面的加载时受到网络影响的, 所以其实效果并不太好.

显式等待:
指定要查找的结点, 然后指定一个最长的等待时间\(^{1}\)和等待条件\(^{2}\), 如果到了规定时间仍没有加载出该节点就抛出超时异常.
(这和隐式等待有什么区别...?)

# 显示等待主要用到的是这几个
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC


browser = webdriver.Chrome()
browser.get("https://www.taobao.com/")
# 设定等待时间
wait = WebDriverWait(browser, 10)
# 调用until()方法
# EC.presence_of_element_located()表示节点出现 -> 内部是元组类型
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
# element_to_be_clickable就是可点击
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
等待条件

image.png
image.png

显隐对比
显式 隐式
等到某种等待条件出现, 如果超出设定时间仍未出险, 则抛出异常 如果在DOM找不到元素, 则在隐式等待期间内, 每隔一段时间再去寻找, 直至超设定时间, 抛出异常
抛出的异常为抛出异常TimeoutException 抛出的异常为NoSuchElementException

前进和后退

使用到的方法:

  • back() -> 页面后退, 回退到进入该页面前的页面
  • forward() -> 页面前进, 进入该页面后又进入的最新页面
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.zhihu.com/explore')
browser.back()  # 模拟页面的回退, 从知乎发现回退到淘宝页面
time.sleep(1)
browser.forward()  # 模拟页面的前进, 从淘宝页面又前进到知乎发现了
browser.close()

Cookies

使用到的方法:

  1. 获取Cookies -> browser.get_cookies()
  2. 添加Cookies -> browser.add_cookie({字典类型})
  3. 删除所有cookies (方法如其名, 最后就只剩下了一个空列表) -> browser.delete_all_cookies()
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
# 获取cookie
print(browser.get_cookies())
# 添加cookie
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
# 删除所有cookie
browser.delete_all_cookies()
print(browser.get_cookies())

选项卡管理

[1] 选项卡是什么?
就是平时用浏览器的时候, 切换页面点击的那个小长方形.

[2] 使用到的方法:

  1. execute_script('window.open()') -> 利用js打开一个新选项卡
  2. 切换选项卡 -> switch_to.window()
  3. 获取所有选项卡 -> browser.window_handles 注意这个window_handles是一个属性而不是一个方法.
import time
from selenium import webdriver
browser = webdriver.Chrome()
'''
工作流程为:
    打开百度页面, 执行js的window.open()打开一个新的选项卡, 获取所有的选项卡,
利用switch_to.window()方法切换到当前页面的下一个选项卡, 也就是刚才打开的新选项卡, 在该选项卡中,
打开淘宝页面, 停留一秒, 再次切换回初始的百度页面选项卡, 在该页面中打开知乎发现界面
'''
browser.get('https://www.baidu.com')
# window.open()表示利用js新开启一个选项卡
browser.execute_script('window.open()')
# browser.window_handles是什么?
# window_handles获取当前所有开启的选项卡, 返回的是选项卡的带好列表
print(browser.window_handles)
# switch_to_window()方法用来切换选项卡
browser.switch_to.window(browser.window_handles[1])
# 在browser.window_handles[1]选项卡下打开淘宝页面
browser.get("https://www.taobao.com")
time.sleep(1)
browser.switch_to.window(browser.window_handles[0])
browser.get("https://www.zhihu.com/explore")

异常处理

import time
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutError:
    print('超时')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('没有该元素')
finally:
    browser.close()

不打开浏览器

每次运行selenium都要自动打开浏览器, 很烦

# 重点在下面的三句, 这样就不会弹出浏览器窗口
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
browser = webdriver.Chrome(options=chrome_options)
browser.get("https://www.baidu.com/")
print(browser.find_element_by_id("su").get_attribute("value"))

简单的操作实例

"""
进入百度页面, 填写搜索信息(python), 点击搜索按钮, 将下拉框拉到底, 停留几秒, 回退到百度初始页面, 同时包含异常处理
"""
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import time
# 初始化
driver = webdriver.Chrome()
try:
    # 进入百度页面
    driver.get("https://www.baidu.com/")
except TimeoutException:
    print("超时")
try:
    # 找到输入框
    kw = driver.find_element_by_css_selector("#kw")
except NoSuchElementException:
    print("找不到该元素")
finally:
    # 输入关键字
    kw.send_keys("Python")
    time.sleep(5)
try:
    # 找到搜索按钮
    button = driver.find_element_by_css_selector("#su")
except NoSuchElementException:
    print("找不到该元素")
finally:
    # 点击搜索
    button.click()
    time.sleep(3)
    # 将下拉框拉到底
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
    time.sleep(3)
    # 回退到初始页面
    driver.back()
    time.sleep(3)
    # 关闭浏览器
    driver.close()
posted @ 2019-10-19 15:10  但是我拒绝  阅读(196)  评论(1编辑  收藏  举报