Selenium详解

news2024/11/16 11:36:40

Selenium 环境配置好之后,我们就可以使用 Selenium 来操作浏览器,做一些我们想做的事情了。在我们爬取网页过程中,经常发现我们想要获得的数据并不能简单的通过解析 HTML 代码获取,这些数据是通过 AJAX 异步加载方式或经过 JS 渲染后才呈现在页面上显示出来。这种情况下我们就可以使用 Selenium 来模拟浏览器浏览页面,进而解决 JavaScript 渲染的问题。

浏览器设置

打开浏览器

我们用最简洁的代码来打开 Chrome 浏览器,并访问 http://www.baidu.com 这个网站:

from selenium import webdriver# 声明浏览器对象driver = webdriver.Chrome()# 访问页面driver.get("http://www.baidu.com")

我们可以看到桌面会弹出一个浏览器窗口,并打开了百度的首页,如下图:

selenium-open-browser

注意红框圈住的部分,这表示这个窗口是我们程序打开的,现在浏览器的控制权在我们的程序中,我们可以用代码让浏览器摆出各种姿势了!

设置浏览器参数

为了避免每次运行程序都打开一个窗口,我们也可以设置无窗口访问,只需添加浏览器参数即可:​​​​​​​

from selenium import webdriver# 设置无窗口chrome_options = webdriver.ChromeOptions()chrome_options.add_argument('--headless')# 声明浏览器对象driver = webdriver.Chrome(options=chrome_options)# 访问页面driver.get("http://www.baidu.com")

常见的浏览器参数还有:​​​​​​​

# 启动就最大化--start-maximized# 指定用户文件夹 User Data 路径,可以把书签这样的用户数据保存在系统分区以外的分区–-user-data-dir=”[PATH]”# 指定缓存Cache路径–-disk-cache-dir=”[PATH]“# 指定Cache大小,单位Byte–-disk-cache-size=100# 隐身模式启动–-incognito# 禁用Javascript–-disable-javascript# 禁止加载所有插件,可以增加速度--disable-plugins# 禁用JavaScript--disable-javascript# 禁用弹出拦截--disable-popup-blocking# 禁用插件--disable-plugins# 禁用图像--disable-images

还有其他好多参数,具体可参见 https://peter.sh/experiments/chromium-command-line-switches/ ,该网站罗列了所有的参数。

设置代理

设置代理很简单,只需要添加一个浏览器参数就行:

chrome_options.add_argument('--proxy-server=http://{ip}:{port}')

在参数里面加上代理的 IP 和端口号。

获取页面元素

获取单个元素

selenium 查找元素有两种方法:第一种是指定使用哪种方法去查找元素,比如指定 CSS 选择器或者根据 xpath 去查找;另一种是直接使用 find_element() ,传入的第一个参数为需要使用的元素查找方法,第二个参数为查找值。来看下例:​​​​​​​

from selenium import webdriverfrom selenium.webdriver.common.by import By# 声明浏览器对象driver = webdriver.Chrome()# 访问页面driver.get("http://www.baidu.com")# 通过id查找element = driver.find_element_by_id("kw")print(element.tag_name)# 通过name查找element = driver.find_element_by_name("wd")print(element.tag_name)# 通过xpath查找element = driver.find_element_by_xpath('//*[@id="kw"]')print(element.tag_name)# 通过另一种方式查找element = driver.find_element(By.ID, "kw")print(element.tag_name)

上面例子中,我们通过不同的方式来获取百度的搜索框,并且打印 tag_name 属性,最终的结果都是一样的:input 。

获取多个元素

我们也可以通过 find_elements() 方法获取多个属性,结果会以 list 的形式返回。我们来看例子:​​​​​​​

from selenium import webdriverfrom selenium.webdriver.common.by import By# 声明浏览器对象driver = webdriver.Chrome()# 访问页面driver.get("http://www.baidu.com")# 查找多个元素elements = driver.find_elements(By.CLASS_NAME, 'mnav')for e in elements:    print(e.text)# 输出结果新闻hao123地图视频贴吧学术

上例中,我们通过 class_name 来获取百度首页上方的百度导航,接着将获取到的导航栏的名称打印了出来。

页面操作

