本系列文档用于对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
是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。
可以将Selenium
理解相当于一个机器人,可以模拟人类在浏览器上的一切行为,自动处理浏览器上的一些行为。
Chromedriver
是一个驱动Chrome
浏览器的驱动程序,使用它才可以驱动浏览器。
Headless Chrome
在Chrome59中开始搭载HeadlessChrome。这是一种在无需显示headless的环境下运行Chrom浏览器的方式。从本质上来说,就是不用chrome浏览器来运行Chrome的功能!
自从Selenium
和PhantomJS
"分手"之后,使用Selenium
+Headless Chrome
成为主流。
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()
更多教程请参考: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语法来获取元素,等价于:input_kw = driver.find_element_by_xpath('//input[@id="kw"]')
input_kw = driver.find_element(By.XPATH, '//input[@id="kw"]')
使用selenium中xpath获取元素属性值得时候和真实的xpath语法有些不同,例如获取a标签的href属性值,在真实的xpath语法中使用//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
标签,在网页中是通过鼠标点击的,因此想要选中checbox
标签,那么先选中这个标签,然后执行click()
事件,代码如下:# 根据name获取元素
rememberEle = driver.find_element_by_name('remember')
rememberEle.click()
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')
其他截屏方法:
driver.get_screenshot_as_file('/Screenshots/foo.png')
script = "var callback = arguments[arguments.length - 1]; "
script2 = "window.setTimeout(function(){ callback('timeout') }, 3000);"
driver.execute_async_script(script + script2)