资讯专栏INFORMATION COLUMN

【Python爬虫】4万字,详解selenium从入门到实战【错过再无】

shiyang6017 / 3241人阅读

摘要:难在哪里根据上面的标签需要定位最后一行标签,以下列出了四种方式,定位的方式多样并不唯一,使用时根据情况进行解析即可。加入每日一练我们使用并指明标签内全部文本即可定位。

?跳转文末? 获取实战源码与作者联系方式,共同学习进步



简介

Selenium 是最广泛使用的开源 Web UI(用户界面)自动化测试套件之一。Selenium 支持的语言包括C#,Java,Perl,PHP,Python 和 Ruby。目前,Selenium Web 驱动程序最受 Python 和 C#欢迎。 Selenium 测试脚本可以使用任何支持的编程语言进行编码,并且可以直接在大多数现代 Web 浏览器中运行。在爬虫领域 selenium 同样是一把利器,能够解决大部分的网页的反爬问题,但也不是万能的,它最明显的缺点就是速度慢。下面就进入正式的 study 阶段。



selenium安装

打开 cmd,输入下面命令进行安装。

pip install -i https://pypi.douban.com/simple selenium

执行后,使用 pip show selenium 查看是否安装成功。



安装浏览器驱动

针对不同的浏览器,需要安装不同的驱动。下面列举了常见的浏览器与对应的驱动程序下载链接,部分网址需要 “科学上网” 才能打开哦(ffffdd)。

  • Firefox 浏览器驱动:Firefox
  • Chrome 浏览器驱动:Chrome
  • IE 浏览器驱动:IE
  • Edge 浏览器驱动:Edge
  • PhantomJS 浏览器驱动:PhantomJS
  • Opera 浏览器驱动:Opera

这里以安装 Chrome 驱动作为演示。但 Chrome 在用 selenium 进行自动化测试时还是有部分 bug ,常规使用没什么问题,但如果出现一些很少见的报错,可以使用 Firefox 进行尝试,毕竟是 selenium 官方推荐使用的。

确定浏览器版本

在新标签页输入 chrome://settings/ 进入设置界面,然后选择 【关于 Chrome

查看自己的版本信息。这里我的版本是94,这样在下载对应版本的 Chrome 驱动即可。

下载驱动

打开 Chrome驱动 。单击对应的版本。

根据自己的操作系统,选择下载。


下载完成后,压缩包内只有一个 exe 文件。

chromedriver.exe 保存到任意位置,并把当前路径保存到环境变量中(我的电脑>>右键属性>>高级系统设置>>高级>>环境变量>>系统变量>>Path),添加的时候要注意不要把 path 变量给覆盖了,如果覆盖了千万别关机,然后百度。添加成功后使用下面代码进行测试。

from selenium import webdriver# Chrome浏览器driver = webdriver.Chrome()


定位页面元素

打开指定页面

使用 selenium 定位页面元素的前提是你已经了解基本的页面布局及各种标签含义,当然如果之前没有接触过,现在我也可以带你简单的了解一下。
以我们熟知的 CSDN 为例,我们进入首页,按 【F12】 进入开发者工具。红框中显示的就是页面的代码,我们要做的就是从代码中定位获取我们需要的元素。

想要定位并获取页面中的信息,首先要使用 webdriver 打开指定页面,再去定位。

from selenium import webdriver# Chrome浏览器driver = webdriver.Chrome()driver.get("https://www.csdn.net/")

执行上面语句后会发现,浏览器打开 CSDN 主页后会马上关闭,想要防止浏览器自动关闭,可以添加下面代码。

# 不自动关闭浏览器option = webdriver.ChromeOptions()option.add_experimental_option("detach", True)# 将option作为参数添加到Chrome中driver = webdriver.Chrome(chrome_options=option)

这样将上面的代码组合再打开浏览器就不会自动关闭了。

from selenium import webdriver# 不自动关闭浏览器option = webdriver.ChromeOptions()option.add_experimental_option("detach", True)# 注意此处添加了chrome_options参数driver = webdriver.Chrome(chrome_options=option)driver.get("https://www.csdn.net/")

下面我们再来看看几种常见的页面元素定位方式。

id 定位