我们可以使用 selenium 来模拟页面操作,例如鼠标点击事件,键盘事件等。我们来看一下例子:​​​​​​​

from selenium import webdriverfrom selenium.webdriver.common.keys import Keysimport time# 声明浏览器对象driver = webdriver.Chrome()# 访问页面driver.get("http://www.baidu.com")# 获取百度搜索框元素element = driver.find_element(By.ID,"kw")# 在搜索框中输入关键词seleniumelement.send_keys("selenium")# 点击"百度一下"按钮driver.find_element(By.XPATH,'//*[@id="su"]').click()time.sleep(5)# 清空搜索框关键词element.clear()time.sleep(2)# 在搜索框中输入关键词python,并模拟键盘的enter操作element.send_keys("python", Keys.ENTER)time.sleep(5)driver.close()

在例子中,我们先是找到百度的搜索框对应的元素,然后模拟在搜索框中输入关键词 “selenium”,接下来模拟点击"百度一下"按钮,我们可以看到页面中出现了搜索 “selenium” 的结果。

接着我们使用 clear() 方法清空了搜索框,然后模拟输入关键词 “python” 并且模拟键盘的 enter 键操作,同样获得了搜索 “python” 的结果。

当然,我们还可以模拟鼠标右击、双击、拖拽等操作,就留给大家自己去探索了。

浏览器操作

等待加载

请求网页时,可能会存在 AJAX 异步加载的情况。而 selenium 只会加载主网页,并不会考虑到 AJAX 的情况。因此,使用时需要等待一些时间,让网页加载完全后再进行操作。

隐式等待

使用隐式等待时,如果 webdriver 没有找到指定的元素,将继续等待指定元素出现,直至超出设定时间,如果还是没有找到指定元素,则抛出找不到元素的异常。默认等待时间为 0。隐式等待是对整个页面进行等待。需要特别说明的是:隐性等待对整个 driver 的周期都起作用,所以只要设置一次即可。

我们来看下例:​​​​​​​

from selenium import webdriverfrom selenium.webdriver.common.keys import Keys# 声明浏览器对象driver = webdriver.Chrome()# 设置隐式等待时间,单位为秒driver.implicitly_wait(0)# 访问页面driver.get("https://www.baidu.com/")# 设置搜索关键词element = driver.find_element(By.ID,"kw")element.send_keys("Selenium", Keys.ENTER)# 页面右边的"相关术语"element2 = driver.find_element(By.CLASS_NAME,"opr-recommends-merge-p")print(element2)

这个例子中,我先打开浏览器访问百度首页,然后在搜索框输入 “Selenium” 关键字,再回车查询。百度会根据输入的关键词在页面的右边展示“相关术语”,这一步是异步加载,需要时间来查询和传输,而我们设置的等待时间是 0,所以肯定会超时。运行后我们会看到报错:​​​​​​​

# 报错信息selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".opr-recommends-merge-p"}  (Session info: chrome=77.0.3865.120)

当我们把等待时间设置为 10 秒时,我们会看到控制台的正确打印了。

显式等待

显式等待是对指定的元素进行等待。首先判定等待条件是否成立,如果成立,则直接返回;如果条件不成立,则等待最长时间为设置的等待时间,如果超过等待时间后仍然没有满足等待条件,则抛出异常。

我们来看一下例子:​​​​​​​

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC# 声明浏览器对象driver = webdriver.Chrome()# 访问页面driver.get("https://www.baidu.com/")# 设置搜索关键词element = driver.find_element(By.ID,"kw")element.send_keys("selenium", Keys.ENTER)# 此时页面右边的"相关术语"还没有加载出来,肯定会报错#element1 = driver.find_element(By.CLASS_NAME,"opr-recommends-merge-p")#print(lement1)# 显示等待10秒,直到页面右边的"相关术语"出现WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "opr-recommends-merge-p")))# 获取页面右边的"相关术语"element2 = driver.find_element_by_class_name("opr-recommends-merge-p")print(element2)

运行这段代码,在打印 element1 的时候肯定会报错,因为此时页面右边的“相关术语”还没加载出来。我们注释掉获取和打印 element1 的这两行,然后设置一个显式的等待条件和 10 秒的等待时间,element2 就可以顺利打印出来了。

