在我们爬取网页过程中,经常发现我们想要获得的数据并不能简单的通过解析HTML代码获取,这些数据是通过AJAX异步加载方式或经过JS渲染后才呈现在页面上显示出来。

selenuim是一种自动化测试工具,它支持多种浏览器。而在爬虫中,我们可以使用它来模拟浏览器浏览页面,进而解决JavaScript渲染的问题。

1. 使用示例

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWait
# 调用Chrome浏览器
browser = webdriver.Chrome()

try:
    browser.get('https://www.baidu.com')
    input_data = browser.find_element_by_id('kw')
    # 传入参数
    input_data.send_keys('数据分析')
    # 点击回车
    input_data.send_keys(Keys.ENTER)
    # 等待加载
    wait = WebDriverWait(browser, 10)
    wait.until(EC.presence_of_element_located((By.ID, 'content_left')))
    # 输出url
    print(browser.current_url)
    # 输出cookies    print(browser.get_cookies)
    # 输出源码    print(browser.page_source)
finally:
    browser.close()

2. 详细介绍

2.1 声明浏览器对象

即告诉程序,应该使用哪个浏览器进行操作

from selenium import webdriver

# 使用Chrome
browser = webdriver.Chrome()
# 如果没有添加chromedriver到系统path里,需要指定chromedriver的路径
browser = webdriver.Chrome('/your path to/webdriver')

# selenium也可以支持其他的浏览器,如Firefox、Edge、Safari...声明方法和上面一样
browser = webdriver.Firefox()
browser = webdriver.Safari()

2.2 访问页面

from selenium import webdriver

# 使用Chrome
browser = webdriver.Chrome()
# 打开淘宝
browser.get('https://www.taobao.com')
# 打印页面源代码
print(browser.page_source)
# 关闭浏览器
browser.close()

2.3 查找元素

成功访问网页后,我们可能需要进行一些操作,比如找到搜索框然后输入关键字再敲击回车键。

因此,就需要在selenium中查找元素。

2.3.1 单个元素

selenium查找元素有两种方法。

第一种,是指定使用哪种方法去查找元素,比如指定依照CSS选择或者依照xpath去进行查找

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

# 查找id
input_first = browser.find_element_by_id('q')
# CSS选择
input_second = browser.find_element_by_css_selector('#q')
# xpath
input_third = browser.find_element_by_xpath('//*[@id="q"]')
# 三种方法的效果一致
print(input_first, input_third, input_third)

下面是详细的元素查找方法

  • 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(),传入的第一个参数为需要使用的元素查找方法

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
browser.find_element(By.ID, 'q')

2.3.2 多个元素

查找多个元素和查找单个元素的方法基本一致(只需要将查找单个元素的func里加一个s)。

查找多个元素返回的是一个list。

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
# 查找单个元素
browser.find_element(By.ID, 'q')
browser.find_element_by_id('q')
# 查找多个元素
browser.find_elements(By.ID, 'q')
browser.find_elements_by_id('q')

2.4 元素交互操作

元素交互是先获取一个元素,然后对获取的元素调用交互方法。

比如说在搜索框内输入文字:

from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.jd.com')

input = browser.find_element_by_css_selector('#key') # 找到搜索框
input.send_keys('iPad') # 输入iPad
time.sleep(1)
input.clear() # 清空搜索框
input.send_keys('iPhone') # 输入iPhone
botton = browser.find_element_by_css_selector('#search > div > div.form > button > i') # 找到搜索按钮
botton.click() # 点击搜索按钮

2.5 交互动作

交互动作是将动作附加到交互链中串行执行,需要使用到ActionChains。

参照官方文档:ActionChains

2.6 执行JavaScript

比如拖拽下拉

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
# 下拉
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')

2.7 获取元素信息

已经通过元素查找获取到元素后,可能还需要获取这个元素的属性、文本

2.7.1 获取属性

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')

print(browser.title) # 网页标题
print(browser.name) # 浏览器名称
print(browser.find_element_by_id('setf').text) # 获取文本
print(browser.find_element_by_id('kw').tag_name) # 搜索框的标签属性
print(browser.find_element_by_id('kw').get_attribute("class")) # 搜索框的其他属性
print(browser.find_element_by_id('kw').get_attribute('value')) # 搜索框输入的内容

2.8 Frame

如果定位到父frame,是无法查找到子frame的信息的,因此需要切换到子frame再进行查找。同理,在子frame也无法查找到父frame的信息

