selenium入门使用

April 8, 2020

2102 9 minutes and 33 seconds
selenium入门使用

[DeadPool爬虫]selenium入门使用

前一篇博客内容的代码中,已经使用了webdirver的功能,这个功能帮助我们在浏览器中打开网页,并且使我们能够对加载后的网页进行实时操作,这么神器的功能,来源于selenium这个框架,其实其本身定义是一个前端自动化测试框架,但是因为其特性,能够帮助我们很好的实现爬虫的功能,因此现在在爬虫领域其也是必须掌握的存在,接下来我就简单总结以下selenium的基础使用,高级使用同样需要在不断地编码中去掌握并同时查看其官方文档~

selenium官方文档

selenium 框架

Selenium 是 ThroughtWorks 一个强大的基于浏览器的开源自动化测试工具,它通常用来编写Web应用的自动化测试。

其本身就是一个独立的框架,拥有自己开的 IDE 工具,所以在爬虫领域里面通常是使用 selenium 中的webdirver模块来实现对浏览器的API调用。这里我们使用的就是 Python 的接口包

安装就也是简单的 pip install selenium 就可以了。

PS: 推荐大家使用virtualenv的方式

既然是用的是 selenium 中 webdirver 模块的功能,所以首先你需要在你的设备上拥有浏览器,同时下载该浏览器的对应驱动程序,这里不同的浏览器驱动不同,列举如下:

Chrome: https://sites.google.com/a/chromium.org/chromedriver/downloads Firefox: https://github.com/mozilla/geckodriver/releases Safari: https://webkit.org/blog/6900/webdriver-support-in-safari-10/ Edge: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

PS: 博文的最末附件会带上 chrome 的最新驱动(三个平台的)

selenium 上手

这里简单的 selenium 使用就以官方文档中的例子为基础,里面稍微修改了一点


from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome(executable_path="E:\\Github\\Lesson\\chromedriver.exe")
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()

这里与官方不同的是使用的 Chrome 作为浏览器,同时加载了驱动位置,其实很多博文和教程都是将驱动程序添加到了 windows 系统环境变量中,或者是放到了 selenium 安装的路径下,这里其实完全没有必要,因为只需要在加载的时候指定位置就行了,还方便根据不同的版本,来加载不同的驱动~

接下来简单解释一下上面的代码

===

这两个导包动作其实就是导入了selenium对应的webdirver模块和键盘绑定Keys,即你的回车、F1等

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

===

这就是我前面说的实例化webdriver的时候指定驱动目录就行了

driver = webdriver.Chrome(executable_path="E:\\Github\\Lesson\\chromedriver.exe")

===

打开页面访问指定网址,并同时判断网页打开是否正确(assert 断言,PS: Python test 中经常使用)

driver.get("http://www.python.org")
assert "Python" in driver.title

===

在当前页面找到name为q的元素,其实就是python官网的搜索输入框,清除内容,填写内容,按下回车

elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)

===

判断当前页面内容里面是否存在指定字符串,然后关闭浏览器

assert "No results found." not in driver.page_source
driver.close()

PS: 一定要记得关闭浏览器,不然你会在不停的尝试中打开越来越多的浏览器

selenium 与页面交互

首先要对页面元素进行交互第一点就是定位元素位置,这里需要你有一定的html和css基础了,不过很好掌握。具体如何查找元素,总结如下:


# find a element
driver.find_element_by_id()
driver.find_element_by_name()
driver.find_element_by_xpath()
driver.find_element_by_link_text()  # a 标签中的文本内容
driver.find_element_by_partial_link_text()  # 非全匹配 a 标签中的文本内容
driver.find_element_by_tag_name()
driver.find_element_by_class_name()
driver.find_element_by_css_selector()

# 上面的方法可以统一为
driver.find_element(By.XPATH, '//button[text()="Some text"]')

# find the elements
driver.find_elements_by_id()
driver.find_elements_by_name()
driver.find_elements_by_xpath()
driver.find_elements_by_link_text()  # a 标签中的文本内容
driver.find_elements_by_partial_link_text()  # 非全匹配 a 标签中的文本内容
driver.find_elements_by_tag_name()
driver.find_elements_by_class_name()
driver.find_elements_by_css_selector()

# 上面的方法可以统一为
driver.find_elements(By.XPATH, '//button')