浏览器前进和后退

我们可以通过 selenium 来操纵浏览器的前进和后退,方法很简单,分别是 back() 和 forward()。来看下例:​​​​​​​

from selenium import webdriverimport time# 声明浏览器对象driver = webdriver.Chrome()# 访问百度driver.get("http://www.baidu.com")time.sleep(2)# 访问微博driver.get("https://weibo.com")time.sleep(2)# 访问知乎driver.get("http://www.zhihu.com")time.sleep(2)# 返回上个页面driver.back()time.sleep(2)# 前进到下个页面driver.forward()# 退出driver.close()

我们首先依次打开百度、微博和知乎三个网站(中间设置的等待时间是为了更好地看演示效果)。然后我们调用返回上个页面方法,可以看到浏览器返回到了微博页面,接着我们调用前进到下个页面方法,可以看到浏览器回到了知乎页面。

操作 Cookie

我们可以通过 selenium 来设置浏览器的 cookie,包括添加 cookie ,删除 cookie ,获取 cookie 等操作。我们来看个例子:​​​​​​​

from selenium import webdriver# 声明浏览器对象driver = webdriver.Chrome()# 访问百度driver.get("http://www.baidu.com")# 获取当前的cookieprint(driver.get_cookies())# 添加cookiedriver.add_cookie({'name': 'mycookie', 'value': 'world'})# 获取设置的cookieprint(driver.get_cookie('mycookie'))# 删除设置的cookiedriver.delete_cookie('mycookie')# 再次获取设置的cookieprint(driver.get_cookie('mycookie'))# 清除所有cookiedriver.delete_all_cookies()# 再次获取cookieprint(driver.get_cookies())# 退出driver.close()# 输出信息[{'domain': '.baidu.com', 'httpOnly': False, 'name': 'H_PS_PSSID', 'path': '/', 'secure': False, 'value': '1422_21106_29721_29568_29221_26350_29589'}, {'domain': '.baidu.com', 'expiry': 1570877928.79997, 'httpOnly': False, 'name': 'BDORZ', 'path': '/', 'secure': False, 'value': 'B490B5EBF6F3CD402E515D22BCDA1598'}, {'domain': 'www.baidu.com', 'expiry': 1571655528, 'httpOnly': False, 'name': 'BD_UPN', 'path': '/', 'secure': False, 'value': '123253'}, {'domain': 'www.baidu.com', 'httpOnly': False, 'name': 'BD_HOME', 'path': '/', 'secure': False, 'value': '0'}, {'domain': '.baidu.com', 'expiry': 3718275175.123787, 'httpOnly': False, 'name': 'PSTM', 'path': '/', 'secure': False, 'value': '1570791528'}, {'domain': '.baidu.com', 'httpOnly': False, 'name': 'delPer', 'path': '/', 'secure': False, 'value': '0'}, {'domain': '.baidu.com', 'expiry': 3718275175.123763, 'httpOnly': False, 'name': 'BIDUPSID', 'path': '/', 'secure': False, 'value': '5A2BAF0B0AE83FA189BE38C65DC65395'}, {'domain': 'www.baidu.com', 'expiry': 1570791529.123808, 'httpOnly': False, 'name': 'BD_LAST_QID', 'path': '/', 'secure': False, 'value': '10847283847030224144'}, {'domain': '.baidu.com', 'expiry': 3718275175.123643, 'httpOnly': False, 'name': 'BAIDUID', 'path': '/', 'secure': False, 'value': '5A2BAF0B0AE83FA189BE38C65DC65395:FG=1'}]{'domain': 'www.baidu.com', 'httpOnly': False, 'name': 'mycookie', 'path': '/', 'secure': True, 'value': 'world'}None[]

在上例中,我们通过 add_cookie() 方法,来设置 cookie 的名称和值,通过给 delete_cookie() 方法传递 cookie 的名称来删除 cookie,还可以通过 get_cookies() 和 delete_all_cookies() 来获取所有 cookie 以及删除所有 cookie 。

标签管理

有些时候我们需要在浏览器里切换标签页,或者增加一个新标签页,或者删除一个标签页,都可以使用 selenium 来实现。我们来看例子:​​​​​​​

