网页操控与数据爬取 Selenium的简单使用

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » 网页操控与数据爬取 Selenium的简单使用

Selenium是一个用于网站应用程序自动化的工具。它可以直接运行在浏览器中,就像真正的用户一样浏览网页。它支持的浏览器包括IE、Firefox、Safari、Google Chrome和Opera等,同时支持多种编程语言,例如Java、Python、.NET、Ruby等。有几篇文章介绍过Selenium的基本使用,感觉不是太详细,这篇文章再做一次整理!

了解Selenium

Jason Huggins在2004年发起了Selenium项目,主要是为了不想让自己的时间浪费的无聊的重复性工作中。当时测试的浏览器都支持JavaScript,因此Jason和他所在的团队采用JavaScript编写一种测试工具来验证浏览器页面的行为。这个JavaScript类库就是Selenium core,同时也是Selenium RC、Selenium IDE的核心组件。

从Selenium诞生至今一共发展了3个版本:Selenium 1.0、Selenium 2.0和Selenium 3.0。每个版本的更新都会有一些变化,这里不进行详细介绍。Selenium不仅在自动化测试和自动化流程开发的领域上占据着重要位置,而且在网络爬虫上也被广泛使用。

安装Selenium

Selenium支持多种浏览器,鳄鱼君Ba以Chrome浏览器进行介绍。首先使用pip命令安装Selenium库:pip install selenium

Selenium的安装相对简单,接下来是按照Chrome的WebDriver。首先查看Chrome的版本信息,不同的版本对应不同的WebDriver:浏览器找到“设置”——“关于Chrome”,查看Chrome的版本信息。另一种方式是在浏览器的地址上输入:chrome://setings/help并回车,即可看到浏览器的版本信息:

网页操控与数据爬取 Selenium的简单使用

浏览器驱动下载:chromedrivergeckodriver ,浏览器版本为74,驱动下载以74开头的。之后解压文件,找到chromedriver.exe直接放置在Python的安装目录。启动Selenium代码:

# 导入Selenium的webdriver类
from selenium import webdriver
# 设置变量url:用于浏览器访问
url='https://www.e1yu.com/'
# 将webdriver类实例化,将浏览器设定为Chrome
# 参数executable_path是设置chromedriver驱动的路径
path='F:\Python3.7.7/chromedriver.exe'
driver=webdriver.Chrome(executable_path=path)
# 打开浏览器并访问网址
driver.get(url)

首先导入Selenium库的webdriver类、webdriver类实例化并指定浏览器、打开浏览器访问网址。如果chromedriver.exe是存放在Python的安装目录中,在webdriver类实例化的时候,可以无需设置参数executable_path;但如果chromedriver.exe是存放在其他目录,在实例化的时候要设置参数executable_path来指向chromedriver.exe所在的位置。上述代码运行后,程序会自动打开一个新的Google Chrome。

Selenium还可以控制其他浏览器,配置方法与配置Chrome方式一样,此处只列出Selenium的具体代码:

from selenium import webdriver
browser=webdriver.Chrome() #谷歌浏览器
browser=webdriver.Firefox() #火狐浏览器
browser=webdriver.Safari()  #国人很少用的浏览器safari
browser=webdriver.Edge()   #微软旗下的浏览器
browser=webdriver.PhantomJS()  #无界面浏览器

网页元素定位

Selenium定位网页元素主要通过元素的属性值或者元素的HTML里的路径位置,定位方式一共有8中,代码参考:

# 通过属性id和name定位
find_element_by_id()
find_element_by_name()
# 通过HTML标签类型和属性class定位
find_element_by_class_name()
find_element_by_tag_name()
# 通过标签值实现定位,partial_link用于模糊匹配
find_element_by_link_text()
find_element_by_partial_link_text()
# 元素的路径定位选择器
find_element_by_xpath()
find_element_by_css_selector()

(1)find_element_by_idfind_element_by_name分别通过元素属性id和name的属性值来定位。如果被定位的元素不存在属性id或name,则无法使用这种定位方式。通常情况下,一个网页中,元素的id或name的属性值是唯一的,如果多个元素的id或name相同,这种定位方式只能定位第一个元素。
(2)find_element_by_class_namefind_element_by_tag_name分别通过元素属性class和元素标签类型进行定位。在一个网页里,属性class的属性值可以被多个元素使用,同一个元素标签也可以多次使用,正因如此,这两种定位方式只能定位符合条件的第一个元素。
(3)find_element_by_link_textfind_element_by_partial_link_text是根据标签值进行定位。若网页中的文字并不是唯一的,那么Selenium也是默认定位第一个符合条件的元素。
(4)find_element_by_xpathfind_element_by_css_selector是由xpath和css_selector实现定位,两者是一个定位选择器,通过标签的路径来实现定位。标签的路径是指当前标签在整个HTML代码里的代码位置。在主流的浏览器开发者工具中,都可以复制xpath和css selector,这里仅作参考语法,有时候还需要自己判断。