标签的 id 具有唯一性,就像人的身份证,假设有个 input 标签如下。

<input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="C++难在哪里?">

我们可以通过 id 定位到它,由于 id 的唯一性,我们可以不用管其他的标签的内容。

driver.find_element_by_id("toolbar-search-input")

name 定位

name 指定标签的名称,在页面中可以不唯一。假设有个 meta 标签如下

<meta name="keywords" content="CSDN博客,CSDN学院,CSDN论坛,CSDN直播">

我们可以使用 find_element_by_name 定位到 meta 标签。

driver.find_element_by_name("keywords")

class 定位

class 指定标签的类名,在页面中可以不唯一。假设有个 div 标签如下

<div class="toolbar-search-container">

我们可以使用 find_element_by_class_name 定位到 div 标签。

driver.find_element_by_class_name("toolbar-search-container")

tag 定位

每个 tag 往往用来定义一类功能,所以通过 tag 来识别某个元素的成功率很低,每个页面一般都用很多相同的 tag ,比如:/

/ 等。这里还是用上面的 div 作为例子。

<div class="toolbar-search-container">

我们可以使用 find_element_by_class_name 定位到 div 标签。

driver.find_element_by_tag_name("div")

xpath 定位

xpath 是一种在 XML 文档中定位元素的语言,它拥有多种定位方式,下面通过实例我们看一下它的几种使用方式。

<html>  <head>...<head/>  <body>    <div id="csdn-toolbar">      <div class="toolbar-inside">        <div class="toolbar-container">          <div class="toolbar-container-left">...div>          <div class="toolbar-container-middle">            <div class="toolbar-search onlySearch">			<div class="toolbar-search-container">				<input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="C++难在哪里?">

根据上面的标签需要定位 最后一行 input 标签,以下列出了四种方式,xpath 定位的方式多样并不唯一,使用时根据情况进行解析即可。

# 绝对路径(层级关系)定位driver.find_element_by_xpath(	"/html/body/div/div/div/div[2]/div/div/input[1]")# 利用元素属性定位driver.find_element_by_xpath(	"//*[@id="toolbar-search-input"]"))# 层级+元素属性定位driver.find_element_by_xpath(	"//div[@id="csdn-toolbar"]/div/div/div[2]/div/div/input[1]")# 逻辑运算符定位driver.find_element_by_xpath(	"//*[@id="toolbar-search-input" and @autocomplete="off"]")

css 定位

CSS 使用选择器来为页面元素绑定属性,它可以较为灵活的选择控件的任意属性,一般定位速度比 xpath 要快,但使用起来略有难度。
CSS 选择器常见语法:

方法例子描述
.class.toolbar-search-container选择 class = "toolbar-search-container" 的所有元素
#id#toolbar-search-input选择 id = "toolbar-search-input" 的元素
**选择所有元素
elementinput选择所有 元素
element>elementdiv>input选择父元素为
的所有 元素
element+elementdiv+input选择同一级中在
之后的所有 元素
[attribute=value]type="text"选择 type = "text" 的所有元素

举个简单的例子,同样定位上面实例中的 input 标签。

driver.find_element_by_css_selector("#toolbar-search-input")driver.find_element_by_css_selector("html>body>div>div>div>div>div>div>input")

link 定位

link 专门用来定位文本链接,假如要定位下面这一标签。

<div class="practice-box" data-v-04f46969="">加入!每日一练div>

我们使用 find_element_by_link_text 并指明标签内全部文本即可定位。

driver.find_element_by_link_text("加入!每日一练")

partial_link 定位

partial_link 翻译过来就是“部分链接”,对于有些文本很长,这时候就可以只指定部分文本即可定位,同样使用刚才的例子。

<div class="practice-box" data-v-04f46969="">加入!每日一练div>

我们使用 find_element_by_partial_link_text 并指明标签内部分文本进行定位。

driver.find_element_by_partial_link_text("加入")


浏览器控制

修改浏览器窗口大小

webdriver 提供 set_window_size() 方法来修改浏览器窗口的大小。

from selenium import webdriver# Chrome浏览器driver = webdriver.Chrome()driver.get("https://www.csdn.net/")# 设置浏览器浏览器的宽高为:600x800driver.set_window_size(600, 800)

