作者 | 俊欣

来源 | 关于数据分析与可视化

今天小编就来讲讲selenium,我们大致会讲这些内容

  • selenium简介与安装

  • 页面元素的定位

  • 浏览器的控制

  • 鼠标的控制

  • 键盘的控制

  • 设置元素的等待

  • 获取cookies

  • 调用JavaScript

  • selenium进阶

selenium的简介与安装

selenium是最广泛使用的开源Web UI自动化测试套件之一,它所支持的语言包括C++JavaPerlPHPPythonRuby,在数据抓取方面也是一把利器,能够解决大部分网页的反爬措施,当然它也并非是万能的,一个比较明显的一点就在于是它速度比较慢,如果每天数据采集的量并不是很高,倒是可以使用这个框架。

那么说到安装,可以直接使用pip在安装

pip install selenium

与此同时呢,我们还需要安装一个浏览器驱动,不同的浏览器需要安装不同的驱动,这边小编主要推荐的以下这两个

  • Firefox浏览器驱动: geckodriver

  • Chrome浏览器驱动: chromedriver

小编平常使用的是selenium+chromedriver比较多,所以这里就以Chrome浏览器为示例,由于要涉及到chromedriver的版本需要和浏览器的版本一致,因此我们先来确认一下浏览器的版本是多少?看下图

我们在“关于Chrome”当中找到浏览器的版本,然后下载对应版本的chromedriver,当然也要对应自己电脑的操作系统

页面元素的定位

在谈到页面元素的定位时,小编默认读者朋友具备了最最基本的前端知识,例如HTMLCSS

ID标签的定位

HTML当中,ID属性是唯一标识一个元素的属性,因此在selenium当中,通过ID来进行元素的定位也作为首选,我们以百度首页为例,搜索框的HTML代码如下,其ID为“kw”,而“百度一下”这个按钮的ID为“su”,我们用Python脚本通过ID的标签来进行元素的定位

driver.find_element_by_id("kw")
driver.find_element_by_id("su")

NAME标签的定位

HTML当中,Name属性和ID属性的功能基本相同,只是Name属性并不是唯一的,如果遇到没有ID标签的时候,我们可以考虑通过Name标签来进行定位,代码如下

driver.find_element_by_name("wd")

Xpath定位

使用Xpath方式来定位几乎涵盖了页面上的任意元素,那什么是Xpath呢?Xpath是一种在XMLHTML文档中查找信息的语言,当然通过Xpath路径来定位元素的时候也是分绝对路径和相对路径。

绝对路径是以单号/来表示,相对路径是以//来表示,而涉及到Xpath路径的编写,小编这里偷个懒,直接选择复制/粘贴的方式,例如针对下面的HTML代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Test</title>
</head>
<body>
<form id="loginForm"><input name="username" type="text" /><input name="password" type="password" /><input name="continue" type="submit" value="Login" /><input name="continue" type="button" value="Clear" />
</form></body>
</html>

我们可以这么来做,打开浏览器的开发者工具,鼠标移到我们选中的元素,然后右击检查,具体看下图

我们还是以百度首页为例,看一下如何通过Xpath来进行页面元素的定位,代码如下

driver.find_element_by_xpath('//*[@id="kw"]')

className标签定位

我们也可以基于class属性来定位元素,尤其是当我们看到有多个并列的元素如list表单,class用的都是共用同一个,如:

driver.find_element_by_class_name("classname")

这个时候,我们就可以通过class属性来定位元素,该方法返回的是一个list列表,而当我们想要定位列表当中的第n个元素时,则可以这样来安排

driver.find_elements_by_class_name("classname")[n]

需要注意的是,这里使用的是find_elements_by_class_name()方法而不是find_element_by_class_name()方法,这里我们还是通过百度首页的例子,通过className标签来定位搜索框这个元素

driver.find_element_by_class_name('s_ipt')

CssSelector()方法定位

其实在Selenium官网当中是更加推荐CssSelector()方法来进行页面元素的定位的,原因在于相比较于Xpath定位速度更快,Css定位分为四类:ID值、Class属性、TagName值等等,我们依次来看

  • ID方式来定位

大概有两种方式,一种是在ID值前面添加TagName的值,另外一种则是不加,代码如下