上述8种定位方式只能定位的第一个元素,如果有多个相同的元素,并且想全部获取,需要将element修改为elements即可,方法不变。前者只是是获取第一个符合条件的元素,后者定位全部符合条件的元素。

网页元素操控

操控网页元素在网页元素定位后才能执行,Selenium可以模拟任何操作,比如单击、右击、拖拉、滚动、复制粘贴或者文本输入等等,操作方式可分为三大类:常规操作鼠标事件操作键盘事件操作

常规操作包含文本清除文本输入单击元素提交表单获取元素值等。以鳄鱼君Ba为例注册用户:

from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.e1yu.com/')
# 我要注册按钮
driver.find_element_by_xpath('/html/body/header/section/div[1]/div[2]/a').click() # 点击注册
# 输入用户名,密码,电话
driver.find_element_by_id('user_name').send_keys('Python') # 输入用户名Python
driver.find_element_by_id('user_email').send_keys('3455272613@qq.com') # 邮箱
driver.find_element_by_xpath('//*[@id="register"]/p[4]/label/button').click()# 发送邮箱验证码
time.sleep(5)
key=input('请输入邮箱验证码:')
driver.find_element_by_id('email_authcode').send_keys(key)
time.sleep(3)
driver.find_element_by_id('user_pass').send_keys('123456jdsoa')
driver.find_element_by_id('user_pass2').send_keys('123456jdsoa')
# 注册按钮
driver.find_element_by_xpath('//*[@id="register"]/p[7]/input').submit() # 注册按钮

其中click和submit在某些情况下可以相互使用,submit只用于表单的提交按钮;click是强调事件的独立性,可用于任何按钮。此外,我们还列出一些实际开发中常见的操作方式:

# 清空X标签的内容
driver.find_element_by_id('X').clear()
# 获取元素在网页中的坐标位置,坐标格式{‘y’:22,‘x’:132}
location=driver.find_element_by_id('X').location
# 获取元素的某个属性值,列如获取X的id属性值
id_name=driver.find_element_by_id('X').get_attribute('id')
# 判断X元素在网页上是否可见,返回值为True或False
result=driver.find_element_by_id('X').is_displayed()
# 判断X元素是否被选,常用于checkbox和radio标签,返回值为True或False
result=driver.find_element_by_id('X').is_selected()
#-----------select标签的方法----------
from selenium.webdriver.support.select import Select
# 根据下拉框的索引选择
Select(driver.find_element_by_id('X')).select_by_index('1')
# 根据下拉框的value属性来选择
Select(driver.find_element_by_id('X')).select_by_index('Python')
# 根据下拉框的值选择
Select(driver.find_element_by_id('X')).select_by_visible_text('Python')

上述是元素常规操作方法,接着讲述鼠标事件操作方法,鼠标事件操作由Selenium的ActionChains类来实现。ActionChains类定义了多种鼠标操作方法,具体的操作方法:

操作方法 说明 示例
perform 执行鼠标事件 click(element).perform()
click是鼠标单击事件
perform是执行这个单击事件
reset_actions 取消鼠标事件 click(element).reset_actions()
click是鼠标单击事件
reset_actions是执行这个单击事件
click 鼠标单击 click(element)
element是某个元素对象
click_and_hold 长按鼠标左键 click_and_hold(element)
element是某个元素对象
context_click 长按鼠标右键 context_click(element)
element是某个元素对象
double_click 鼠标双击 double_click(element)
element是某个元素对象
drag_and_drop 对元素长按左键并移动到另一个元素的位置后释放鼠标左键 drag_and_drop(element1,element2)
element1是某个元素对象
element2是目标元素对象
drag_and_drop_by_offset 对元素长按左键并移动到指定坐标位置 drag_and_drop_by_offset(element1,x,y)
element1是某个元素对象
x是偏移的x坐标
y是偏移的y坐标
key_down 对元素长按键盘中的某个按键 key_down(Keys.CONTROL,element)
element是某个元素对象
Keys.CONTROL是由Keys定义的键盘事件
key_up 对元素释放键盘中的某个按键 key_up(Keys.CONTROL,element)
element是某个元素对象
Keys.CONTROL是由Keys定义的键盘事件
move_by_offset 对当前鼠标所在位置进行偏移 move_by_offset(x,y)
x是偏移的x坐标
y是偏移的y坐标
move_to_element 将鼠标移动到某个元素所在的位置 move_to_element(element)
element是某个元素对象
move_to_element_with_offset 将鼠标移动到某个元素并偏移一定的位置 move_to_element_with_offset(element,x,y)
element是某个元素对象
x是偏移的x坐标
y是偏移的y坐标
pause 设置暂停执行时间 pause(1000)
release 释放鼠标长按操作 release(element)
element是某个元素对象
如果element为空,对当前鼠标的位置进行长按操作进行释放。
send_keys 执行文本输入 send_key(value)
value是输入内容
send_keys_to_element 对当前元素执行文本输入 send_keys_to_element(element,value)
element是某个元素对象
value是输入内容