也可以使用 maximize_window() 方法可以实现浏览器全屏显示。

from selenium import webdriver# Chrome浏览器driver = webdriver.Chrome()driver.get("https://www.csdn.net/")# 设置浏览器浏览器的宽高为:600x800driver.maximize_window()

浏览器前进&后退

webdriver 提供 backforward 方法来实现页面的后退与前进。下面我们 ①进入CSDN首页,②打开CSDN个人主页,③back 返回到CSDN首页,④ forward 前进到个人主页。

from selenium import webdriverfrom time import sleepdriver = webdriver.Chrome()# 访问CSDN首页driver.get("https://www.csdn.net/")sleep(2)#访问CSDN个人主页driver.get("https://blog.csdn.net/qq_43965708")sleep(2)#返回(后退)到CSDN首页driver.back()sleep(2)#前进到个人主页driver.forward()

细心的读者会发现第二次 get() 打开新页面时,会在原来的页面打开,而不是在新标签中打开。如果想的话也可以在新的标签页中打开新的链接,但需要更改一下代码,执行 js 语句来打开新的标签。

# 在原页面打开driver.get("https://blog.csdn.net/qq_43965708")# 新标签中打开js = "window.open("https://blog.csdn.net/qq_43965708")"driver.execute_script(js)

浏览器刷新

在一些特殊情况下我们可能需要刷新页面来获取最新的页面数据,这时我们可以使用 refresh() 来刷新当前页面。

# 刷新页面driver.refresh()

浏览器窗口切换

在很多时候我们都需要用到窗口切换,比如:当我们点击注册按钮时,它一般会打开一个新的标签页,但实际上代码并没有切换到最新页面中,这时你如果要定位注册页面的标签就会发现定位不到,这时就需要将实际窗口切换到最新打开的那个窗口。我们先获取当前各个窗口的句柄,这些信息的保存顺序是按照时间来的,最新打开的窗口放在数组的末尾,这时我们就可以定位到最新打开的那个窗口了。

# 获取打开的多个窗口句柄windows = driver.window_handles# 切换到当前最新打开的窗口driver.switch_to.window(windows[-1])

常见操作

webdriver中的常见操作有:

方法描述
send_keys()模拟输入指定内容
clear()清除文本内容
is_displayed()判断该元素是否可见
get_attribute()获取标签属性值
size返回元素的尺寸
text返回元素文本

接下来还是用 CSDN 首页为例,需要用到的就是搜素框和搜索按钮。通过下面的例子就可以气息的了解各个操作的用法了。

from selenium import webdriverdriver = webdriver.Chrome()driver.get("https://www.csdn.net/")sleep(2)# 定位搜索输入框text_label = driver.find_element_by_xpath("//*[@id="toolbar-search-input"]")# 在搜索框中输入 Dream丶Killertext_label.send_keys("Dream丶Killer")sleep(2)# 清除搜索框中的内容text_label.clear()# 输出搜索框元素是否可见print(text_label.is_displayed())# 输出placeholder的值print(text_label.get_attribute("placeholder"))# 定位搜索按钮button = driver.find_element_by_xpath("//*[@id="toolbar-search-button"]/span")# 输出按钮的大小print(button.size)# 输出按钮上的文本print(button.text)"""输出内容Truepython面试100问{"height": 32, "width": 28}搜索"""



鼠标控制

在webdriver 中,鼠标操作都封装在ActionChains类中,常见方法如下:

方法描述
click()单击左键
context_click()单击右键
double_click()双击
drag_and_drop()拖动
move_to_element()鼠标悬停
perform()执行所有ActionChains中存储的动作

单击左键

模拟完成单击鼠标左键的操作,一般点击进入子页面等会用到,左键不需要用到 ActionChains

# 定位搜索按钮button = driver.find_element_by_xpath("//*[@id="toolbar-search-button"]/span")# 执行单击操作button.click()

单击右键

鼠标右击的操作与左击有很大不同,需要使用 ActionChains

from selenium.webdriver.common.action_chains import ActionChains# 定位搜索按钮button = driver.find_element_by_xpath("//*[@id="toolbar-search-button"]/span")# 右键搜索按钮ActionChains(driver).context_click(button).perform()

双击

