文章目录
准备工作
Selenium是当下较为流行的Python自动化处理框架,适配多种主流浏览器,可以用来处理爬虫过程中的各类反爬验证操作。在使用前首先要安装Selenium库、浏览器以及对应浏览器的驱动程序。
一、安装库
可以使用pip
或conda
安装。
# pip安装
pip install selenium
# pip镜像安装
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
# conda安装
conda install selenium
二、安装浏览器与驱动程序
兼容浏览器 Mozilla Firefox
/ Google Chrome
/ Microsoft Edge
/ Safari
等主流浏览器,默认电脑已经安装,必须有对应的浏览器才可以进行自动化控制。
下面以Chrome
为例演示谷歌浏览器的驱动程序安装过程。
方式一:手动安装
-
查看浏览器版本
在浏览器的地址栏键入
Chrome://version
-
选择对应版本号的驱动版本
下载地址:CNPM Binaries Mirror (npmmirror.com)
下载地址:https://chromedriver.chromium.org/home
-
配置环境变量(可不配,直接使用驱动的绝对路径)
方式二:自动安装
-
安装第三方库
webdriver_manager
pip install webdriver_manager
-
调用第三方库的方法
from selenium import webdriver from selenium.webdriver.common.keys import Keys from webdriver_manager.chrome import ChromeDriverManager # 自动安装驱动,会自动获取当前浏览器的版本并去下载对应的驱动到本地 # 如果本地已经有该浏览器渠道,则会提示其已存在 browser = webdriver.Chrome(ChromeDriverManager().install()) browser.get('http://www.baidu.com') search = browser.find_element_by_id('kw') search.send_keys('python') search.send_keys(Keys.ENTER) # 关闭浏览器 browser.close()
基本用法
一、浏览器对象
浏览器对象是自动化程序的锚点,所有操作都绑定在浏览器对象上进行,需根据对应的浏览器和浏览器驱动生成对应的浏览器对象。
from selenium import webdriver
# 初始化浏览器为chrome浏览器
browser = webdriver.Chrome()
# 指定绝对路径的方式
path = r'C:\Users\Gdc\.wdm\drivers\chromedriver\win32\96.0.4664.45\chromedriver.exe'
browser = webdriver.Chrome(path)
# 关闭浏览器
browser.close()
"""
拓展:通过option参数指定浏览器对象的形式
1. 初始化无界面chrome浏览器
option = webdriver.ChromeOptions()
option.add_argument("--headless")
browser = webdriver.Chrome(options=option)
2. 设置编码格式
options = webdriver.ChromeOptions()
options.add_argument('lang=zh_CN.UTF-8')
browser = webdriver.Chrome(options=options)
3. 添加请求头
options = webdriver.ChromeOptions()
options.add_argument('user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"')
browser = webdriver.Chrome(options=options)
4. 禁止加载图片
options = webdriver.ChromeOptions()
options.add_argument('blink-settings=imagesEnabled=false')
browser = webdriver.Chrome(options=options)
5. 禁用浏览器弹窗
options = webdriver.ChromeOptions()
prefs = {
'profile.default_content_setting_values': {
'notifications': 2
}
}
options.add_experimental_option('prefs', prefs)
browser = webdriver.Chrome(options=options)
6. 禁用JavaScript
options = webdriver.ChromeOptions()
options.add_argument('--disable-javascript')
browser = webdriver.Chrome(options=options)
7. 隐藏滚动条
options = webdriver.ChromeOptions()
options.add_argument('--hide-scrollbars')
browser = webdriver.Chrome(options=options)
8. 以最高权限运行
options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
browser = webdriver.Chrome(options=options)
9. 添加指定插件运行
options = webdriver.ChromeOptions()
extension_path = '想要加载的插件路径'
options.add_extension(extension_path)
browser = webdriver.Chrome(options=options)
"""
二、浏览器窗口操作
用户在生成浏览器对象之后可以对浏览器窗口进行一定的基础调整,例如调整窗口大小、使用代码刷新页面、使用代码前翻页面后翻页面等。
2.1 调整窗口大小
调用浏览器对象set_window_size()
方法可以用来设置浏览器大小(分辨率)。
调用浏览器对象maximize_window()
方法可以设置浏览器为全屏。
from selenium import webdriver
import time
browser = webdriver.Chrome()
# 设置浏览器大小为全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)
# 设置分辨率为500*500
browser.set_window_size(500,500)
time.sleep(2)
# 设置分辨率为1000*800
browser.set_window_size(1000,800)
time.sleep(2)
# 关闭浏览器
browser.close()
2.2 页面刷新
调用浏览器对象refresh()
方法用以进行浏览器对象的页面刷新,相当于F5键。
from selenium import webdriver
import time
browser = webdriver.Chrome()
# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)
try:
# 刷新页面
browser.refresh()
print('刷新页面')
except Exception as e:
print('刷新失败')
# 关闭浏览器
browser.close()
2.3 前进与后退
调用浏览器对象forward()
方法可以用来实现前进。
调用浏览器对象back()
方法可以用来实现后退。
读者可自行尝试,这里不做代码示例。
2.4 窗口切换
-
Frame
切换使用浏览器对象
switch_to_frame()
方法进行指定id
的切换,需要传入切换目标的id
作为参数。若想回到父页面,需要使用浏览器对象
switch_to.parent_frame()
方法。 -
选项卡切换
""" current_window_handle:获取当前窗口的句柄。 window_handles:返回当前浏览器的所有窗口的句柄。 switch_to_window():用于切换到对应的窗口。 """ # 打开百度 browser.get('http://www.baidu.com') # 新建一个选项卡 browser.execute_script('window.open()') # 将操作焦点切换到新建的选项卡并跳转到知乎 browser.switch_to.window(browser.window_handles[1]) browser.get('http://www.zhihu.com') # 回到第一个选项卡并打开淘宝(原来的百度页面改为了淘宝) browser.switch_to.window(browser.window_handles[0]) browser.get('http://www.taobao.com')
三、获取页面属性
此小节为操作重点,在生成浏览器对象之后需要通过各种方式定位网页标签并获取用户所需的内容和数据。
3.1 获取页面的基础属性
有一些基础属性如网页标题、网址、浏览器名称、页面源码等信息均可以通过浏览器对象的属性获取。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get(r'https://www.baidu.com')
# 网页标题
# 输出“百度一下,你就知道”
print(browser.title)
# 当前网址
# 输出https://www.baidu.com/
print(browser.current_url)
# 浏览器名称
# 输出chrome
print(browser.name)
# 网页源码
# 输出html源码,可以继续通过xml解析
print(browser.page_source)
3.2 定位页面元素
-
通过
id
定位元素使用浏览器对象
find_element_by_id()
方法,传入页面元素的id
,返回值即为该元素。# 获取百度的搜索框,对应id为kw browser.get(r'https://www.baidu.com') input_obj = browser.find_element_by_id('kw')
-
通过
name
定位元素使用浏览器对象
find_element_by_name()
方法,传入页面元素的name
,返回值即为该元素。多个相同
name
元素不一定能定位成功。# 获取百度的搜索框,对应name为wd browser.get(r'https://www.baidu.com') input_obj = browser.find_element_by_name('wd')
-
通过
class
定位元素使用浏览器对象
find_element_by_class_name()
方法,传入页面元素的class
,返回值即为该元素。多个相同
class
元素不一定能定位成功。# 获取百度的搜索框,对应class为s_ipt browser.get(r'https://www.baidu.com') input_obj = browser.find_element_by_class_name('s_ipt')
-
通过
tag
定位元素tag
是指HTML元素的类型,常见有input
,table
,submit
等,使用浏览器对象find_element_by_tag_name()
方法,传入页面元素的tag
,返回值即为该元素。由于同个页面中会出现很多相同类型的元素,该方法不常用。
# 获取百度的搜索框,对应tag为input browser.get(r'https://www.baidu.com') input_obj = browser.find_element_by_tag_name('input')
-
通过链接文本定位元素
使用浏览器对象
find_element_by_link_text()
方法,传入对应的链接文本,返回值即为该元素。若对应的链接文本过长,可以使用模糊匹配
find_element_by_partial_link_text()
。# 获取百度的新闻导航(全匹配) browser.get(r'https://www.baidu.com') news_nav = browser.find_element_by_link_text('新闻') # 获取百度的新闻导航(模糊匹配) news_nav = browser.find_element_by_partial_link_text('闻')
-
通过
xpath
定位元素以上几种方法都是通过唯一的属性值来定位元素,除
id
外,其余属性并不是一直都是唯一的,因此使用以上方法定位元素都显得过于理想,而xpath
是通过元素在HTML代码中的位置定位的,相较以上几种定位元素的方法在实际场景中更为常用。使用浏览器对象
find_element_by_xpath()
方法,传入对应的xpath
,返回值即为该元素。# 获取百度的搜索框 browser.get(r'https://www.baidu.com') input_obj = browser.find_element_by_xpath("//*[@id='kw']")
-
通过
css
筛选器定位元素相比
xpath
更好理解,定位速度也更快。使用浏览器对象
find_element_by_css_selector()
方法,传入对应的css
筛选条件,返回值即为该元素。# 获取百度的搜索框 browser.get(r'https://www.baidu.com') # css筛选条件需要补充对应的css知识,此处根据id筛选 input_obj = browser.find_element_by_css_selector('#kw')
-
通用方法
find_element()
定位需传入两个参数:定位方式以及定位属性值
from selenium.webdriver.common.by import By from selenium import webdriver browser = webdriver.Chrome() browser.get(r'https://www.baidu.com') # 以下代码与上述几种定位方式等同 browser.find_element(By.ID,'kw') browser.find_element(By.NAME,'wd') browser.find_element(By.CLASS_NAME,'s_ipt') browser.find_element(By.TAG_NAME,'input') browser.find_element(By.LINK_TEXT,'新闻') browser.find_element(By.PARTIAL_LINK_TEXT,'闻') browser.find_element(By.XPATH,'//*[@id="kw"]') browser.find_element(By.CSS_SELECTOR,'#kw')
-
定位多个元素
使用浏览器对象
find_elements()
方法,得到的结果会是列表形式,其余操作与以上find_element
一致,取对应第几个元素时仅需对返回的列表切片。
3.3 获取页面元素的属性
-
get_attribute()
方法只要对应的元素中有属性,即可将该属性作为参数传入获取。
browser.get(r'https://www.baidu.com') logo = browser.find_element_by_css_selector('#hotsearch-content-wrapper > li:nth-child(1) > a') # 获取logo的链接 print(logo.get_attribute('href'))
-
点方法
id
: 获取元素的idlocation
:获取元素在页面上距离左上(0,0)的位置size
:获取元素在页面上显示的宽和高tag_name
:获取元素的标签属性- …
browser.get(r'https://www.baidu.com') logo = browser.find_element_by_css_selector('#hotsearch-content-wrapper > li:nth-child(1) > a') print(logo.id) # 6af39c9b-70e8-4033-8a74-7201ae09d540 print(logo.location) # {'x': 490, 'y': 46} print(logo.size) # {'height': 129, 'width': 270} print(logo.tag_name) # img
四、交互操作
此小节为操作重点,在生成浏览器对象之后需要通过各种方式对网页标签进行交互以模拟真实用户的操作。
4.1 网页标签交互
定位至指定网页标签元素后,即可对其进行交互操作。
-
输入文本
使用元素对象
send_keys()
方法对输入框等元素进行文本输入。# 定位搜索框,并在其中输入'python' input_obj = browser.find_element_by_class_name('s_ipt') input_obj.send_keys('python')
-
清除文本
使用元素对象
clear()
方法对输入框等元素进行文本清除。# 定位搜索框,清除当前的输入 input_obj = browser.find_element_by_class_name('s_ipt') input_obj.clear()
-
点击
使用元素对象
click()
方法对按钮等元素进行点击。# 定位新闻导航,并点击跳转 news_nav = browser.find_element_by_link_text('新闻') news_nav.click()
-
回车
回车可以用于表单控件的提交(其实也可以定位到提交按钮然后通过
click()
点击。使用元素对象
submit()
方法对表单控件的输入进行提交。# 定位搜索框,在其中输入'python',回车查找 input_obj = browser.find_element_by_class_name('s_ipt') input_obj.send_keys('python') input_obj.submit()
-
单选
定位某一单个元素,通过
click()
点击选中。 -
多选
依次定位某些元素,通过
click()
点击选中。 -
下拉框
假设下拉框HTML代码为:
<form> <select name="selection"> <option value="1" selected>一</option> <option value="2">二</option> <option value="3">三</option> <option value="4">四</option> </select> </form>
使用
Select
类对其进行处理。# 需要引入Select类 from selenium.webdriver.support.select import Select # 定位到需要操作的下拉框,初始化Select类 select_obj = Select(browser.find_element_by_id("selection")) """ 三种选择某一选项项的方法 select_by_index() # 通过索引选中;注意:index索引是从“0”开始。 select_by_value() # 通过value值选中,value标签的属性值。 select_by_visible_text() # 通过文本值选中,即显示在下拉框的文本值。 """ select_obj.select_by_index(1) # 选中第二个下拉选项 select_obj.select_by_value("3") # 选中第三个下拉选项 select_obj.select_by_visible_text("四") # 选中第四个下拉选项 """ 四种取消选中的方法 deselect_by_index() # 通过索引取消选中,注意:index索引是从“0”开始。 deselect_by_value() # 通过value值取消选中,value标签的属性值。 deselect_by_visible_text() # 通过文本值取消选中,即显示在下拉框的文本值。 deselect_all() # 取消全部选中。 """ select_obj.deselect_by_index(1) # 取消第二个下拉框的选中 select_obj.deselect_by_value("3") # 取消选中第三个下拉选项 select_obj.deselect_by_visible_text("四") # 取消选中第四个下拉选项 select_obj.deselect_all() # 取消全部选中 """ 查看四种下拉框属性 all_selected_options # 查看所有已选。 first_selected_option # 查看第一个已选。 is_multiple # 查看该下拉框是否是多选状态。 options # 查看选项元素列表。 """
4.2 模拟鼠标交互
在模拟鼠标交互操作前,首先需要导入ActionChains
类。
from selenium.webdriver.common.action_chains import ActionChains
-
右键点击
# 定位到要右击的元素 right_click_obj = browser.find_element_by_link_text('新闻') # 执行鼠标右键操作 ActionChains(browser).context_click(right_click_obj).perform()
-
双击
# 定位到要双击的元素 double_click_obj = browser.find_element_by_css_selector('#bottom_layer > div > p:nth-child(8) > span') # 执行双击操作 ActionChains(browser).double_click(double_click_obj).perform()
-
拖拽
drag_and_drop(source,target)
进行元素拖拽,常用于滑块验证等操作。# 开始位置 source = browser.find_element_by_css_selector("#draggable") # 结束位置 target = browser.find_element_by_css_selector("#droppable") # 执行元素的拖放操作 actions = ActionChains(browser) actions.drag_and_drop(source, target) actions.perform()
-
鼠标悬停
# 定位到要悬停的元素 hover_obj = browser.find_element_by_css_selector("#form > span.bg.s_ipt_wr.new-pmd.quickdelete-wrap > span.soutu-btn") # 执行鼠标悬停操作 ActionChains(browser).move_to_element(hover_obj).perform()
-
单击并保持
# 定位到要点击并保存的元素 button = browser.finde_element_by_class_name('geetest_slider_button') # 单击元素并保持 ActionChains(browser).click_and_hold(button).perform()
-
鼠标移动
# 经常在点击并保持后移动,等价于拖拽效果,但不同于需要两个元素对象,此处只需要指定轨迹像素 # 续单击并保持的样例代码 x = 100 y = 50 # 将对应元素向x轴方向移动100像素,向y轴方向移动50像素 ActionChains(browser).move_by_offset(xoffset=x, yoffset=y).perform()
-
鼠标松开
# 点击并保持后续操作,松开点击保持 ActionChains(browser).release().perform()
4.3 模拟键盘交互
selenium
中的Keys()
类提供了大部分的键盘操作方法,通过send_keys()
方法来模拟键盘上的按键。
常见的键盘操作:
send_keys(Keys.BACK_SPACE)
:删除键(BackSpace)
send_keys(Keys.SPACE)
:空格键(Space)
send_keys(Keys.TAB)
:制表键(TAB)
send_keys(Keys.ESCAPE)
:回退键(ESCAPE)
send_keys(Keys.ENTER)
:回车键(ENTER)
send_keys(Keys.CONTRL,'a')
:全选(Ctrl+A)
send_keys(Keys.CONTRL,'c')
:复制(Ctrl+C)
send_keys(Keys.CONTRL,'x')
:剪切(Ctrl+X)
send_keys(Keys.CONTRL,'v')
:粘贴(Ctrl+V)
send_keys(Keys.F1)
:键盘F1…
send_keys(Keys.F12)
:键盘F12
4.4 运行JavaScript
通过使用浏览器对象execute_script()
方法来实现JS的操作。
from selenium import webdriver
browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')
# 操作JS让浏览器的下拉进度条拉动至最底,并弹出弹窗提醒
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
4.5 操作Cookie
通过使用浏览器对象get_cookies()
方法获取指定key
的值。
通过使用浏览器对象add_cookie()
方法添加指定键值的Cookie。
通过使用浏览器对象delete_all_cookies()
方法删除所有的Cookie。
from selenium import webdriver
browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')
# 获取cookie
print(f'Cookies的值:{browser.get_cookies()}')
# 添加cookie
browser.add_cookie({'name':'宇后初晴_da', 'value':'帅哥'})
print(f'添加后Cookies的值:{browser.get_cookies()}')
# 删除cookie
browser.delete_all_cookies()
print(f'删除后Cookies的值:{browser.get_cookies()}')
五、延迟等待
如果遇到使用ajax
加载的网页,页面元素可能不是同时加载出来的,这个时候尝试在get
方法执行完成时获取网页源代码可能并非浏览器完全加载完成的页面。所以,这种情况下需要设置延时等待一定时间,确保全部网页元素都被加载出来。
-
强制等待
time.sleep(n)
强制等待n秒,在执行get
方法之后执行。 -
隐式等待
使用浏览器对象
implicitly_wait()
方法设置等待时间,传入秒作为参数,若到时间有元素节点没有加载出来,就会抛出异常。from selenium import webdriver browser = webdriver.Chrome() # 隐式等待,等待时间10秒 browser.implicitly_wait(10) browser.get('https://www.baidu.com') print(browser.current_url) print(browser.title) # 关闭浏览器 browser.close()
-
显式等待
引入
WebDriverWait
,设置一个等待时间和一个条件,在规定时间内,每隔一段时间查看下条件是否成立,如果成立那么程序就继续执行,否则就抛出一个超时异常。from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import time browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 设置显示等待时间10s wait = WebDriverWait(browser, 10) # 设置判断条件:等待id='kw'的元素加载完成 input_obj = wait.until(EC.presence_of_element_located((By.ID, 'kw'))) # 在输入框输入关键词'Python' input_obj.send_keys('Python') # 关闭浏览器 time.sleep(2) browser.close()
WebDriverWait
参数说明:WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
driver
:浏览器驱动timeout
:超时时间,等待的最长时间(同时要考虑隐性等待时间)poll_frequency
:每次检测的间隔时间,默认是0.5秒ignored_exceptions
:超时后的异常信息,默认情况下抛出NoSuchElementException
异常判断条件参数说明:
until(method,message='')
method
: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是Falsemessage
: 如果超时,抛出TimeoutException
,将message
传入异常until_not(method,message='')
method
: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是Falsemessage
: 如果超时,抛出TimeoutException
,将message
传入异常until_not
与until
相反,until
是当某元素出现或什么条件成立则继续执行,until_not
是当某元素消失或什么条件不成立则继续执行,二者需要传入的参数相同。其他等待条件:
from selenium.webdriver.support import expected_conditions as EC # 判断标题是否和预期的一致 title_is # 判断标题中是否包含预期的字符串 title_contains # 判断指定元素是否加载出来 presence_of_element_located # 判断所有元素是否加载完成 presence_of_all_elements_located # 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0,传入参数是元组类型的locator visibility_of_element_located # 判断元素是否可见,传入参数是定位后的元素WebElement visibility_of # 判断某个元素是否不可见,或是否不存在于DOM树 invisibility_of_element_located # 判断元素的 text 是否包含预期字符串 text_to_be_present_in_element # 判断元素的 value 是否包含预期字符串 text_to_be_present_in_element_value #判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement frame_to_be_available_and_switch_to_it #判断是否有alert出现 alert_is_present #判断元素是否可点击 element_to_be_clickable # 判断元素是否被选中,一般用在下拉列表,传入WebElement对象 element_to_be_selected # 判断元素是否被选中 element_located_to_be_selected # 判断元素的选中状态是否和预期一致,传入参数:定位后的元素,相等返回True,否则返回False element_selection_state_to_be # 判断元素的选中状态是否和预期一致,传入参数:元素的定位,相等返回True,否则返回False element_located_selection_state_to_be #判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了 staleness_of
总结
以上就是今天要讲的内容,本文用万字详解了Python爬虫中常见的自动化WEB框架Selenium,简单介绍了使用Python进行自动化操作的准备工作和常用的交互指令,如果觉得对你有帮助的话不妨点个关注点个收藏,我们下期再见~