driver.find_element_by_css_selector("#id_value")  # 不添加前面的`TagName`值
driver.find_element_by_css_selector("tag_name.class_value")  # 不添加前面的`TagName`值

当然有时候这个TagName的值非常的冗长,中间可能还有空格,那么这当中的空格就需要用点“.”来替换

driver.find_element_by_css_selector("tag_name.class_value1.calss_value2.class_value3")  # 不添加前面的`TagName`值

我们仍然以百度首页的搜索框为例,它的HTML代码如下

要是用CssSelector.class()方式来实现元素的定位的话,Python代码该这样来实现,和上面Xpath()的方法一样,可以稍微偷点懒,通过复制/粘贴的方式从开发者工具当中来获取元素的位置

代码如下

driver.find_element_by_css_selector('#kw')

linkText()方式来定位

这个方法直接通过链接上面的文字来定位元素,案例如下

通过linkText()方法来定位“地图”这个元素,代码如下

driver.find_element_by_link_text("地图").click()

浏览器的控制

修改浏览器窗口的大小

我们可以通过使用set_window_size()这个方法来修改浏览器窗口的大小,代码如下

# 修改浏览器的大小
driver.set_window_size(500, 900)

同时还有maxmize_window()方法是用来实现浏览器全屏显示,代码如下

# 全屏显示
driver.maximize_window()

浏览器的前进与后退

前进与后退用到的方法分别是forward()back(),代码如下

# 前进与后退
driver.forward()
driver.back()

浏览器的刷新

刷新用到的方法是refresh(),代码如下

# 刷新页面
driver.refresh()

除了上面这些,webdriver的常见操作还有

  • 关闭浏览器:get()

  • 清除文本:clear()

  • 单击元素:click()

  • 提交表单:submit()

  • 模拟输入内容:send_keys()

我们可以尝试着用上面提到的一些方法来写段程序

from selenium import webdriver
from time import sleepdriver = webdriver.Chrome(executable_path="chromedriver.exe")
driver.get("https://www.baidu.com")
sleep(3)
driver.maximize_window()
sleep(1)
driver.find_element_by_xpath('//*[@id="s-top-loginbtn"]').click()
sleep(3)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__userName"]').send_keys('12121212')
sleep(1)
driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_11__password"]').send_keys('testtest')
sleep(2)
driver.refresh()
sleep(3)
driver.quit()

output

鼠标的控制

鼠标的控制都是封装在ActionChains类当中,常见的有以下几种

引入action_chains类
from selenium.webdriver.common.action_chains import ActionChains
# 右击
ActionChains(driver).context_click(element).perform()
# 双击
ActionChains(driver).double_click(element).perform()
# 拖放
ActionChains(driver).drag_and_drop(Start, End).perform()
# 悬停
ActionChains(driver).move_to_element(Above).perform()
# 按下
ActionChains(driver).click_and_hold(leftclick).perform()
# 执行指定的操作

键盘的控制

webdriver中的Keys()类,提供了几乎所有按键的方法,常用的如下

# 删除键
driver.find_element_by_id('xxx').send_keys(Keys.BACK_SPACE)
# 空格键
driver.find_element_by_id('xxx').send_keys(Keys.SPACE)
# 回车键
driver.find_element_by_id('xxx').send_keys(Keys.ENTER)
# Ctrl + A 全选内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'a')
# Ctrl + C/V 复制/粘贴内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'c')
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'v')

其他的一些键盘操作

  • 向上箭头:Keys.ARROW_UP

  • 向下箭头:Keys.ARROW_DOWN

  • 向左/向右箭头:Keys.ARROW_LEFT/Keys.ARROW_RIGHT

  • Shift键:Keys.SHIFT

  • F1键:Keys.F1

元素的等待

有显示等待和隐式等待两种

显示等待

显示等待指的是设置一个超时时间,每隔一段时间去查看一下该元素是否存在,如果存在则执行后面的内容,要是超过了最长的等待时间,则抛出异常(TimeoutException),需要用到的是WebDriverWait()方法,同时配合untilnot until方法

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

其中的参数:

  • timeout: 最长超时时间,默认以秒为单位

  • poll_frequency: 检测的时间间隔,默认是0.5s

  • ignored_exceptions: 指定忽略的异常,默认忽略的有NoSuchElementException这个异常

