Python爬虫4.3 — selenium基础用法教程
综述
本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4
在前一章中,我们了解了Ajax的分析和抓取方式,这其实也是JavaScript动态渲染的页面的一种情形,通过直接分析Ajax,我们仍然可以借助requests或urllib来实现数据爬取。
不过JavaScript动态渲染的页面不止Ajax这一种。例如淘宝这种页面,它即使是Ajax获取的数据,但是其Ajax接口含有很多加密参数,我们难以直接找出其规律,也很难直接分析Ajax来抓取。
为了解决这些问题,我们可以直接使用模拟浏览器运行的方式来实现,这样就可以做到在浏览器中看到是什么样,抓取的源码就是什么样,也就是可见即可爬。这样我们就不用再去管网页内部的JavaScript用了什么算法渲染页面,不用管网页后台的Ajax接口到底有哪些参数。
Python提供了许多模拟浏览器运行的库,如Selenium、Splash、PyV8、Ghost等。本章中,我们就来介绍一下Selenium的用法。Selenium+chromedriver(Headless Chrome)可以称为爬虫的终极解决方案。
Selenium + Chromedriver
Selenium 介绍
Selenium
是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。
可以将Selenium
理解相当于一个机器人,可以模拟人类在浏览器上的一切行为,自动处理浏览器上的一些行为。
Chromedriver 介绍
Chromedriver
是一个驱动Chrome
浏览器的驱动程序,使用它才可以驱动浏览器。
Headless Chrome
在Chrome59中开始搭载HeadlessChrome。这是一种在无需显示headless的环境下运行Chrom浏览器的方式。从本质上来说,就是不用chrome浏览器来运行Chrome的功能!
自从Selenium
和PhantomJS
"分手"之后,使用Selenium
+Headless Chrome
成为主流。
其他浏览器的driver
- Chrome : https://sites.google.com/a/chromium.org/chromedriver/downloads
- Firefox : https://github.com/mozilla/geckodriver/releases
- Edge : https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
- Safari : https://webkit.org/blog/6900/webdriver-support-in-safari-10/
安装Selenium+chromedriver
- 安装
Selenium
:Selenium
有很多语言的版本,有java、ruby、python等。我们使用pip
安装python版本即可:
$ pip install selenium
- 安装
chromedriver
:下载相应的chromedriver
放到不需要权限的纯英文目录下就可以了。版本号对应描述:http://chromedriver.storage.googleapis.com/2.40/notes.txt
简单使用
获取百度首页
现在我们以一个简单的获取百度首页的例子来讲下Selenium
和chromedriver
如何快速入门,示例代码如下:
# 引入所需库
from selenium import webdriver
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 打开百度
driver.get('https://www.baidu.com/')
# 获取源码
print(driver.page_source)
# 关闭
driver.close()
Selenium常用操作
更多教程请参考:https://python-selenium-zh.readthedocs.io/zh_CN/latest/
关闭页面
driver.close()
: 关闭当前页面。driver.quit()
: 退出整个浏览器。
示例代码如下:
# 引入所需库
import time
from selenium import webdriver
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 打开百度
driver.get('https://www.baidu.com/')
time.sleep(5)
# 关闭当前页面
driver.close()
# 关闭浏览器
driver.quit()
定位元素
find_element_by_id
: 根据id来查找某个元素。等价于:input_kw = driver.find_element_by_id('kw') input_kw = driver.find_element(By.ID, 'kw')
find_element_by_class_name
: 根据类名查找元素,等价于:input_kw = driver.find_element_by_class_name('s_ipt') input_kw = driver.find_element(By.CLASS_NAME, 's_ipt')
find_element_by_name
: 根据name属性的值来查找元素,等价于:input_kw = driver.find_element_by_name('wd') input_kw = driver.find_element(By.ID, 'wd')
find_element_by_tag_name
: 根据标签名来查找元素,等价于:input_kw = driver.find_element_by_tag_name('input') input_kw = driver.find_element(By.TAG_NAME, 'input')
find_element_by_xpath
: 根据xpath语法来获取元素,等价于:
使用selenium中xpath获取元素属性值得时候和真实的xpath语法有些不同,例如获取a标签的href属性值,在真实的xpath语法中使用input_kw = driver.find_element_by_xpath('//input[@id="kw"]') input_kw = driver.find_element(By.XPATH, '//input[@id="kw"]')
//a[@seed="bankcard-more"]/@href
即可,但是在selenium中这样使用会报错;只能使用//a[@seed="bankcard-more"]
先获取标签元素,然后使用get_attribute("href")
获取属性值,例如:bank_url_ele = driver.find_element_by_xpath('//a[@seed="bankcard-more"]') bank_url = bank_url_ele.get_attribute("href")
find_element_by_css_selector
: 根据css选择器来选择元素,等价于:input_kw = driver.find_element_by_css_selector('.s_ipt') input_kw = driver.find_element(By.CSS_SELECTOR, '.s_ipt')
使用示例代码如下:
# 引入所需库
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 打开百度
driver.get('https://www.baidu.com/')
time.sleep(2)
# 根据id获取元素
# input_kw = driver.find_element_by_id('kw')
# input_kw = driver.find_element(By.ID, 'kw')
# 根据类名获取元素
# input_kw = driver.find_element_by_class_name('s_ipt')
# input_kw = driver.find_element(By.CLASS_NAME, 's_ipt')
# 根据name属性值来获取元素
# input_kw = driver.find_element_by_name('wd')
# input_kw = driver.find_element(By.NAME, 'wd')
# 根据标签名来获取元素
# input_kw = driver.find_element_by_tag_name('input')
# input_kw = driver.find_element(By.TAG_NAME, 'input')
# 根据xpath语法获取元素
# input_kw = driver.find_element_by_xpath('//input[@id="kw"]')
# input_kw = driver.find_element(By.XPATH, '//input[@id="kw"]')
# 根据css选择器来选择元素
input_kw = driver.find_element_by_css_selector('.s_ipt')
# input_kw = driver.find_element(By.CSS_SELECTOR, '.s_ipt')
print(input_kw)
# 获取全部符合元素
# inputs_kw = driver.find_elements_by_css_selector('.s_ipt')[0]
inputs_kw = driver.find_elements(By.CSS_SELECTOR, '.s_ipt')
print(inputs_kw)
time.sleep(2)
# 关闭当前页面
driver.close()
注意:
1. find_element_
获取第一个符合条件的元素。find_elements_
是获取所有满足条件的元素。
2.如果知识想要解析网页中的数据,那么推荐将网页源代码使用lxml来解析,因为lxml底层使用的是c余言,所以解析效率会更高。
3. 如果想要对元素进行一些操作,比如给一个文本框输入值,或者是点击某个按钮,那么就必须使用selenium给我们提供的查找元素的方法
操作表单元素
常见的表单元素:
input
: type=‘text | password |email | number | checkbox’button
: button | input[type=‘submit’]select
: 下拉选择
- 操作输入框:分为两步,第一步:找到这个元素;第二步:使用
send_key(value)
将数据填充进入。使用clear()
方法可以清除输入框中的内容。代码如下:# 根据id获取元素 input_kw = driver.find_element_by_id('kw') # input表单 input_kw.send_keys('python') # 清除输入框中内容 input_kw.clear()
- 操作checkbox:因为要选中
checkbox
标签,在网页中是通过鼠标点击的,因此想要选中checbox
标签,那么先选中这个标签,然后执行click()
事件,代码如下:# 根据name获取元素 rememberEle = driver.find_element_by_name('remember') rememberEle.click()
- 选择select:select元素不能直接点击,因为点击后还需要选中元素。这时候selenium就专门为select标签提供了一个类
selenium.webdriver.soupport.ui.Select
。将获取到的元素当成参数传到这个类中,创建对象。以后就可以使用这个对象进行选择了,代码如下:from selenium.webdriver.support.ui import Select # 根据name获取元素 select_tag = driver.find_element_by_name('jumpMenu') select_btn = Select(select_tag) # 根据索引进行选择 # select_btn.select_by_index(1) # 根据值进行选择 # select_btn.select_by_value('http://www.95you.com') # 根据可见文本进行选择 select_btn.select_by_visible_text('广州东百信息科技有限公司') # 取消选中的所有选择 select_btn.deselect_all() # select_btn.deselect_by_index(1) # select_btn.select_by_value('http://www.95you.com') # select_btn.deselect_by_visible_text('广州东百信息科技有限公司')
- 操作按钮:操作按钮有很多种方式,比如单击、右击、双击等。这里将一个最简单的,就是点击,直接调用
click()
函数就可以了,代码如下:# 操作按钮 input_btn = driver.find_element_by_id('reg_btn') input_btn.click()
示例代码如下:
# 引入所需库
import time
from selenium import webdriver
from selenium.webdriver.support.ui import Select
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
# driver.get('https://www.baidu.com/')
# time.sleep(2)
# 根据id获取元素
# input_kw = driver.find_element_by_id('kw')
# input表单
# input_kw.send_keys('python')
# 操作checkbox
# driver.get('https://www.douban.com/')
# time.sleep(2)
# # 根据name获取元素
# rememberEle = driver.find_element_by_name('remember')
# rememberEle.click()
# 操作select
driver.get('http://95yueba.com/')
time.sleep(2)
# 根据name获取元素
select_tag = driver.find_element_by_name('jumpMenu')
select_btn = Select(select_tag)
# 根据索引进行选择
# select_btn.select_by_index(1)
# 根据值进行选择
# select_btn.select_by_value('http://www.95you.com')
# 根据可见文本进行选择
select_btn.select_by_visible_text('广州东百信息科技有限公司')
# 取消选中的所有选择
select_btn.deselect_all()
# select_btn.deselect_by_index(1)
# select_btn.select_by_value('http://www.95you.com')
# select_btn.deselect_by_visible_text('广州东百信息科技有限公司')
time.sleep(2)
# 操作按钮
input_btn = driver.find_element_by_id('reg_btn')
input_btn.click()
# 关闭当前页面
driver.close()
获取截屏
我们也可进行截取页面形成图片进行保存,示例代码如下:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
driver = webdriver.Chrome(executable_path=path, options=options)
driver.get('https://httpbin.org/ip')
# 进行截屏保存
driver.save_screenshot('1.png')
其他截屏方法:
- get_screenshot_as_base64(): 获取当前窗口的截图保存为一个base64编码的字符串。
- get_screenshot_as_file(filename): 获取当前窗口的截图保存为一个png格式的图片,filename参数为图片的保存地址,最后应该以.png结尾。如果出现IO错误,则返回False。用法:
driver.get_screenshot_as_file('/Screenshots/foo.png')
- get_screenshot_as_png(): 获取当前窗口的截图保存为一个png格式的二进制字符串。
获取窗口信息
- get_window_position(windowHandle=’current’): 获取当前窗口的x,y坐标。
- get_window_rect(): 获取当前窗口的x,y坐标和当前窗口的高度和宽度。
- get_window_size(windowHandle=’current’): 获取当前窗口的高度和宽度。
执行JS代码
- execute_async_script(script, *args) : 在当前的window/frame中异步执行JS代码。
- script:是你要执行的JS代码。
- *args:是你的JS代码执行要传入的参数。
- 用法:
script = "var callback = arguments[arguments.length - 1]; " script2 = "window.setTimeout(function(){ callback('timeout') }, 3000);" driver.execute_async_script(script + script2)
- execute_script(script, *args): 在当前的window/frame中同步执行JS代码。
- script:是你要执行的JS代码。
- *args:是你的JS代码执行要传入的参数。