from selenium.common.exceptions import NoSuchElementException
from selenium import webdriver

browser = webdriver.Chrome('/Users/xingyu/Downloads/chromedriver')
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')

# 切换至子frame
browser.switch_to.frame('iframeResult')
# 查找元素
source = browser.find_element_by_css_selector('#draggable')
print('source')

# 在子frame中不能找到父frame的信息
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)

2.9 等待

请求网页时,可能会存在AJAX异步加载的情况。而selenium只会加载主网页,并不会考虑到AJAX的情况。因此,使用时需要等待一些时间,让网页加载完全后再进行操作。

2.9.1 隐式等待

使用隐式等待时,如果webdriver没有找到指定的元素,将继续等待。超出规定时间后,如果还是没又找到指定元素则抛出找不到元素的异常。默认等待时间为0。

隐式等待是对整个页面进行等待。

需要特别说明的是:隐性等待对整个driver的周期都起作用,所以只要设置一次即可。

from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Chrome('/Users/xingyu/Downloads/chromedriver')
# 隐式等待,时长为10
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

2.9.2 显式等待

显示等待包含了等待条件和等待时间

首先判定等待条件是否成立,如果成立,则直接返回;如果条件不成立,则等待最长时间为等待时间,如果超过等待时间后仍然没有满足等待等待条件,则抛出异常。

显式等待是对指定的元素进行等待。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Chrome('/Users/xingyu/Downloads/chromedriver')
driver.implicitly_wait(10)  # 隐性等待和显性等待可以同时用,但要注意:等待的最长时间取两者之中的大者
driver.get('https://www.baidu.com')

try:
    WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id('kw')).send_keys("lambda")
finally:
    driver.close()

2.10 浏览器的前进/后退

back实现回到前一页面,forward实现前往下一页面

import time
from selenium.common.exceptions import NoSuchElementException

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

2.11 对Cookies进行操作

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
# 获取当前cookies
print(browser.get_cookies())
# 添加cookies
browser.add_cookie({'name': 'name', 'domain':'domain', 'value':'value'})
print(browser.get_cookies())
# 清除所有cookies
browser.delete_all_cookies()
print(browser.get_cookies())

2.12 选项卡管理

选项卡管理就是浏览器的标签。有些时候我们需要在浏览器里增加一个新标签页或者删除一个标签页,就可以使用selenium来实现。

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
# 增加一个新的标签页
browser.execute_script('window.open()')
# window_handles即为目前浏览器的标签页信息
print(browser.window_handles)

# 切换至标签页1
browser.switch_to.window(browser.window_handles[1])
browser.get('https://www.taobao.com')
# 切换至标签页0
browser.switch_to.window(browser.window_handles[0])
browser.get('https://www.python.org')

# 关闭目前定位标签页,也就是标签页0
browser.close()
# 退出浏览器
browser.quit()

2.13 异常处理

参照官方文档:Exceptions

最新文章

  1. 页面width与height使用百分比来划分不起作用解决办法--记录六
  2. 5 Hbase
  3. OJ 1188 全排列---康托展开
  4. MyBatis3资料网址
  5. 【python自动化第三篇:python入门进阶】
  6. CTRL+A, CTRL+C, CTRL+V
  7. Delphi函数指针的两种定义(对象方法存在一个隐藏参数self,所以不能相互赋值)
  8. EasyUI搭建前端框架
  9. R语言高性能编程(三)
  10. Ajax,JSONP以及跨域问题
  11. (后端)Java新人入职——配置环境及安装开发工具(完全)
  12. centos关机、重启、图形界面与命令行界面切换命令
  13. codeoforces 975B Mancala
  14. 替代iframe
  15. Ajax 滚动异步加载数据
  16. poi导出excel合并单元格(包括列合并、行合并)
  17. redis安装使用配置
  18. spring boot 启动方式
  19. cocos2d-x聊天气泡
  20. vim c++插件clang_complete

热门文章

  1. Xor-MST Codeforces - 888G
  2. python学习之TCP/UDP
  3. .Net应用导入、导出Excel文件
  4. dataTable 中数据的居中显示
  5. 我喜欢的两个js类实现方式 现在再加上一个 极简主义法
  6. slf4j介绍以及与Log4j、Log4j2、LogBack整合方法
  7. bootstrop媒体对象、面板和Well
  8. LN : Eden Polymorphic And OOP Design Pattern Abstract Factory
  9. 利用html5canvas给图片增加文字水印
  10. Vuex.js状态管理共享数据 - day8