这些方法都是在ActionChains类所定义的类方法,若想使用这些操作方法,必须将ActionChains类实例化后才能调用。以CSDN登录页面为例,使用用户名加密码的方式登录会出现滑块验证。具体代码如下:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 双击登录
element=driver.find_element_by_xpath('//*[@id="csdn_container_tool"]/div/ul/li[4]/a')
ActionChains(driver).double_click(element).perform()
# 延时
time.sleep(3)
# 切换密码登录
driver.find_element_by_xpath('//*[@id="app"]/div/div/div[1]/div[2]/div[5]/ul/li[2]/a').click()
time.sleep(1)
driver.find_element_by_id('all').send_keys('13673770772')
driver.find_element_by_id('password-number').send_keys('1897745389dsgmmc')
# 点击登录按钮会出现验证码
driver.find_element_by_xpath('//*[@id="app"]/div/div/div[1]/div[2]/div[5]/div/div[6]/div/button').click()
time.sleep(3)
# 找到滑块并滑动
element=driver.find_element_by_id('nc_1_n1z')
ActionChains(driver).drag_and_drop_by_offset(element,300,0).perform()
time.sleep(3)

目前CSDN登录出现的为滑块验证,使用selenium操控会被识别为机器人,所以即使滑动滑块也不会登录成功,主要就是练习下如何应对滑块验证码,很多大型网站出现滑块验证码,使用Selenium操控滑块都会失败:

网页操控与数据爬取 Selenium的简单使用

代码首先将ActionChains实例化,实例化的时候传入driver对象。driver是chromedriver打开的浏览器对象,这是告诉ActionChains的操作浏览器对象是driver。实例化之后就可以直接调用鼠标事件操作方法,这些方法需要传入element对象,element是网页中某个标签元素。最后再调用perform方法,这是一个执行命令,因为鼠标操作可以拖拉、长按鼠标的左键或右键,这是一个持久性的操作,而调用perform方法可以让这个鼠标操作马上执行。

接着是键盘事件操作,它是模拟键盘上的某个按键,主要通过send_keys方法来实现。以百度搜索为例,利用快捷键实现搜索内容的变换:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
# 获取输入框标签
element=driver.find_element_by_id('kw')
# 输入框输入内容
element.send_keys('鳄鱼君Ba')
time.sleep(3)

# 删除最后一个文字
element.send_keys(Keys.BACK_SPACE)
time.sleep(3)

# 添加输入空格键+a
element.send_keys(Keys.SPACE)
element.send_keys('a')
time.sleep(2)

# ctrl +a全选输入框内容
element.send_keys(Keys.CONTROL,'a')
time.sleep(2)
# ctrl+x剪切输入框neir
element.send_keys(Keys.CONTROL,'x')
time.sleep(2)
# ctrl+v粘贴内容到输入框
element.send_keys(Keys.CONTROL,'v')
time.sleep(2)
# 通过回车键来代替单击操作
driver.find_element_by_id('su').send_keys(Keys.ENTER)

运行代码就会看到具体的键盘操作。Keys类定义了很多键盘的快捷键,可以查看源代码。在pycharm中查看源代码非常简单,按住Ctrl键,将鼠标放到Keys并单击,即可看到所有的快捷键!

常用功能

Selenium常用功能:设置浏览器的参数、浏览器多窗口切换、设置等待时间、文件的上传与下载、Cookies处理以及frame框架操作。