其中都很简单,主要比较特别的就是 XPath 这个东西了,不过也有其标准 W3C XPATH

W3C XPath Tutorial

然后元素找到了之后,怎么与之进行交互呢?其实简单想象一下,前端页面的交互主要分为两种形式:一种是输入;一种是点击。因此归纳的方式也就分为这两种

输入

例如下面这个密码输入框,可以通过下面的代码找到该输入框之后,清空内容,填写内容。


<input type="text" name="passwd" id="passwd-id" />


element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

element.clear()
element.send_keys("some text")

除了输入框,还有就是选择框,本质上任然是输入框,但是需要通过点击来实现的内容输入,这里我仍然建议以其HTML本身的含义来定义其类型,这是一种输入操作。


<select class="form-control" name="name">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>

# 常规方法
# 选择全部的 options
element = driver.find_element_by_xpath("//select[@name='name']")
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
    print("Value is: %s" % option.get_attribute("value"))
    option.click()

# Selenium 中的UI库 进行找寻select
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_xpath("//select[@name='name']"))

# 列举全部的options
options = select.options

# 选择特定的options
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

# 查看当前选中的options
selected_options = select.all_selected_options

# 选择全部的options
select.select_all()

# 重置全部的选择
select.deselect_all()

点击

对于点击事件,可以总结为两个方式: 1、点击动作直接完成;2、点击动作间隔完成。与之对应的就是点击和拖拽,其本质是一样的,只不过是点下和松开的时间间隔不同而已

针对点击直接完成(点击)


# 找到对应的button之后,直接触发点击事件即可
driver.find_element_by_id("submit").click()

针对点击间隔完成(拖拽)


# 找到目标元素和最终位置,执行拖拽效果
element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()

相比输入这个点击动作就要简单一些

selenium 附加功能

对于弹出的对话框支持


alert = driver.switch_to_alert()

history and location

浏览器的访问地址和历史


driver.get("http://www.example.com")
driver.forward()
driver.back()

windows and iframe

切换打开的窗口和嵌入的iframe


# 轮流切换当前打开的窗口
for handle in driver.window_handles:
    driver.switch_to_window(handle)

# 切换当前的iframe
driver.switch_to_frame("frameName")
# 或者直接切换到里面的元素
driver.switch_to_frame("frameName.0.child")


# 回到默认窗口
driver.switch_to_default_content()

cookies

获取和增加当前域下的cookies


# Go to the correct domain
driver.get("http://www.example.com")

# Now set the cookie. This one's valid for the entire domain
cookie = {name : foo, value : bar}
driver.add_cookie(cookie)

# And now output all the available cookies for the current URL
driver.get_cookies()

selenium 显式等待

简单来说就是判断你打开页面的过程中是否加载完成


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.Chrome(executable_path="E:\\Github\\Lesson\\chromedriver.exe")
driver.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

其中可以支持的触发动作包含一下方式:


wait.until(EC.title_is((By.ID, 'someid')))
wait.until(EC.title_contains((By.ID, 'someid')))
wait.until(EC.presence_of_element_located((By.ID, 'someid')))
wait.until(EC.visibility_of_element_located((By.ID, 'someid')))
wait.until(EC.visibility_of((By.ID, 'someid')))
wait.until(EC.presence_of_all_elements_located((By.ID, 'someid')))
wait.until(EC.text_to_be_present_in_element((By.ID, 'someid')))
wait.until(EC.text_to_be_present_in_element_value((By.ID, 'someid')))
wait.until(EC.invisibility_of_element_located((By.ID, 'someid')))
wait.until(frame_to_be_available_and_switch_to_it((By.ID, 'someid')))
wait.until(invisibility_of_element_located((By.ID, 'someid')))
wait.until(element_to_be_clickable((By.ID, 'someid')))
wait.until(staleness_of((By.ID, 'someid')))
wait.until(element_to_be_selected((By.ID, 'someid')))
wait.until(element_located_to_be_selected((By.ID, 'someid')))
wait.until(element_selection_state_to_be((By.ID, 'someid')))
wait.until(element_located_selection_state_to_be((By.ID, 'someid')))
wait.until(alert_is_present((By.ID, 'someid')))

以上,就是通过我自己对于selenium官方文档的知识总结,当然还有具体的高级使用方法,后续有机会的话,会将我遇到的一些问题挨个介绍一下~

附件: