Selenium手册

前言

​ 通过爬虫直接抓取网页HTML源码里面的数据可能并没有我们想要的数据,这是因为网页通过JavaScript动态渲染过了。除了Ajax技术外,有些网页不通过Ajax而是通过JavaScript来直接渲染页面。就算是能通过Ajax抓取,有一些比如淘宝网的Ajax接口里面拥有加密技术,很难找出其中的规律所以很难通过Ajax进行抓取。

一、引入

​ Python里面提供了许多模拟浏览器运行的库,在这里主要举例较为常见的Selenium,通过这个库就不用为动态渲染的网页发愁了。

二、Selenium的基本使用

2.1、准备

​ 在使用Selenium操作谷歌浏览器之前必须下载谷歌驱动才能使用,需要下载对应或者相近版本的谷歌浏览器驱动。除了点击右上角三个点里面去查看版本号,再就是通过搜索:chrome://version/查看版本号。

下载谷歌浏览器驱动程序∶https://chromedriver.storage.googleapis.com/index.html

国内下载谷歌地址可能比较慢,我们可以通过阿里的镜像站下载,地址:https://registry.npmmirror.com/binary.html?path=chromedriver/

如果安装谷歌浏览器其驱动时,找不到匹配浏览器最新版本的驱动,如我的浏览器为最新版本的,进入:https://googlechromelabs.github.io/chrome-for-testing/

备注:下载的驱动放在和编写代码的同级目录下,放在其他路径则需要指定路径地址。

2.2、声明浏览器对象
from selenium import webdriver

# 下面各种浏览器的声明种类,驱动在代码同级目录则无需指定路径
browser = webdriver.Chrome()
browser = webdirver.Firefox()
browser = webdirver.Edge()
browser = webdirver.PhantomJS() # 无界面浏览器
browser = webdriver.Safari()

# 初始化浏览器对象--------------------------------------------------------------------
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
 
# 新版本写法
browser = webdriver.Chrome(service=Service(r'D:\software\PyCharmLib\chromedriver.exe'))
# 旧版写法
# browser = webdriver.Chrome(r'D:\software\PyCharmLib\chromedriver.exe')
 
browser.get('http://www.baidu.com')
# 新版写法
search = browser.find_element(by=By.ID, value='kw')
# 旧版写法
# search = browser.find_element_by_id('kw')
search.send_keys('python')
search.send_keys(Keys.ENTER)
 
# 关闭浏览器
browser.close()
# 打开浏览器任务结束会直接关闭浏览器,不想关闭浏览器下面的方法
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# options.add_argument("–ignore-certificate-errors")  忽略不信任证书
webdriver = webdriver.Chrome(options=option) # 防止程序结束关闭浏览器
2.3、访问页面

​ 简单的示例来进行selenium运用。

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

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input_third = browser.find_element(by=By.XPATH, value='//*[@id="q"]') # 获取标签
print(input_third)
browser.close() # 关闭浏览器
2.4、设置浏览器大小、刷新、后退前进页面
# 设置浏览器大小为500*500像素
browser.set_window_size(500, 500)

# 设置浏览器全屏
browser.maximize_window()

# 刷新页面,等同于f5刷新网页
browser.refresh()

# forward()方法可以用来实现前进下一页面,back()可以用来实现后退上一页面。(就是浏览器左上角左和右箭头功能一样)
browser.forward()
browser.back()
# 随机睡眠防止机器识别爬虫
time.sleep(random.uniform(intx,inty)) 
2.5、获取页面基础属性
# 浏览器标题
title = browser.title
# 当前浏览器打开的网页网址
url = browser.current_url
# 浏览器名(用的什么浏览器)
name = browser.name
# 浏览器源码
source = browser.page_source

三、Selenium定位元素

节点交互:输入文字时使用send_key( )方法,清空文字使用clear( )方法,点击按钮时使用click( )方法。

3.1 ID定位
# 获取网页首页id为:toolbar-search-input的搜索框,并且输入python
from selenium.webdriver.common.by import By # 定位一定要映入By类
 
