Python爬虫之Selenium库的使用

Selenium是一个自动化测试工具,对各种浏览器都能很好地支持,包括Chrome、Firefox这些主流浏览器。使用它就可以模拟浏览器进行各种各样的操作,包括爬取一些网页内容。当你看到浏览器自己运行并且在网页上翻页或者跳转的时候,应该会觉得很有趣的。

Selenium 2,又名 WebDriver,它的主要新功能是集成了 Selenium 1.0 以及 WebDriver(WebDriver 曾经是 Selenium 的竞争对手)。也就是说 Selenium 2 是 Selenium 和 WebDriver 两个项目的合并,即 Selenium 2 兼容 Selenium,它既支持 Selenium API 也支持 WebDriver API。当这两个框架被合并后,一个框架的缺陷被另一个框架所弥补。


工具准备

先安装好Selenium库和对应浏览器的WebDriver驱动,比如我用的是Chrome,则相对应安装的是ChromeDriver

前者使用pip就可以很方便地安装,后者要到相应网站下载,解压后就是一个exe文件(windows系统里面),然后要在系统里面加上环境变量,推荐放在PythonScripts 目录下。

ChromeDriver的官方网站:https://sites.google.com/a/chromium.org/chromedriver/downloads
,找到和自己浏览器版本对应的ChromeDriver版本,再根据所使用的系统类型进行选择。


基本使用方法

快速开始:

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('https://www.csdn.net/')

运行这段代码,会自动打开浏览器,然后访问CSDN的首页。
在这里插入图片描述

模拟提交:

下面的代码实现了模拟提交提交搜索的功能,首先等页面加载完成,然后输入到搜索框文本,点击提交。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
 
driver = webdriver.Chrome()
driver.get("http://www.python.org")
#断言
assert "Python" in driver.title
# 通过name属性找到搜索框
elem = driver.find_element_by_name("q")
# 在搜索框内输入内容
elem.send_keys("pycon")
# 提交
elem.send_keys(Keys.RETURN)
# 打印网页源代码
print(driver.page_source)

在这里插入图片描述
其中 driver.get 方法会打开请求的URL,WebDriver 会等待页面完全加载完成之后才会返回,即程序会等待页面的所有内容加载完成,JS渲染完毕之后才继续往下执行。注意:如果这里用到了特别多的 Ajax 的话,程序可能不知道是否已经完全加载完毕。而且由于是境外网站,所以反应时间会更长,耐心等待,或者换一个网站来进行测试。

上面代码里面的find_element_by_name是一个寻找网页name属性的方法,还有很多其他的find_element_by_*方法可以使用,根据需求来选择。

这里来列举一下常用查找元素的方法:

method说明
find_element_by_name通过元素name定位
find_element_by_id通过元素id定位
find_element_by_xpath通过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通过css选择器进行定位

如果要定位的元素有多个,那么可以把element改为elements,这样就可以匹配多个元素了。

还可以采用By类来确定哪种选择方式,然后再匹配。

from selenium.webdriver.common.by import By
 
driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')

By 类的一些属性如下:

ID = “id”
XPATH = “xpath”
LINK_TEXT = “link text”
PARTIAL_LINK_TEXT = “partial link text”
NAME = “name”
TAG_NAME = “tag name”
CLASS_NAME = “class name”
CSS_SELECTOR = “css selector”

页面操作:

1.页面交互:

对于一个页面中的HTML元素,首先我们要找到他,通过我们刚刚列出来的方法就可以来查找元素。

例如:

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

获取了元素之后,下一步当然就是向文本输入内容了,可以利用下面的方法:

element.send_keys("some text")

但是有一个副作用是当你输入一些文本时,这些 输入框中原有的文本不会被自动清除掉,相反,你的输入会继续添加到已存在文本之后。 你可以很方便的使用clear方法去清除input或者textarea元素中的内容:

element.clear()

你还可以通过”Keys”类来模式输入按键,下面是模拟一个方向键:

element.send_keys("and some", Keys.ARROW_DOWN)

2.填写表格

我们已经知道了怎样向文本框中输入文字,但是其它的表单元素呢?虽然也可以通过普通页面交互的方法处理,但是需要一个个进行,这并不是一个非常有效的方法。

其实 WebDriver 中提供了一个叫Select的类,可以帮助我们完成这些事情。他提供更有用的方法处理这些内容:

from selenium.webdriver.support.ui import Select

select = Select(driver.find_element_by_name('name'))
# 可以采用以下三种方法
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

如你所见,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择,十分方便。你可以根据自己的需要来尽情选择不同的方法,就是这么简单。

WebDriver 也提供一些有用的方法来取消选择已经选择的元素:

select = Select(driver.find_element_by_id('id'))
select.deselect_all()

这样便可以取消所有的选择。

假设在一个案例中,我们需要列出所有已经选择的选项:

select = Select(driver.find_element_by_xpath("xpath"))
all_selected_options = select.all_selected_options

获取所有可选选项是:

options = select.options

一旦你填写完整个表单,你应该想去提交它,有一个方法就是去找到一个“submit” 按钮然后点击它:

driver.find_element_by_id("submit").click()

当然你也可以单独提交某个元素:

element.submit()

如果调用的元素不在表单内,将会抛出NoSuchElementException异常。

3.元素拖放

要完成元素的拖拽,首先你需要指定被拖动的元素和拖动目标元素,然后利用ActionChains类来实现:

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()

这样就实现了元素从 source 拖动到 target 的操作。

4.页面切换

一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换。切换窗口的方法如下:

driver.switch_to_window("windowName")

还可以使用 window_handles 方法来获取每个窗口的操作对象,这样就可以迭代所有已经打开的窗口了:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

在很多网页中都是有Frame标签,所以我们爬取数据的时候就涉及到切入到frame中以及切出来的问题,切换 frame 的方法如下:

driver.switch_to_frame("frameName")

通过“.”操作符你还可以获得子frame,并通过下标指定任意frame,就像这样:

driver.switch_to_frame("frameName.0.child")

4.处理弹窗

WebDriver内置了对处理弹出对话框的支持。 在你的某些动作之后可能会触发弹出对话框,你可以像下面这样访问对话框:

alert = driver.switch_to_alert()

5.访问历史记录

操作页面的前进和后退功能:

driver.forward()
driver.back()

5.操作Cookies

为页面添加 Cookies:

driver.get("http://www.example.com")
cookie = {‘name’ : ‘foo’, ‘value’ : ‘bar’}
driver.add_cookie(cookie)

获取页面 Cookies:

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

6.等待页面加载

  • 显示等待

显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码。 这里有一些方便的方法让你只等待需要的时间。WebDriverWait结合ExpectedCondition是实现的一种方式。

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()
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()

程序默认会 500ms 调用一次来查看元素是否已经生成,如果本来元素就是存在的,那么会立即返回。

  • 隐式等待

如果某些元素不是立即可用的,隐式等待是告诉WebDriver去等待一定的时间后去查找元素。 默认等待时间是0秒,一旦设置该值,隐式等待是设置该WebDriver的实例的生命周期。

from selenium import webdriver
 
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

常用的内置等待条件,可以直接调用,这样就不需要再自己写了:

method说明
title_is标题是某内容
title_contain标题包含某内容
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

更多内容可以看中文翻译文档:https://selenium-python-zh.readthedocs.io/en/latest/index.html

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 设计师:Steven·简谈 返回首页