我们来看下面的案例

driver = webdriver.Chrome()
driver.get("http://somedomain/url_that_delays_loading")
try:    element = WebDriverWait(driver, 10).until(           EC.presence_of_element_located((By.ID, "myDynamicElement")))
finally:    driver.quit()

上面的代码最多等待10秒,超时后就抛出异常,但是假设在等了3秒之后就找到了这个元素,那么也就不会多等下剩下的7秒钟时间,而是继续执行后续的代码

隐式等待

主要使用的是implicitly_wait()来实现

browser = webdriver.Chrome(path)
# 隐式等待3秒
browser.implicitly_wait(3)

获取Cookie

Cookie是用来识别用户身份的关键,我们通常也是通过selenium先模拟登录网页获取Cookie,然后再通过requests携带Cookie来发送请求。

webdriver提供了cookies的几种操作,我们挑选几个常用的来说明

  • get_cookies():以字典的形式返回当前会话中可见的cookie信息

  • get_cookies(name): 返回cookie字典中指定的的cookie信息

  • add_cookie(cookie_dict): 将cookie添加到当前会话中

下面看一个简单的示例代码

driver=webdriver.Chrome(executable_path="chromedriver.exe")
driver.get(url=url)
time.sleep(1)cookie_list=driver.get_cookies()
cookies =";".join([item["name"] +"=" + item["value"] + "" for item in cookie_list])
session=requests.session()headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36','cookie': cookies
}response=session.get(url=url,headers=headers)
soup=BeautifulSoup(response.text,'lxml')

调用JavaScript

webdriver当中可以使用execut_script()方法来实现JavaScript的执行,下面我们来看一个简单的例子

from selenium import webdriver
import time
bro=webdriver.Chrome(executable_path='./chromedriver')
bro.get("https://www.baidu.com")# 执行js代码
bro.execute_script('alert(10)')
time.sleep(3)
bro.close()

除此之外,我们还可以通过selenium执行JavaScript来实现屏幕上下滚动

from selenium import webdriver
bro=webdriver.Chrome(executable_path='./chromedriver')
bro.get("https://www.baidu.com")
# 执行js代码
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')

selenium进阶

selenium启动的浏览器,会非常容易的被检测出来,通常可以通过window.navigator.webdriver的值来查看,如果是true则说明是使用了selenium模拟浏览器,如果是undefined则通常会被认为是正常的浏览器。

那么我们似乎可以执行下面这段代码来强行更改window.navigator.webdriver最后返回的值

driver.execute_script('Object.defineProperties(navigator,{webdriver:{get:()=>false}})'
)

当然这种方法也有一定的缺陷,毕竟这段代码是在网页已经加载完毕之后才运行的,此时网页自身的JavaScript程序已经通过读取window.navigator.webdriver知道你使用的是模拟浏览器了。所以我们有两种办法来解决这个缺陷。

  • 在Chrome当中添加实验性功能参数

代码如下

from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptionsoption = ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
driver=Chrome(options=option)
  • 调用chrome当中的开发工具协议的命令

核心思想就是让Chrome浏览器在打开页面,还没有运行网页自带的JavaScript代码时,先来执行我们给定的代码,通过execute_cdp_cmd()方法,

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""
})

当然为了更好隐藏指纹特征,我们可以将上面两种方法想结合

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path='./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""
})
driver.get(url)

最后的最后,我们也可以通过运行stealth.min.js文件来实现隐藏selenium模拟浏览器的特征,这个文件之前是给puppeteer用的,使得其隐藏浏览器的指纹特征,而让Python使用时,需要先导入这份JS文件

import time
from selenium.webdriver import Chromeoption = webdriver.ChromeOptions()
option.add_argument("--headless")# 无头浏览器需要添加user-agent来隐藏特征
option.add_argument('user-agent=.....')
driver = Chrome(options=option)
driver.implicitly_wait(5)with open('stealth.min.js') as f:js = f.read()driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": js
})driver.get(url)

资讯

程序员敲诈老板,或面临37年监禁

资讯

Meta新语音模型可支持128种语言交流

资讯

全球首个活体机器人,能生娃

专访

低代码平台产品的使用者都是谁?

分享