设置浏览器的参数是在定义driver的时候设置chrome_options参数,该参数是一个Options类所实例化的对象。其中常用的参数是设置浏览器是否可视化浏览器的请求头等信息,前者可以加快代码运行速度,后者可以有效地防止网站的反爬虫检测。具体的代码如下:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Options类实例化
options=Options()
# 设置浏览器参数
# ——headless是不显示浏览器窗口及执行过程
options.add_argument('--headless')
# 设置lang和User-Agent信息
options.add_argument('lang=zh_CN.UTF-8')
User_Agent='Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)'
options.add_argument('User-Agent='+User_Agent)
# 启动浏览器并设置chrome_options
driver=webdriver.Chrome(options=options)
driver.get('https://www.baidu.com/')
print(driver.page_source)
# # 浏览器窗口最大化
# driver.maximize_window()
# # 浏览器窗口最小化
# driver.minimize_window()
# # 获取网页的标题内容
# driver.title()
# # 获取网页的HTML
# print(driver.page_source)

浏览器多窗口切换是在同一个浏览器中切换不同的网页窗口。打开浏览器可以看到,浏览器顶部可以不断添加新的窗口,而Selenium可以通过窗口切换来获取不同的网页信息。具体代码如下:

from selenium import webdriver
import time
driver=webdriver.Chrome()
driver.get('https://www.e1yu.com/')
# 使用JavaScript开启新的窗口
js="window.open('https://www.e1yu.com/')"
driver.execute_script(js)
# 获取当前显示的窗口信息
current_window=driver.current_window_handle
# 获取浏览器的全部窗口信息
handles=driver.window_handles
# 设置延时可以看到切换效果
time.sleep(1)
driver.switch_to.window(handles[0])
time.sleep(1)
driver.switch_to.window(handles[1])

上述代码中,使用了execute_script方法,这是通过浏览器运行JavaScript代码生成新的窗口,然后获取浏览器上的全部窗口信息,window_handles方法是获取当前浏览器的窗口信息,并以列表的形式表示,最后由switch_to.window方法进行窗口之间的切换。

Selenium的执行速度相当快,在Selenium执行的过程中往往需要等待网页的响应才能执行下一个步骤,否则程序会抛出异常信息。网页响的应快慢取决于多方面因素,因此在某些操作之间需要设置一个等待时间,让Selenium与网页响应尽量达到同步执行,这样才能保证程序的稳健性。在前面的例子中,延时是使用Python内置的time模块来实现的,而Selenium本身提供了一些延时的功能,具体的使用方法如下:

from selenium import webdriver
driver=webdriver.Chrome()
driver.get('https://www.baidu.com/')
# 隐性等待,最长等待时间30s
driver.implicitly_wait(30)
driver.find_element_by_id('kw').send_keys('鳄鱼君Ba')
# 显性等待
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
# visibility_of_element_located检查网页元素是否可见
# (By.ID,'kw):kw是百度输入框的id,By.ID是使用find_element_by_id定位
condition=expected_conditions.visibility_of_element_located(
    (By.ID,'kw')
)
WebDriverWait(driver,timeout=30,poll_frequency=0.5).until(condition)

隐性等待是在一个设定的时间内检测网页是否加载完成,也就是一般情况下你看到浏览器标签栏那个小圈不再转,才会执行下一步。比如代码中设置30秒等待时间,网页只要在30秒内完成加载就会自动执行下一步,如果超出30秒就会抛出异常。值得注意的是,隐性等待对整个driver的周期都起作用,所以只要设置一次即可。

显性等待能够根据判断条件而进行灵活地等待,程序每隔一段时间检测一次,如果检测结果与条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间为止,然后抛出TimeoutException异常。显性等待的使用涉及到多个模块:Byexpected_conditionsWebDriverWait

● By:设置元素定位方式。定位方式共8种,分别是ID 、XPATH、LINK_TEXT、PARTIAL_LINK_TEXT、NAME、TAG_NAME、CLASS_NAME、CSS_SELECTOR。
● expected_conditions:验证网页元素是否存在,提供了多种验证方式。
WebDriverWait的参数说明:
● driver:浏览器对象driver。
● timeout:超时时间,等待的最长时间。
● poll_frequency:检测时间的间隔。
● ignored_exceptions:忽略的异常,如果在调用until或until_not的过程中抛出的异常在这个参数里,则不中断代码,继续等待,如果抛出的异常在这个参数之外,则中断代码并抛出异常。默认值为NoSuchElementException。
● until:条件判断,参数必须为expected_conditions对象。如果网页里某个元素与条件符合,则中断等待并执行下一个步骤。
● until_not:与until的逻辑相反。