browser.find_element(By.ID, 'toolbar-search-input').send_keys('Python') # 输入值
3.2 NAME定位
# 获取百度首页name为wd的搜索框,并且输入python
browser.find_element(By.NAME, 'wd').send_keys('Python')
3.3 CLASS定位
# 获取百度首页classname为s_ipt的搜索框,并且输入python
browser.find_element(By.CLASS_NAME, 's_ipt').send_keys('Python')
3.4 tag定位 (标签匹配)
#获取csdn首页tag为h3的文本内容
h = browser.find_element(By.TAG_NAME, 'h3').text
3.5 link定位(a标签内文本)
# 获取百度首页link内容为新闻的链接,并点击(文本定位,且必须是超链接即a标签)
browser.find_element(By.LINK_TEXT, '新闻').click()
3.6 partial定位(模糊匹配文本)
# (具有部分链接文本值与位置匹配的第一个元素将被返回。)
# 获取csdn首页link内容为课程的模糊检索链接,并点击,页面显示的是:下载·课程
browser.find_element(By.PARTIAL_LINK_TEXT, '课程').click()
3.7 Xpath定位
# 获取csdn首页,通过xpath检索搜索框,并输入python内容
browser.find_element(By.XPATH, "//*[@id='toolbar-search-input']").send_keys('Python')
3.8 CSS定位(css选择器)
# 获取csdn首页,通过css写法,获取id为toolbar-search-input的搜索框
browser.find_element(By.CSS_SELECTOR, "#toolbar-search-input").send_keys('Python')
3.9 文本定位(和link不一样)

​ 能不能直接通过文本内容去定位元素,但是这个元素又不是超链接a,此时可以通过下面的方法来定位元素。注意的是也是优先捕捉第一个检测到的元素,属于模糊搜索

# 通过文本定位任意元素
browser.find_element(By.XPATH, "//*[contains(text(), '你想要定位的文本内容')]")
3.10 多元素
# 写法如下,selement和selements分别是获取第一个,后者是获取id为'id'的列表
find_selement(By.ID, 'id').click()
find_selements(By.ID, 'id')

四、Selenium获取元素属性

​ 通过第3点的定位方式,我们已经基本掌握了全部定位方式。那么我就可以通过定位来获取定位元素的属性了,在通过Selenium数据收集/网络爬虫的时候,能让我们更方便进行数据采集。

4.1 获取属性- get_attribute()
from selenium import webdriver

# 通过Xpath获取图片标签
logo = browser.find_element(By.XPATH, "//div[@class='toolbar-subMenu-box']//img")
# 提取img标签里面的title属性的值和src属性的值
logo.get_attribute('title')
logo.get_attribute('src')
4.2 获取文本
# 通过Xpath获取a标签里面的文本值
txt = browser.find_element(By.XPATH, "//dd[@class='desc']//a").text
4.3 获取其他属性 - id、location、size、tag_name

​ 除了获取文本之外,我们还需要关注几个常用属性。例如id、locaition位置、size大小(图片)、tag_name标签名等。

# 通过学习
hot_img = browser.find_element(By.XPATH, "//dt[@data-v-e8da5228]/a/img")
print(hot_img.text) # 打印文本内容,若标签里面没有则打印空值
print(hot_img.id) # 打印标签id(一串字母加数字的字符串,不常用)
print(hot_img.location) # 打印属性所在位置,{'x':0,'y':290}。
print(hot_img.tag_name) # 打印标签名
print(hot_img.size) # 图片大小,{'height':0,'width':0}

五、Selenium交互效果

5.1 回车确认 - submit()
inputs = browser.find_element(By.ID, 'kw').send_keys('Python') # 输入搜索内容
time.sleep(1) # 等待输入完成
# 搜索python
inputs.submit() # 模拟键盘上的回车
5.2 单选、多选

​ 有时候网页上的元素需要鼠标悬停出现元素才能点击。再selenium中没有专门的这种方法函数,所以思路是直接源码定位到这个悬停出现的单选元素。然后click()点击一下就可以。