点收藏

点点赞

点在看

Python 爬虫利器 Selenium 从入门到进阶相关推荐

  1. 从入门到入土:Python爬虫学习|Selenium自动化模块学习|简单入门|轻松上手|自动操作浏览器进行处理|chrome|PART01

    此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) 本人博客所有文章纯属学习之用,不涉及商业利益.不合适引用,自当删除! 若 ...

  2. Python爬虫利器四之PhantomJS的用法

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) 原文这篇文章讲解的纯PhantomJS的用法,讲得比较细致,具体可以跟Python也可以跟node等结合使用. ...

  3. 小白学 Python 爬虫(20):Xpath 进阶

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  4. Python爬虫之selenium库使用详解

    Python爬虫之selenium库使用详解 本章内容如下: 什么是Selenium selenium基本使用 声明浏览器对象 访问页面 查找元素 多个元素查找 元素交互操作 交互动作 执行JavaS ...

  5. python爬虫之selenium,谷歌无头浏览器

    python爬虫之selenium和PhantomJS 主要的内容 lenium hantomjs 无头浏览器 的懒加载 一 什么是selenium? 介绍 它是python中的一个第三方库,对外提供 ...

  6. Python爬虫之selenium高级功能

    Python爬虫之selenium高级功能 原文地址 表单操作 元素拖拽 页面切换 弹窗处理 表单操作 表单里面会有文本框.密码框.下拉框.登陆框等. 这些涉及与页面的交互,比如输入.删除.点击等. ...

  7. python 模拟浏览器selenium_浅谈python爬虫使用Selenium模拟浏览器行为

    前几天有位微信读者问我一个爬虫的问题,就是在爬去百度贴吧首页的热门动态下面的图片的时候,爬取的图片总是爬取不完整,比首页看到的少.原因他也大概分析了下,就是后面的图片是动态加载的.他的问题就是这部分动 ...

  8. python爬虫——使用selenium爬取微博数据(一)

    python爬虫--使用selenium爬取微博数据(二) 写在前面 之前因为在组里做和nlp相关的项目,需要自己构建数据集,采用selenium爬取了几十万条微博数据,学习了很多,想在这里分享一下如 ...

  9. [Python爬虫]使用Selenium操作浏览器订购火车票

    这个专题主要说的是Python在爬虫方面的应用,包括爬取和处理部分 [Python爬虫]使用Python爬取动态网页-腾讯动漫(Selenium) [Python爬虫]使用Python爬取静态网页-斗 ...

最新文章

  1. bzoj1717 [Usaco2006 Dec]Milk Patterns 产奶的模式
  2. SVN删除服务器端项目文件
  3. 写程序时,经常要重载OnPaint,定位很麻烦,现在有个简单办法
  4. flink編譯hadoop3.1.2(失败,这个问题没有意义,关闭)
  5. 二叉树的广度优先遍历(层序遍历)
  6. 【软件开发综合实验】文本压缩软件
  7. 《Summer Tree》第八期封面
  8. Java代码模拟实现购物车
  9. BAT转EXE 小程序
  10. VoIP技术(2)--语音编码算法-1
  11. Extracting Data from XML
  12. 展望未来~走向计算机之路
  13. Java模式设计卖电脑实验报告,面向对象(Java)实验0继承、接口和多态
  14. 独家全新娱乐性超高的喝酒神器微信小程序源码支持流量主解锁多人对战等等
  15. java的Http的PUT请求
  16. 【若依(ruoyi)】summernote富文本编辑器的使用
  17. 高通转单台积电,联发科的高端梦悬了
  18. Oracle 从入门到精通系列 - 前言
  19. 自媒体新手入门攻略,学习干货内容了解运营技巧
  20. 星钻VIP已经来了,银河VIP还会远吗?

热门文章

  1. python查询mysql中文乱码问题
  2. 从HelloWorld看Knative Serving代码实现
  3. BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
  4. SilverLight 4页面跳转大全
  5. ExtJs 备忘录(3)—— Form表单(三) [ 数据验证 ]
  6. css中的垂直居中方法
  7. 利用phpmailer类邮件发送
  8. HashSet 详解
  9. 理解LoadRunner中的局部变量和全局变量
  10. 编译android不再需要jdk1.5