Selenium是一个自动化测试工具,使用它可以驱动浏览器完成特定的动作(点击,滚动等),同时它可以获取网页源代码,做到可见及可爬。对于一些由AJAX加载的加密数据它也能很好的完成。
Selenium的安装
推荐使用pip3 install selenium
安装。
ChromeDriver的安装
Selenium是一个自动化测试工具,它需要浏览器配合使用,首先我们需要安装Chrome浏览器,这个简单,不再赘述。
同时,我们需要配置ChromeDriver。只有配置了驱动Selenium才能驱动Chrome浏览器进行操作。驱动下载地址:http://chromedriver.chromium.org/。一定要下载和Chrome浏览器版本对应的驱动。
下载完对应的驱动后我们需要进行环境变量的配置:
。保存后执行
source ~/.profile` 使设置生效。首先我们需要创建浏览器对象,Selenium支持非常多的浏览器,以Chrome为例声明浏览器对象:
from selenium import webdriver
brower = webdriver.Chrome()
#selenium还支持以下浏览器
# webdriver.Firefox()
# webdriver.PhantomJS()
# webdriver.Safari()
# webdriver.Edge()
使用webdriver完成了浏览器对象的创建,后续的一切操作都是基于此对象进行了。
创建好浏览器对象后可以调用get()
方法来请求网页,现在访问百度。
from selenium import webdriver
brower = webdriver.Chrome()
brower.get('https://www.baidu.com')#访问百度
print(brower.page_source)#打印网页源码
brower.close()
运行代码我们可以看见自动打开浏览器访问百度,再自动关闭。控制台输出了网页源码。
我们使用Selenium可以进行表单填充,点击操作,这些操作的前提是我们需要获取相应的节点(输入框,点击按钮等)。
from selenium import webdriver
brower = webdriver.Chrome()
brower.get('http://www.baidu.com')#访问百度
input_kw = brower.find_element_by_id("kw")#根据id查找输入框
# input_kw2 = brower.find_element_by_css_selector("#kw")使用css选择器查找输入框
search_btn = brower.find_element_by_xpath('//*[@id="su"]')#使用xpath查找搜索按钮
print(input_kw,search_btn)
brower.close()
可以发现查找到的节点类型为WebElement
类型。
获取单个节点的方法还有以下几个:
find_element_by_name():根据name属性值查找;
find_element_by_link_text():根据a标签的文本内容查找,返回第一个匹配的节点;
find_element_by_partial_link_text():根据a标签的局部文本内容查找,返回第一个匹配的节点;
find_element_by_tag_name():根据标签名查找,返回第一个匹配的节点;
find_element_by_class_name():根据class属性值查找;
除了以上几种特点的方法用于查找节点,Selenium提供了一个通用方法find_element(by=By.ID, value=None)
查找方式by和值,默认根据ID查找。
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.get('http://www.baidu.com')#访问百度
input_kw = brower.find_element(By.ID,"kw")#根据id查找输入框
# input_kw2 = brower.find_element(By.CSS_SELECTOR,"#kw")使用css选择器查找输入框
search_btn = brower.find_element(By.XPATH,'//*[@id="su"]')#使用xpath查找搜索按钮
print(input_kw,search_btn)
brower.close()
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.get('https://www.taobao.com/')
lis = brower.find_elements(By.CSS_SELECTOR,'.service-bd > li')
print(lis)
brower.close()
获取到指定节点后我们进行模拟操作,一般为输入文本内容和点击按钮。现在我们打开百度首页搜索“python”相关内容。
这里写代码片
执行代码后浏览器自动打开访问百度并搜索Python。
其他交互操作(例如滚动)查看官方文档:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement。
ActionChains是一种自动执行低级别交互的方法,例如鼠标移动,鼠标按钮操作,按键和上下文菜单交互。 这对于执行更复杂的操作非常有用,例如悬停和拖放。
示例实现一个节点的拖曳动作:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import time
brower = webdriver.Chrome()
brower.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
brower.switch_to.frame('iframeResult')
source = brower.find_element(By.ID,'draggable')
target = brower.find_element(By.ID,'droppable')
actions = ActionChains(brower)#创建ActionChains对象
actions.drag_and_drop(source,target)#按住源元素上的鼠标左键,然后移动到目标元素并释放鼠标按钮。模拟拖曳操作
actions.perform()#执行调用的操作,如果有多个按照调用顺序执行。
time.sleep(5)
brower.close()
Selenium可以使用execute_script()
方法执行JS代码。Selenium并没有提供下拉进度条的操作,这时候就需要我们执行JS代码来完成下拉操作了。
from selenium import webdriver
import time
brower = webdriver.Chrome()
brower.get('https://www.baidu.com/s?wd=Python')
time.sleep(2)
brower.execute_script('window.scrollTo(0,document.body.scrollHeight)')#下拉到最底部
time.sleep(2)
brower.execute_script('alert("To Bottom")')
time.sleep(2)
brower.close()
虽然我们通过调用page_source获取网页源码再通过解析库获取节点信息,但是Selenium提供了获取节点的方法,并且返回WebElement对象,此对象有对应的方法和属性获取节点信息。
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.get('https://www.baidu.com')
input_kw = brower.find_element(By.ID,'kw')
print(input_kw.get_attribute('class'))
print(input_kw.get_attribute('name'))
brower.close()
brower = webdriver.Chrome()
brower.get(‘https://www.baidu.com’)
node = brower.find_element(By.CSS_SELECTOR,’#u1 > a:nth-child(1)’)
print(node.text)
brower.close()
![这里写图片描述](https://img-blog.csdn.net/20180909222532958?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI1MzQzNTU3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
## 延时等待 ##
在爬取过程中由于网络等因素导致网页还没加载出来,如果这时候我们获取节点当然是无法实现的,所以我们需要等待一段时间确保节点已经加载出来。等待方式有两种:**隐式等待和显示等待**。
隐式等待
调用`implicitly_wait()` 使用隐式等待。使用隐式等待时,如果Selenium无法再DOM树中找到节点则等待,超出等待时间后抛出异常信息。
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.implicitly_wait(10)#等待10秒,默认0
brower.get(‘https://www.baidu.com’)
input_kw = brower.find_element(By.ID,‘kw’)
input_kw.send_keys(‘阿里巴巴’)
brower.close()
显式等待
隐式等待需要等待页面加载完成,但是我们其实只需要某几个节点而已,这未免太浪费时间了,并且由于网络的影响我们很难把控应该等待多长时间是合理的。
显示等待可以指定等待目标节点的最长时间,如果在规定时间内加载出来了这个节点就返回,否则抛异常。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC#等待条件
from selenium.webdriver.support.ui import WebDriverWait
brower = webdriver.Chrome()
brower.get(‘https://www.baidu.com’)
wait = WebDriverWait(brower,10)#设置最长等待时间
input_kw = wait.until(EC.presence_of_element_located((By.ID,‘kw’)))#传入元组,等待id为kw的节点加载出来
print(input_kw)
brower.close()
如果是等待一个按钮我们不应该简简单单的等待节点出现,而应该等待至节点可点击才行,对应的条件为`element_to_be_clickable`。
btn = wait.until(EC.element_to_be_clickable((By.ID,‘su’)))
关于等待条件根据[官网](https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions)我们总结出以下几个常用的条件:
| 等待条件| 描述|
| ------------- |:-------------:|
| title_is | 标题是某内容 |
| title_contains | 标题包含某内容|
| presence_of_element_located | 节点加载出来,传入定位元组 |
| visibility_of_element_located | 节点可见,传入定位元组 |
| presence_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| 节点可选择,传入定位元组 |
## 前进和后退 ##
使用`forward()` 和`back()`可以实现页面前进和后退功能。
from selenium import webdriver
import time
brower = webdriver.Chrome()
brower.get(‘https://www.taobao.com’)
brower.get(‘https://blog.csdn.net/qq_25343557’)
time.sleep(2)
brower.back()
time.sleep(2)
brower.forward()
time.sleep(2)
brower.close()
## Cookie操作 ##
使用`get_cookies()` 获取cookie,`delete_all_cookies()` 删除所有cookie,`add_cookie()` 添加cookie。
from selenium import webdriver
brower = webdriver.Chrome()
brower.get(‘https://blog.csdn.net/qq_25343557’)
print(brower.get_cookies())#获取cookies
brower.delete_all_cookies()#删除cookies
print(brower.get_cookies())
brower.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’, ‘secure’:True})#添加cookie,必须包含name和value
print(brower.get_cookies())
brower.close()
![这里写图片描述](https://img-blog.csdn.net/20180910100817733?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI1MzQzNTU3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
## 选项卡切换 ##
使用`switch_to.window()` 切换到指定的选项卡,参数为选项卡代号。使用`window_handles`获取当前开启的所有选项卡。
示例:
from selenium import webdriver
import time
brower = webdriver.Chrome()
brower.get(‘https://www.baidu.com’)
time.sleep(1)
brower.execute_script(‘window.open()’)#执行js开启新的选项卡
handle = brower.window_handles
brower.switch_to.window(handle[1])#切换到新的选项卡
brower.get(‘https://www.taobao.com’)
time.sleep(1)
brower.switch_to.window(handle[0])
time.sleep(1)
brower.switch_to.window(handle[1])
time.sleep(1)
brower.close()
----------
## 练习 ##
**请爬取[卡推漫画](http://www.katui.net/)中任意一部漫画?尝试使用多种方法爬取哦!交流请评论**