from selenium import webdriverimport time# 声明浏览器对象driver = webdriver.Chrome()# 访问百度driver.get("http://www.baidu.com")time.sleep(2)# 新增一个标签页driver.execute_script('window.open()')time.sleep(2)# 打印标签页print(driver.window_handles)# 切换至标签页1(当前标签页为0)driver.switch_to.window(driver.window_handles[1])time.sleep(2)# 在当前标签页访问知乎driver.get("http://www.zhihu.com")time.sleep(2)# 切换至标签页0driver.switch_to.window(driver.window_handles[0])time.sleep(2)# 在标签页0访问微博driver.get("http://www.weibo.com")time.sleep(2)# 关闭driver.close()# 退出driver.quit()

大家运行代码就可以体会到切换标签页和访问网页的变化,中间加了等待是为了延迟变化。另外,注意标签页从左往右是从 0 开始编号的。

总结

本节给大家介绍了 Selenium 的常见使用方法,利用这些方法我们可以很轻易地去操纵浏览器,让浏览器按照我们预设的规则来顺序执行操作指令。当然本文中列举的只是 selenium 的一部分操作,还有很多丰富的功能等着大家自己去探索。如果你能够熟练地运用和组合这些操作,你会发现还有更多复杂好玩的事情等着你去探索!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python高级系列教程:Python闭包和装饰器

今天我们将继续讲解 Python 中的闭包和装饰器。虽然我们还没有详细学习这两个概念,但在面向对象编程中,我们已经经常使用装饰器了。装饰器可以给函数增加额外的功能,就像语法糖一样甜。在 Python 中,装饰器的格式通常是在函数上方…

三分钟学习一个python小知识1-----------我的对python的基本语法的理解

文章目录 一、变量定义二、数据类型三、条件语句四、循环语句五、函数定义总结 一、变量定义 在Python中,使用等号()进行变量的定义,并不需要声明变量的类型,Python会自动根据赋值的数据类型来判断变量的类型&#xf…

算法篇——动态规划 完全和多重背包问题 (js版)

一些分析总结 01 背包 问题和 完全背包 问题的不同点在于,所有的物品只能使用一次,判断 哪些物品 装进背包里 物品价值和 最大;而 完全背包 问题中,所有物品都能使用n次,判断 哪个物品 装 n 个进去 物品价值和 最大。…

Mybatis源码分析_日志模块 (1)

不得不承认,学习MyBatis的时间成本要比学习Spring低很多,Mybatis是我所了解过的代码量最小、整体架构最简单,但是又是最具有学习价值的一个框架。如果,你想快速的阅读一个框架的源码,并且掌握这个框架的精髓&#xff0…

浅析GeoServer CVE-2023-25157 SQL注入

简介 GeoServer是一个开源的地图服务器&#xff0c;它是遵循OpenGIS Web服务器规范的J2EE实现&#xff0c;通过它可以方便的将地图数据发布为地图服务&#xff0c;实现地理空间数据在用户之间的共享。 影响版本 geoserver<2.18.7 2.19.0<geoserver<2.19.7 2.20.0…

国内外八大敏捷开发工具盘点

1、Leangoo领歌&#xff1b;官网&#xff1a;Leangoo领歌 - 高效企业必备的敏捷工具,Scrum工具,SAFe敏捷工具,敏捷项目管理,敏捷研发工具 2、VersionOne&#xff1b;官网&#xff1a;https://www.collab.net/products/versiononehttps://www.collab.net/products/versionone …

Python高级系列教程:Python高级语法与正则表达式

学习目标 1、能够掌握with语句的使用 2、能够知道生成器的两种创建方式 3、能够知道深拷贝和浅拷贝的区别 4、能够掌握Python中的正则表达式编写 一、Python高级语法 1、with语句和上下文管理器 ☆ with语句 Python提供了 with 语句的写法&#xff0c;既简单又安全。文件操…

Vue-scoped(局部)样式

scoped(局部)样式 scoped是在脚手架有一个编写样式的小技巧 作用&#xff1a;让样式在局部生效&#xff0c;防止冲突 1 编写案例 现在有两个组件&#xff0c;一个student,一个school&#xff0c;现在想给组件写点样式 这里只给个背景色 没问题&#xff0c;样式生效 2 样式冲…