from selenium.webdriver.common.action_chains import ActionChains
# 鼠标悬停操作,开始之前记得导入上面的库
div_element = browser.find_element(By.ID, 's-usersetting-top')
ActionChains(browser).move_to_element(div_element).perform()
time.sleep(1)
# 悬停之后出现选项,按照正常的定位去点击元素就行了
5.3 下拉框 -Select
  1. 定位选择框的方法:
    • select_by_index() # 通过索引定位,index从0开始算
    • select_by_visible_text() # 通过文本值定位,即下拉框的值
  2. 取消已选中项的方法:
    • deselect_all() # 取消已选中的所有项
    • deselect_by_index() # 取消已选中的等于index索引的项
    • deselect_by_visible_text() # 取消已选中的等于文本值的项
from selenium.webdriver.support.select import Select

sel = Select(browser.find_element(By.NAME, 'fruit'))  #选中下拉框元素

# 通过index定位
sel.select_by_index(1)
print('第一个选中项:%s'%(sel.first_selected_option.text))

# 通过文本定位
sel.select_by_visible_text('西瓜')
time.sleep(2)
5.4 处理弹窗

​ 有时候使用selenium操作网页的时候会遇见alert提示弹窗、confirm取消和确定弹窗、输入内容的prompt弹窗。核心方法有:

text()  # 获取文本值
accept()  # 点击确认
dismiss()  # 点击取消或者是关闭对话框
send_keys() # 输入文本值,仅限于prompt,在alert和confirm上是没有输入框的
# 用于提示----------------------------------------
# 定位到元素
browser.find_element(By.ID, 'alert').click()
# 切换到alert上
alert = browser.switch_to.alert
alert.accept()      # 相当于点击确认按钮

# 用于确认----------------------------------------
# 定位元素
browser.find_element(By.ID, 'confirm').click()
# 切换到alert上
confirm = browser.switch_to.alert
# 相当于点击确认按钮
confirm.accept()

# 用于输入内容----------------------------------------
# 定位元素
browser.find_element(By.ID, 'prompt').click()
# 切换到alert
prompt = browser.switch_to.alert
# 输入文本
prompt.send_keys('记得点个赞!!!')
prompt.accept() # 相当于点击确认按钮

六、浏览器窗口和ifrme的切换

​ 在使用selenium爬虫的过程中会遇见嵌入页面iframe网页标签。还有不断地点击进入其他网页会产生很多网页窗口。这个时候我们需要切换网页窗口进行操作,所以下面示例进入不同网页中的操作。

6.1 父子页面切换—iframe网页标签
switch_to.frame()          # 切换同一页面的不同子页面
switch_to.parent_frame()   # 切换回父页面
# 如果iframe有name或id的话,直接使用switch_to_frame
driver.switch_to_frame('id或name值')  # 进入到iframe框架
# 如果iframe没有name或者id的时
# 先定位到iframe
elementi = driver.switch_to.frame('frame_content')
# 再将定位对象传给switch_to_frame()方法
driver.switch_to_frame(elementi)
'''
可以通过switch_to.parent_content(后退到父节点)方法跳出当前iframe,或者还可以通过switch_to.default_content(跳出)方法跳回最外层的页面
'''
6.2 浏览器选项卡窗口切换
  • 关闭标签页:browser.close()
  • 切换标签页:browser.switch_to.window()
  • 显示全部标签页:browser.window_handles(返回当前浏览器的所有窗口的句柄)
# 获取打开的多个窗口句柄
windows = driver.window_handles
# 切换到当前最新打开的窗口,索引-1表示直接选择最后一个,即最新的选项卡
driver.switch_to.window(windows[-1])
driver.close() # 关闭当前页

七、模拟鼠标操作

​ 上面的所有操作都是讲的如何模拟浏览器去操作,我们有时候也需要用到selenium去模拟键盘和鼠标,主要是通过ActionChains模块即可实现鼠标的基本操作。

# 首先先导入库
from selenium.webdriver.common.action_chains import ActionChains

# 左键点击click(),常用的。

# 右键点击—— context_click()
ActionChains(browser).context_click('选中的元素').perform()

# 双击—— double_click()
ActionChains(browser).double_click('选中的元素').perform()

# 悬停—— move_to_element()
ActionChains(browser).move_to_element('选中的元素').perform()

# 拖拽—— drag_and_drop()
ActionChains(browser).drag_and_drop('选中的元素').perform()

# 定位移动—— move_by_offset()
ActionChains(driver).move_by_offset(x, y).click().perform()
# 重置定位
action.reset_actions()