隐性等待和显性等待相比于time.sleep这种强制等待更为灵活和智能,可解决各种网络延误的问题,隐性等待和显性等待可以同时使用,但最长的等待时间取决于两者之间的最大数。

上传文件在网页中用上传按钮来显示,通过单击按钮就会打开本地电脑的一个文件对话框,在文件对话框选择文件并确认即可上存文件路径。而Selenium实现过程相对简单,只需定位到网页的上传按钮并使用send_keys方法来写入文件路径(绝对路径)即可实现,代码参考:

from selenium import webdriver
driver=webdriver.Chrome()
driver.get('https://images.ac.cn/simple.html')# 某图床网站
driver.find_element_by_name('file').send_keys('F:\\scratches\\scratches\\1.jpg')

文件下载的原理与文件上存是一样的,但是Chrome浏览器可能会弹出阻止下载窗口,这里可以使用Firefox,具体代码如下:

from selenium import webdriver
# 设置文件保存位置,默认系统的Download文件夹
options=webdriver.ChromeOptions()
prefs={'download.default_directory':'F:\\'}
options.add_experimental_option('prefs',prefs)
# 启动浏览器
driver=webdriver.Chrome()
driver.get('http://stdl.qq.com/stdl/qqbrowser/wechat/chatother/index.html')# PC微信
driver.maximize_window()
# 找到下载按钮并下载
driver.find_element_by_xpath('/html/body/div/a').click()

浏览器Cookies的使用,Cookies操作无非就是读取、添加和删除Cookies。Cookies信息可以在浏览器开发者工具的Network标签页查看。

from selenium import webdriver
import time
# 启动浏览器
driver=webdriver.Chrome()
driver.get('https://www.baidu.com')
time.sleep(2)
# 添加Cookies
driver.add_cookie({'name':'www.e1yu.com','value':'123456'})
# 获取全部Cookies
all_cookies=driver.get_cookies()
print('全部的cookies为:%s' % all_cookies)
# 获取name为www.e1yu.com的cookie内容
one_cookie=driver.get_cookie('www.e1yu.com')
print('单个cookie为:%s' % one_cookie)
# 删除name为www.e1yu.com的cookie
driver.delete_cookie('www.e1yu.com')
surplus=driver.get_cookies()
print('剩余的cookies为:%s' % surplus)
# 删除全部cookies
driver.delete_all_cookies()
surplus_cookies=driver.get_cookies()
print('剩余的cookies为:%s' % surplus)

代码输出的Cookies信息以列表的形式展示,列表的每个元素是一个字典,如果添加cookies,必须存在name和value键值对,expiry键值对需替换删除,这个后面遇到再详细介绍!

frame是一个框架页面,在HTML5已经不支持使用这个框架,但在一些网站中依然会看到它的身影。frame的作用是在HTML代码里面嵌套一个或多个不同的HTML代码,每嵌套一个HTML都需要由frame来实现。以为百度知道为例,随便打开某条题目,题目的回答数最好是0回答

打开开发者工具的Elements标签页,快速定位到文本输入框,在Elements标签页可以看到这个文本框是由iframe框架页面生成的。iframeframe实现的功能是相同的,只不过使用方式和灵活性有所不同,不管是iframe或frame, Selenium的定位和操作方式都是一样的。

网页操控与数据爬取 Selenium的简单使用

由于一个HTML可以嵌套了一个或多个iframe,那么Selenium在操作不同的iframe需要通过switch_to.frame()来切换到指定的iframe,再执行相应的操作。

from selenium import webdriver
driver=webdriver.Chrome()
driver.get('')

# ’‘’‘’‘定位到第一个iframe’‘’‘’‘’
# 通过索引定位
driver.switch_to.frame(0)
# 通过iframe的id或name定位
driver.switch_to.frame('iframe_id')
# 先定位iframe再切换到iframe_id
element=driver.find_element_by_id('iframe_id')
driver.switch_to.frame(element)
# 从iframe_id返回HTML
driver.switch_to.default_content()

# ’‘’‘’‘定位到第二个iframe’‘’‘’‘’
# 通过索引定位
driver.switch_to.frame(1)
# 通过iframe的id或name定位
driver.switch_to.frame('iframe_name')
# 先定位iframe再切换到iframe_id
element=driver.find_element_by_id('iframe_name')
driver.switch_to.frame(element)
# 从iframe_id返回HTML
driver.switch_to.default_content()

遇到具体的网站,在进行具体介绍。

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《网页操控与数据爬取 Selenium的简单使用》 发布于2020-06-05

分享到:
赞(0) 赏杯咖啡

评论 抢沙发

9 + 1 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册