docker canal 安装

(373条消息) 使用 Docker 部署 canal 服务_canal docker部署_qq2276031的博客-CSDN博客https://blog.csdn.net/qq2276031/article/details/120234122 docker canal github 网址 Canal Admin Docker alibaba/canal Wiki (github.com)https://github.com/alibaba/canal/wiki/Ca…

璞华产业园区租赁运营平台,助力空间资产管理数字化转型!

{ 产业园区租赁运营平台 } 直面行业痛点 专注技术创新 点击输入图片描述&#xff08;最多30字&#xff09; 产业园区作为产业转型升级的重要载体&#xff0c;产业园区租赁运营也正迎来新的发展机遇。璞华一直关注为客户智能化转型过程中提供的服务&#xff0c;能否将技术方案…

【自监督论文阅读 3】DINOv1

文章目录 一、摘要二、引言三、相关工作3.1 自监督学习3.2 自训练与知识蒸馏 四、方法4.1 SSL with Knowledge Distillation4.2 教师网络4.3 网络架构4.4 避免坍塌 五、实验与评估六、消融实验6.1 不同组合的重要性6.2 教师网络选择的影响6.3 避免坍塌6.4 在小batch上训练 七、…

elk搭建

1、前言 ELK 是一个开源的日志管理解决方案&#xff0c;主要是为了统一收集生产的日志&#xff0c;方便日志的查询&#xff0c;传统的日志都是保存在每个机器上&#xff0c;当要查询的时候&#xff0c;需要到每一台机器上去查询日志&#xff0c;非常麻烦&#xff0c;而elk则使…

阿里巴巴 Java 开发手册部分整理

阿里巴巴 Java 开发手册 一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 集合处理(六) 并发处理(七) 控制语句(八) 注释规约(九) 其它 二、异常日志(一) 异常处理(二) 日志规约 三、单元测试四、安全规约五、MySQL 数据库(一) 建表规约(二) 索引规约(三…

Java 操作pdf工具类

1、获取pdf页数 添加maven依赖&#xff1a; <!-- java获取Pdf文件页码 --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>1.8.11</version></dependency>代码实现&#x…

Goby 漏洞发布|电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞

漏洞名称&#xff1a;电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞 English Name&#xff1a;Telecom system /manager/teletext/material/upload.php fileupload vulnerability CVSS core: 9.8 影响资产数&#xff1a;856 漏洞描述&…

不过时的经典层架构

在《设计服务要考虑的7个维度》中讲到设计一定要把不稳定的部分做封装。今天咱们就从这个角度重新审视一下经典的四层架构。 上面是一个经典层架构的示意图。这个架构大多数的公司和项目都在直接用&#xff0c;或者用其变体。 比如&#xff0c;某大厂上层Client客户端可能是电商…

安卓蓝牙GATT协议介绍

前言 现在低功耗蓝牙&#xff08;BLE&#xff09;连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范&#xff0c;这些很短的数据段被称为属性&#xff08;Attribute&#xff09;。 GAP 详细介绍 GAT…

GBASE金融信创优秀解决方案鉴赏 · 核心业务系统数据库解决方案

为此&#xff0c;实验室特别开设金融信创优秀解决方案专栏&#xff0c;集中展示优秀成果。现在&#xff0c;让我们一起来领略下GBASE的优秀解决方案吧~可点击阅读原文 →《金融信创优秀解决方案--核心业务系统数据库解决方案》。 核心业务系统数据库解决方案 方案简介 随着技…

Android Qcom USB Driver学习(十三)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom USB Driver学习(零) Android Qcom USB Driver学习(八) Android Qcom USB Driver学习(九) UCSI USB Type-C Connector System Software Interface Specification DPM Device Policy Manager deals with the USB P…

智安网络|驾驭数字化转型时代:加速业务转型的战略

随着科技的飞速发展和数字化时代的到来&#xff0c;企业面临着前所未有的机遇和挑战。数字化正在改变着商业的方方面面&#xff0c;而那些能够及时适应和把握这些变化的企业将脱颖而出。因此&#xff0c;加速企业转型成为了当务之急。 一、为什么需要加速企业转型 1.全球市场竞…