模拟鼠标双击操作。

# 定位搜索按钮button = driver.find_element_by_xpath("//*[@id="toolbar-search-button"]/span")# 执行双击动作ActionChains(driver).double_click(button).perform()

拖动

模拟鼠标拖动操作,该操作有两个必要参数,

  • source:鼠标拖动的元素
  • target:鼠标拖至并释放的目标元素
# 定位要拖动的元素source = driver.find_element_by_xpath("xxx")# 定位目标元素target = driver.find_element_by_xpath("xxx")# 执行拖动动作ActionChains(driver).drag_and_drop(source, target).perform()

鼠标悬停

模拟悬停的作用一般是为了显示隐藏的下拉框,比如 CSDN 主页的收藏栏,我们看一下效果。

# 定位收藏栏collect  = driver.find_element_by_xpath("//*[@id="csdn-toolbar"]/div/div/div[3]/div/div[3]/a")# 悬停至收藏标签处ActionChains(driver).move_to_element(collect).perform()


键盘控制

webdriverKeys 类几乎提供了键盘上的所有按键方法,我们可以使用 send_keys + Keys 实现输出键盘上的组合按键如 “Ctrl + C”、“Ctrl + V” 等。

from selenium.webdriver.common.keys import Keys# 定位输入框并输入文本driver.find_element_by_id("xxx").send_keys("Dream丶killer")# 模拟回车键进行跳转(输入内容后) driver.find_element_by_id("xxx").send_keys(Keys.ENTER)# 使用 Backspace 来删除一个字符driver.find_element_by_id("xxx").send_keys(Keys.BACK_SPACE)# Ctrl + A 全选输入框中内容driver.find_element_by_id("xxx").send_keys(Keys.CONTROL, "a")# Ctrl + C 复制输入框中内容driver.find_element_by_id("xxx").send_keys(Keys.CONTROL, "c")# Ctrl + V 粘贴输入框中内容driver.find_element_by_id("xxx").send_keys(Keys.CONTROL, "v")

其他常见键盘操作:

操作描述
Keys.F1F1键
Keys.SPACE空格
Keys.TABTab键
Keys.ESCAPEESC键
Keys.ALTAlt键
Keys.SHIFTShift键
Keys.ARROW_DOWN向下箭头
Keys.ARROW_LEFT向左箭头
Keys.ARROW_RIGHT向右箭头
Keys.ARROW_UP向上箭头


设置元素等待

很多页面都使用 ajax 技术,页面的元素不是同时被加载出来的,为了防止定位这些尚在加载的元素报错,可以设置元素等来增加脚本的稳定性。webdriver 中的等待分为 显式等待 和 隐式等待。

显式等待

显式等待:设置一个超时时间,每个一段时间就去检测一次该元素是否存在,如果存在则执行后续内容,如果超过最大时间(超时时间)则抛出超时异常(TimeoutException)。显示等待需要使用 WebDriverWait,同时配合 untilnot until 。下面详细讲解一下。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

  • driver:浏览器驱动
  • timeout:超时时间,单位秒
  • poll_frequency:每次检测的间隔时间,默认为0.5秒
  • ignored_exceptions:指定忽略的异常,如果在调用 untiluntil_not 的过程中抛出指定忽略的异常,则不中断代码,默认忽略的只有 NoSuchElementException