八、模拟键盘操作

​ 模拟鼠标使用的是ActionChains,当然还有模拟键盘的操作,模拟键盘使用的是Keys模块,通过send_keys()、key_down()、key_up() 等方法来搭配使用。

Keys.BACK_SPACE Keys.SPACE Keys.TAB Keys.ESCAPE Keys.ENTER
删除键 空格 制表键 回退键 回车键
Keys.ALT Keys.CONTROL Keys.SHIFT Keys.F1...Keys.F12
alt键 ctrl键 shift键 f1到f12键
'''
from selenium.webdriver.common.keys import Keys
常用的组合按键
send_keys(Keys.CONTROL, 'a')         # 全选,ctrl+a
send_keys(Keys.CONTROL, 'x')         # 裁剪,ctrl+x
send_keys(Keys.CONTROL, 'c')         # 复制,ctrl+c
send_keys(Keys.CONTROL, 'v')         # 粘贴,ctrl+v
'''
'''
上面的使用不行的话,直接使用下面的方法(完全模拟真实操作)
ActionChains(driver).key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()
'''

九、加载等待

​ 通过selenium来爬取网页的时候,由于网速以及网站服务器的带宽导致网页全部加载完成的速度有所差别。有时候通过selenium定位一个元素会因为加载时间太快导致定位不到元素,所以需要使用到selenium中的两个等待方式,分别为“隐式等待”“显式等待”

9.1 隐式等待

​ 即当查找节点时并没有立即出现的时候,隐式等待讲等待一段时间再查找节点,默认时间为0。关键字:没出现,按照设置的时间等待完成后再查找。

driver.implicitly_wait(5) # 等待5秒后在查找元素,再找不到则抛出异常
9.2 显式等待(推荐)

​ 隐式等待的效果其实并没有那么好,因为没有立刻找到元素,程序会根据设置的时间到了在查找一遍。而显式等待它指定一个最长等待时间,在这个时间内只要找到了元素就返回查找的节点,到了规定时间没找到,则抛出超时异常。

from selenium.webdriver.support.ui import WebDriverWait

# 使用第一种方法---------------------------------------------------
WebDriverWait(driver, 10).until(lambda _: driver.find_element(
by=By.ID, value='kw').send_keys('selenium')

# 使用第二种方法--------------------------------------------------------
webwait = WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)       
'''
    driver:浏览器驱动
    timeout:超时时间,秒
    poll_frequency:检测频率,默认是0.5秒一次
    ignored_exceptions:超时后的报错信息,默认是NoSuchElementException异常
'''                
# 增加判断---------------------------------------------------------------
webwait.until(method,msg='') # until_not()方法即条件相反
'''
    method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False
    msg:如果超时,抛出TimeoutException,将msg传入异常
'''   

十、补充

10.1 Javascript调用
# 下拉滚动条
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
# 弹出提示框
driver.execute_script('alert("到底了。")')
# 修改元素属性
driver.execute_script("arguments[0].setAttribute(arguments[1],arguments[2])", '元素', '属性名', '属性值')
10.2 Cookie调用
# 添加cookie
browser.add_cookie(cookie_dict=)
# 获取某个cookie
browser.get_cookie(name=)
# 获取全部cookie
browser.get_cookies()
# 删除某个cookie
browser.delete_cookie(name=)
# 删除全部cookie
browser.delete_all_cookies()

10.3 反屏蔽

一般来讲,使用selenium访问某个网址(浏览器以Chrome为例),都会有`Chrome正受到自动测试软件的控制`的提示。检测当前浏览器窗口下的window.navigator对象是否包含webdriver这个属性。因为在正常使用浏览器的情况下,这个属性是undefined的,然而,一旦我们使用了selenium,selenium会给Window.navigator设置webdriver属性,很多网站就通过JavaScript判断,如果webdriver存在就直接屏蔽。

Ps:方法这里就不罗列了,遇到这种情况首先通过自己手动打开浏览器可以进入网站,而通过selenium进不去,知道原因就行,遇到了在网上查找对应方法设置一下就行。

posted @ 2023-12-28 21:15  CloudWK  阅读(179)  评论(0编辑  收藏  举报