until(method, message=’ ‘)
until_not(method, message=’ ")

  • method:指定预期条件的判断方法,在等待期间,每隔一段时间调用该方法,判断元素是否存在,直到元素出现。until_not 正好相反,当元素消失或指定条件不成立,则继续执行后续代码
  • message: 如果超时,抛出 TimeoutException ,并显示 message 中的内容

method 中的预期条件判断方法是由 expected_conditions 提供,下面列举常用方法。

先定义一个定位器

from selenium.webdriver.common.by import Byfrom selenium import webdriverdriver = webdriver.Chrome()locator = (By.ID, "kw")element = driver.find_element_by_id("kw")
方法描述
title_is(‘百度一下’)判断当前页面的 title 是否等于预期
title_contains(‘百度’)判断当前页面的 title 是否包含预期字符串
presence_of_element_located(locator)判断元素是否被加到了 dom 树里,并不代表该元素一定可见
visibility_of_element_located(locator)判断元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of(element)跟上一个方法作用相同,但传入参数为 element
text_to_be_present_in_element(locator , ‘百度’)判断元素中的 text 是否包含了预期的字符串
text_to_be_present_in_element_value(locator , ‘某值’)判断元素中的 value 属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it(locator)判断该 frame 是否可以 switch 进去,True 则 switch 进去,反之 False
invisibility_of_element_located(locator)判断元素中是否不存在于 dom 树或不可见
element_to_be_clickable(locator)判断元素中是否可见并且是可点击的
staleness_of(element)等待元素从 dom 树中移除
element_to_be_selected(element)判断元素是否被选中,一般用在下拉列表
element_selection_state_to_be(element, True)判断元素的选中状态是否符合预期,参数 element,第二个参数为 True/False
element_located_selection_state_to_be(locator, True)跟上一个方法作用相同,但传入参数为 locator
alert_is_present()判断页面上是否存在 alert

下面写一个简单的例子,这里定位一个页面不存在的元素,抛出的异常信息正是我们指定的内容。

from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome()element = WebDriverWait(driver, 5, 0.5).until(            EC.presence_of_element_located((By.ID, "kw")),                                           message="超时啦!")

隐式等待

隐式等待也是指定一个超时时间,如果超出这个时间指定元素还没有被加载出来,就会抛出 NoSuchElementException 异常。
除了抛出的异常不同外,还有一点,隐式等待是全局性的,即运行过程中,如果元素可以定位到,它不会影响代码运行,但如果定位不到,则它会以轮询的方式不断地访问元素直到元素被找到,若超过指定时间,则抛出异常

使用 implicitly_wait() 来实现隐式等待,使用难度相对于显式等待要简单很多。
示例:打开个人主页,设置一个隐式等待时间 5s,通过 id 定位一个不存在的元素,最后打印 抛出的异常 与 运行时间。

from selenium import webdriverfrom time import timedriver = webdriver.Chrome()driver.get("https://blog.csdn.net/qq_43965708")start = time()driver.implicitly_wait(5)try:    driver.find_element_by_id("kw")except Exception as e:    print(e)    print(f"耗时:{time()-start}")


代码运行到 driver.find_element_by_id("kw") 这句之后触发隐式等待,在轮询检查 5s 后仍然没有定位

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/122210.html

相关文章

  • 首次公开,整理12年积累的博客收藏夹,零距离展示《收藏夹吃灰》系列博客

    摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...

    Harriet666 评论0 收藏0
  • SegmentFault 技术周刊 Vol.30 - 学习 Python 来做一些神奇好玩的事情吧

    摘要:学习笔记七数学形态学关注的是图像中的形状,它提供了一些方法用于检测形状和改变形状。学习笔记十一尺度不变特征变换,简称是图像局部特征提取的现代方法基于区域图像块的分析。本文的目的是简明扼要地说明的编码机制,并给出一些建议。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 开始之前,我们先来看这样一个提问: pyth...

    lifesimple 评论0 收藏0
  • 【小白+python+selenium库+图片爬取+反爬+资料】超详细新手实现(01)webdriv

    摘要:且本小白也亲身经历了整个从小白到爬虫初入门的过程,因此就斗胆在上开一个栏目,以我的图片爬虫全实现过程为例,以期用更简单清晰详尽的方式来帮助更多小白应对更大多数的爬虫实际问题。 前言: 一个月前,博主在学过python(一年前)、会一点网络(能按F12)的情况下,凭着热血和兴趣,开始了pyth...

    Half 评论0 收藏0
  • 零基础如何学爬虫技术

    摘要:楚江数据是专业的互联网数据技术服务,现整理出零基础如何学爬虫技术以供学习,。本文来源知乎作者路人甲链接楚江数据提供网站数据采集和爬虫软件定制开发服务,服务范围涵盖社交网络电子商务分类信息学术研究等。 楚江数据是专业的互联网数据技术服务,现整理出零基础如何学爬虫技术以供学习,http://www.chujiangdata.com。 第一:Python爬虫学习系列教程(来源于某博主:htt...

    KunMinX 评论0 收藏0

发表评论

0条评论

shiyang6017

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<