当前位置:   article > 正文

【Python爬虫】selenium的详细使用方法_selenium 4.16使用

selenium 4.16使用

selenium介绍

selenium是一个用于web应用测试的工具,selenium所做的测试会直接运行在浏览器中,就像真人进行操作一样,像是打开浏览器,输入账号密码登录等等。目前selenium支持大部分的浏览器,例如:IE,Mozilla Firefox,Safari,Google Chrome,Opera,Edge等等浏览器,selenium是一个相当成功的开源工具,支持众多的语言包括C#,Java,php,python等等,在爬虫领域也有他的一席之地

在这里插入图片描述

安装selenium

win+r输入cmd,输入以下代码即可完成python selenium库的安装

pip install selenium
  • 1

安装完毕后可以使用pip show selenium来检验是否安装成功

安装浏览器驱动

不同的浏览器需要不同的驱动去支持,但目前浏览器版本的更新速度很快,有时候驱动的版本赶不上浏览器的版本,这时候可以根据需求选择降低浏览器版本或者在selenium的高版本中有些功能不需要webdriver也能实现(个人经历,有误还请指出)

确认版本号并下载

本人常用浏览器为edge,且谷歌的webdriver更新速度较慢,所以这里就用edge来展示操作内容,但是最好推荐使用firefox进行测试,官方推荐的报错的概率小一些

在这里插入图片描述

上图中的"版本 117.0.2045.60 (正式版本) (64 位)"中的117.0.2045.60就是浏览器的版本号,然后去edge的webdriver网站上查找相关的webdiver驱动即可

在这里插入图片描述

选择自己的版本进行下载即可,我的是x64版本的,点击开始下载,下载完毕后将文件进行解压,获得一个名为msedgedriver.exe的运行文件,将该文件保存到你想放的位置

在这里插入图片描述

配置环境变量

搜索查看高级系统设置,或者找到【我的电脑】——【右键打开属性】——【高级系统设置】——【环境变量】

在这里插入图片描述
在这里插入图片描述

检验环境变量

运行以下代码,检测是否可以成功运行,其他浏览器指令类似

from selenium import webdriver

#edge
driver=webdriver.Edge()
#chrome
driver=webdriver.Chrome()
#firefox
driver=webdriver.Firefox()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

定位元素

注意:在说定位前,需要注意的是selenium的新旧版本是有差别的,本文章将对两种都分别给出代码

随便打开一个网页点击F12打开开发者工具,可以看到下面的就是网页的代码,我们要做的就是定位我们需要的元素,比如说登录框这个a标签,但是我们首先要学会打开这个页面

在这里插入图片描述

打开指定网页

from selenium import webdriver

#edge
driver=webdriver.Edge()
driver.get('https://www.pixiv.net/')
  • 1
  • 2
  • 3
  • 4
  • 5

运行上述代码后会发现浏览器在出现一瞬间后就会马上消失,为了方便我们看,可以添加语句防止selenium自动关闭浏览器

from selenium import webdriver
from selenium.webdriver.edge.options import Options

#设置options
options=Options()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

另外一种写法,两种写法效果一致,下面一种代码较为简洁

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出网页代码

定位的标准就是在这个driver获取的网页源码中找的,否则会报错

#在driver.get('https://www.pixiv.net/')后加下面一句话
print(driver.page_source)
  • 1
  • 2

运行代码

<html lang="zh" class=" page-cool-index" xmlns:wb="http://open.weibo.com/wb" data-theme="default"><head>

<meta charset="utf-8">
    <meta name="viewport" content="width=1160">


<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="pixiv">
<meta property="fb:app_id" content="140810032656374">
<meta property="wb:webmaster" content="4fd391fccdb49500">
                        <meta property="twitter:card" content="summary_large_image">
                                <meta property="twitter:site" content="@pixiv">
                                <meta property="twitter:title" content="插画交流网站 [pixiv]">
                                <meta property="twitter:description" content="pixiv是提供插画等作品的投稿、阅览服务的「插画交流网站」。这里有各种各样不同风格的投稿作品,我们还会举办官方、用户企画的各种比赛。">
                                <meta property="twitter:image" 
......展示一部分
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

ID定位

我们知道html中的id标签具有唯一性,就像是车牌号或是身份证之类的,比如有如下的标签,可以知道这个form标签的id为nav-searchform

<form id="nav-searchform" class="" style="border-radius:8px 8px 8px 8px;"></form>
  • 1

现在我们通过id定位到这个form,如果定位到就输出,下面是演示代码

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element_by_id('nav-searchform')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element(By.ID,'nav-searchform')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="b141db7f98f14935fcf0b02a16ec9697", element="73445B08D791A4DDB8C1767A1DBFBF95_element_38")>
  • 1

NAME定位

标签中的name参数可以不是唯一的,所以这了就有两个函数等下分别介绍,有如下html代码片段

<meta name="viewport" content="width=1160">
  • 1

现在我们通过name对这个标签进行定位,找到了就输出,下面是演示代码

获取单一标签

较老版本
from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element_by_name('viewport')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
较新版本
from selenium import webdriver
from selenium.webdriver.common.by import By

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element(By.NAME,'viewport')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="25b0d0b64d3509caceeeb4d230439803", element="4788C4EB780A9EB1FC46683E4EE01C58_element_19")>
  • 1

在上文中我们提到,name不是唯一的,所以说selenium提供了多个定位的函数,将element改成elements即可,演示代码将打印获取到的数据是什么样的

获取多个标签

较老版本
from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
print(driver.find_elements(By.NAME,'viewport'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
较新版本
from selenium import webdriver
from selenium.webdriver.common.by import By

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
print(driver.find_elements(By.NAME,'viewport'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行结果

[<selenium.webdriver.remote.webelement.WebElement (session="261f740729f8b59c23a38ed2f5f4641d", element="E79CC23F1DED57B9C919314A269D19B4_element_19")>]
  • 1

返回的是一个列表,如果我们要对每一个都进行操作,只要遍历即可

CLASS定位

在html中,class参数也不是唯一的,所以和NAME定位一样也有获取多个标签的方法,这里不再举例,只展示单个标签获取的代码,例如有如下html片段

<a href="/login.php?ref=wwwtop_accounts_index" class="signup-form__submit--login">登录</a>
  • 1

现在我们通过class对这个标签进行定位,找到了就输出内容,下面是演示代码

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element_by_class_name('signup-form__submit--login')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element(By.CLASS_NAME,'signup-form__submit--login')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="d082718db12b989c1ddb140d2c6a3993", element="D076E06740ACFCF12941AB330A3E4FCB_element_16")>
  • 1

TAG定位

在html中,tag就是标签例如input标签,div标签等等,我们也可以通过tag来定位,显然tag不止有一个,同样和name和class一样可以找多个,由于原理相同,这里只展示获取一个,有如下代码

<meta charset="utf-8">
<meta name="viewport" content="width=1160">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="pixiv">
  • 1
  • 2
  • 3
  • 4

现在我们通过class对这个标签进行定位,找到了就输出内容,下面是演示代码

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element_by_tag_name('meta')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element(By.TAG_NAME,'meta')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="98f22eab1bc456c95a8caafea956d8c6", element="A08DF5AC2486B8A4A58AF09E9A149177_element_19")>
  • 1

XPATH定位

xpath是一种常见的对html和xml文本进行定位的一种手段,下面先简单介绍一下xpath中常见的语法,由于部分xpath的表述同样有多个标签符合要求,所以同样拥有查找多个的方法,这里不再做过多展示

#使用绝对路径(层级关系)进行定位
xpath="/html/body/div[2]/div[2]/div[1]/div[1]/div/div/form"
#使用元素属性进行定位
xpath="//*[@class='username']"    #注意此处单引号和双引号的使用
#使用层级+元素属性进行定位
xpath="//div[@class='center-search__bar']/form/div/input"
#在xpath中使用逻辑表达进行定位
xpath="//*[@name='viewport' and @content='width=1160']"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

有如下html片段,接下来将使用xpath对其进行定位,找到了就输出

<input class="nav-search-input" type="text" autocomplete="off" accesskey="s" maxlength="100" x-webkit-speech="" x-webkit-grammar="builtin:translate" value="" placeholder="李佳琦offer3" title="李佳琦offer3">
  • 1

下面是演示代码

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element_by_xpath('//*[@id="nav-searchform"]/div[1]/input')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element(By.XPATH,'//*[@id="nav-searchform"]/div[1]/input')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="02861773f803549fb01e7c8e57b904e2", element="DB7C3EEAA07DFC4162BAA688C9963C04_element_2")>
  • 1

CSS定位

css定位十分灵活,一般速度较快,但是需要对css语法有一定的掌握才能更好的使用,以下介绍一些常见的语法,同时和name一样也有其不唯一性,这里不在赘述

方法举例概述
**选择所有
#id#i_cecream选择id="i_cecream"的标签
.class.bili-feed4选择class="bili-feed4"的标签
elementform选择所有<form>标签
element1>element2form>input选择父标签为<form>之下的所有<input>标签
element1+element2form+input选择在同一级在<form>之后的所有<input>标签
[attribute=value]type=“text/javascript”找到所有type="text/javascript"的标签

比如有如下html片段,接下来将使用css对其进行定位,找到了就输出

<a href="//cm.bilibili.com" data-target-url="**" data-v-7f4a51a0=""></a>
  • 1

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element_by_css_selector('[href="//cm.bilibili.com"]')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.bilibili.com/')
#定位元素
element=driver.find_element(By.CSS_SELECTOR,'[href="//cm.bilibili.com"]')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="1a8502b5fd94e89fb3672d5fb2ed0a0b", element="E808FDEC6AEA4FA3127234D28D4406C2_element_179")>
  • 1

LINK定位

link定位是通过定位文本内容来定位标签,对于动态的标签并不是十分的好用,link定位也和name定位类似有不唯一性,例如有如下html片段

<a href="/login.php?ref=wwwtop_accounts_index" class="signup-form__submit--login">登录</a>
  • 1

下面将通过"登录"来进行对标签的定位,演示代码如下

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element_by_link_text('登录')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element(By.LINK_TEXT,'登录')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="8c18f357881cc23da103887ff7edb56a", element="E6F3BF9A611DD85EB20D78401F4609A4_element_19")>
  • 1

PARTIAL_LINK 定位

对于较长的文本内容,如果全部复制到代码中会影响到代码的简洁性的观赏性,所以partial_link就是通过部分内容来进行定位,同样的name等定位方法一样具有不唯一性,例如有如下html片段

<a href="https://policies.google.com/terms"> Terms of Service</a>
  • 1

下面将通过"登录"来进行对标签的定位,演示代码如下

较老版本

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element_by_partial_link_text('Terms')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

较新版本

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
#定位元素
element=driver.find_element(By.PARTIAL_LINK_TEXT,'Terms')
print(element)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果

<selenium.webdriver.remote.webelement.WebElement (session="21869cd58281999dc690c87f145183a9", element="63373D4A1F4660B9672E1B408575CA74_element_19")>
  • 1

页面控制

在实际操作中根据需要我们要对浏览器的页面进行操作,比如刷新网页,切换标签页等等,就像我们手动控制一样,selenium也能实现这些功能

修改浏览器窗口

selenium中常见的三种方式调整浏览器窗口,自定义,最大窗口,最小化窗口

自定义大小

通过使用set_window_size(宽,高)来调整窗口大小,代码实现如下

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
driver.set_window_size(1000,1000)	#写在driver.get()的上面也行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

最小化窗口

通过使用minimize_window()方法实现浏览器最小化

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
driver.minimize_window()	#写在driver.get()的上面也行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

全屏窗口

通过使用maximize_window()方法实现浏览器最小化

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
driver.get('https://www.pixiv.net/')
driver.maximize_window()	#写在driver.get()的上面也行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

页面的前进与后退

selenium提供了back()和forward()两个方法实现页面的前进与后退

from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开pixiv网页
driver.get('https://www.pixiv.net/')
time.sleep(2.5)
#打开bilibili网页
driver.get('https://www.bilibili.com/')
time.sleep(2.5)
#后退至pixiv网页
driver.back()
time.sleep(1.5)
#前进到bilibili网页
driver.forward()
time.sleep(1.5)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

上述方法中使用了两次,如果想要在新标签页打开,可以使用js的方法进行操作

#打开pixiv网页
driver.get('https://www.pixiv.net/')
time.sleep(2.5)
#打开bilibili网页
driver.get('https://www.bilibili.com/')
time.sleep(2.5)

#替换为如下内容

#打开pixiv网页
driver.get('https://www.pixiv.net/')
time.sleep(2.5)
#在新建标签页打开bilibili网页
js="window.open('https://www.bilibili.com/')"
driver.execute_script(js)
time.sleep(2.5)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

页面刷新

有一些特殊情况下我们可能需要刷新页面才能加载出来,要通过刷新来获取最新数据,这就要用到refresh()方法了

from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开pixiv网页
driver.get('https://www.pixiv.net/')
driver.refresh()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

切换窗口

在我们访问网站的时候,比如某站就会弹出一个登录窗口让我们登录,但是我们直接定位这些窗口的元素是无法直接定位到的,所以要先切换到窗口上,一般我们把这些窗口称为句柄,当我们点击登录按钮后就会弹出新的句柄,我们通过driver.window_handles来获取句柄,由于句柄是按时间顺序获得的,取得的数据类似于数据和列表,可以通过索引来进行切换,由于我们一般会获取最新的句柄,所以一般会取最新的也就是-1所对应的句柄,下面是某站的代码演示

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b站
driver.get('https://www.bilibili.com/')
time.sleep(1.5)
#点击登录按钮
login_element=driver.find_element(By.CSS_SELECTOR,'#i_cecream > div.bili-feed4 > div.bili-header.large-header > div.bili-header__bar > ul.right-entry > li:nth-child(1) > li > div.right-entry__outside.go-login-btn > div > span')
login_element.click()
#获取句柄并切换至最新句柄
windows=driver.window_handles
driver.switch_to.window(windows[-1])
#点击注册按钮
register_element=driver.find_element(By.CLASS_NAME,'btn_other')
register_element.click()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

鼠标控制

selenium的鼠标控制可以模拟人一样的操作对元素、标签进行点击来达到我们想要的效果或者数据,通常我们正常的操作有:单击左键、单击右键、双击、拖拽、悬停等

鼠标单击左键

我们一般使用单机左键来实现一些普通的点击功能,如点击登录等,在selenium中也是一样,对标签使用click()的方法即可完成简单的单击左键,下面以点击某网站的登录键为例

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开p站
driver.get('https://www.pixiv.net/')
#点击登录按钮
login_element=driver.find_element(By.CLASS_NAME,'signup-form__submit--login')
login_element.click()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

鼠标单击右键

由于单击左键和单击右键差别较大,所以selenium提供了不同的方法需要用到名为ActionChains的类来实现,下面以单击右键某网站的登录键为例

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开p站
driver.get('https://www.pixiv.net/')
#右键点击登录按钮
login_element=driver.find_element(By.CLASS_NAME,'signup-form__submit--login')
ActionChains(driver).context_click(login_element).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

鼠标左键双击

双击与单机同样有所差异,所以我们依旧要使用ActionChains的类来实现,下面我们将双击某网站输入密码的小眼睛来观察

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b站登录界面
driver.get('https://passport.bilibili.com/login')
#左键双击小眼睛按钮
eye_element=driver.find_element(By.CLASS_NAME,'eye-btn')
ActionChains(driver).double_click(eye_element).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

鼠标拖拽

将一个元素拖拽到另一个要释放的元素上,比如滑动登录和设计拖拽等就用到这种方法,以下是某网站的实例,我们将标题拖到一个画布上

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开某网站的设计界面并点击文字选项
driver.get('https://www.canva.cn/design/play?locale=zh-CN')
time.sleep(2)
text_element=driver.find_element(By.CLASS_NAME,'sW2TIg')
text_element.click()
driver.implicitly_wait(20)
#定位标题元素位置
title_element=driver.find_element(By.CLASS_NAME,'mqHySA')
#定位画布元素位置
draw_element=driver.find_element(By.CLASS_NAME,'xvJQZA')
#推拽图片至画布位置
ActionChains(driver).drag_and_drop(title_element, draw_element).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

鼠标悬停

有时候当我们鼠标悬停在某个元素上的时候才会出现内容,所以selenium也十分贴心的准备了这个功能,同样是在ActionChains的类中实现,下面以某科技网站为例

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开apple网站
driver.get('https://www.apple.com')
#定位Store标签位置
store_element=driver.find_element(By.XPATH,'//*[@id="globalnav-list"]/li[2]/div/div/div[1]')
time.sleep(1)
#移动鼠标至Store并悬浮,因为edge有外部弹窗,所以我们写一个死循环,让鼠标一直悬浮在Store上
while True:
    ActionChains(driver).move_to_element(store_element).perform()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

键盘控制

我们使用键盘常用的就是输入作用,selenium也实现了这些功能,同时还实现了快捷键的使用,比如复制粘贴的键盘快捷键,但要实现快捷键的使用则需要使用Keys来实现

输入内容

输入内容通过定位标签并输入数据来实现,使用了send_keys()的方法函数,下面是输入登录框的代码实现

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b网的登录页
driver.get('https://passport.bilibili.com/login')
#定位账号标签
username_element=driver.find_element(By.XPATH,'//[@id="app"]/div[2]/div[2]/div[3]/div[2]/div[1]/div[1]/input')
#输入内容
username_element.send_keys('123456789')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

其他操作

使用其他操作就要用到Keys来实现,下面是Keys中的常见用法

代码等效操作
Keys.ENTER回车键
Keys.BACK_SPACE按一次删除键
Keys.CONTROL按住Ctrl键
Keys.F1按F1键【F2等同理】
Keys.SPACE按空格键
Keys.TAB按Tab键
Keys.ESCAPE按ESC键
Keys.ALT按Alt键
Keys.SHIFT按Shift键
Keys.ARROW_DOWN按向下箭头
Keys.ARROW_LEFT按向左箭头
Keys.ARROW_RIGHT按向右箭头
Keys.ARROW_UP按向上箭头

下面演示其中的几种来感受以下效果

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b网的登录页
driver.get('https://passport.bilibili.com/login')
#定位账号标签
username_element=driver.find_element(By.CSS_SELECTOR,'#app > div.login_wp > div.login__main > div.main__right > div.login-pwd > div.tab__form > div:nth-child(1) > input[type=text]')
#输入内容
username_element.send_keys('123456789')
time.sleep(1.5)
#删除一个符号
username_element.send_keys(Keys.BACKSPACE)
time.sleep(1.5)
#全选内容
username_element.send_keys(Keys.CONTROL,'a')
time.sleep(1.5)
#按Tab键
username_element.send_keys(Keys.TAB)
time.sleep(1.5)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

等待操作

由于许多页面采用异步实现不可能一次性全部加载完毕,所以我们需要进行等待,而等待操作分为显式等待、隐式等待两种,这两者都是selenium自己提供的,还有一种是外界的强制等待,也就是使用time.sleep()来实现进程的休息

显式等待

我们设定一个超时的时限,每过一段实现就去检验一次某元素是否出现,如果出现了,就执行下一句代码,如果超出了时间限制还没有出现,则报错,我们需要用到一个叫WebDriverWait的类,代码基本格式如下

WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None).until(expected_conditions.title_is(data),message='')
#dirver就是驱动,你写的driver.get()的driver
#timeout就是超时时间,单位是秒
#poll_frequency就是每次检测的时间间隔,默认是0.5秒检测一次
#ignored_exceptions就是指定忽略的异常,如果在调用until或until_not的过程中抛出指定忽略的异常,则不中断代码,默认忽略的只有NoSuchElementException
#until()也可改为until_not(),until()用于指定预期条件的判断方法,在等待期间,每隔一段时间调用该方法,判断元素是否存在,直到元素出现,until_not()则正好相反,当元素消失或指定条件不成立,则继续执行后续代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

WebDriverWait方法函数判断由expected_conditions提供,可以在设置message来返回自定义报错信息,以下是常见的几种方法判断函数,先来定义一下方法判断中要出现的参数

locator=(By.ID,"1")
element = driver.find_element_by_id('1')
content='1'
  • 1
  • 2
  • 3
方法概述
title_is(content)判断当前页面的title是否等于content
title_contains(content)判断当前页面的title是否包含content
presence_of_element_located(locator)判断元素是否被加到了dom树里,但并不代表该元素一定可见
visibility_of_element_located(locator)判断元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of(element)同上,但传入的是element
text_to_be_present_in_element(locator ,content)判断元素中的text是否包含了content
text_to_be_present_in_element_value(locator ,content)判断元素中的value属性是否包含了content
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)判断元素中是否可见并且是可点击的
element_to_be_clickable(locator)等待元素从dom树中移除
element_to_be_selected(element)等待元素从dom树中移除
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.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b网的登录页
driver.get('https://passport.bilibili.com/login')
#定位标签
element = WebDriverWait(driver, 8, 0.5).until(
            EC.presence_of_element_located((By.ID, '1')),
                                           message='访问超时')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

运行结果

selenium.common.exceptions.TimeoutException: Message: 访问超时
  • 1

隐式等待

隐式等待同样是设置时间,如果没有被加载出来就抛出NoSuchElementException异常,在隐式等待的情况下你是可以在下面写driver.find_element()的语段的,如果没有找到,隐式就会不断的查找元素,知道被找到或者超出时间限制抛出异常,隐式等待语法为driver.implicitly_wait(“时间【单位秒】”),下面是示例

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开b网的登录页
driver.get('https://passport.bilibili.com/login')
#设置隐式等待时间
driver.implicitly_wait(5)
#设置初始时间用于计时
start=time.time()
#查找元素
try:
    element=driver.find_element(By.ID,'1')
except Exception as E:
    print('error')
finally:
    #输出耗时
    print(time.time()-start)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

运行结果

error
5.047070503234863
  • 1
  • 2

强制等待

强制等待需要使用time.sleep()来实现,单位为秒,这里不再过多赘述,需要注意的是,time.sleep()是一种进程挂起,相比隐式等待,如果设定等待时间均为5秒,而元素在2秒内被加载出来,此时隐式等待将直接运行下一段代码,而强制等待则需要等待5秒结束

表单切换

由于网页会使用嵌套来写也就是iframe和frame,使用嵌套的表单selenium是无法直接获取的,所以就有了表单切换这个需求,下面是代码演示

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开某视频网站
driver.get('http://yhdm72.com/acg/68717/1.html')
driver.implicitly_wait(10)
#查找iframe标签
driver.switch_to.frame('playiframe')    #默认使用id和name进行定位
#因为该网站有两个嵌套且id相同,所以切换两次
driver.switch_to.frame('playiframe')

#使用xpath定位方法
#iframe_element=driver.find_element(By.XPATH,'/html/body/div[3]/div[2]/iframe')
#driver.switch_to.frame(iframe_element)

#查找video标签
video_element=driver.find_element(By.TAG_NAME,'video')
print(video_element.get_attribute('src'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

运行结果,可知这个src是加密

blob:http://ss2.quelingfei.com:9900/8322436d-6f35-4f90-905f-531cde8352e5
  • 1

JS弹窗处理

弹出js弹窗时,我们先定位switch_to.alert来获取弹窗,然后在使用方法进行操作

方法概述
text获取弹窗中的文字
accept确认弹窗内容
dismiss取消弹窗
send_keys发送内容至警告框

下面是对某网站的实际操作

from selenium import webdriver
import time

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://incsky16.github.io/2022/06/18/142test/')
#切换至弹窗
alert=driver.switch_to.alert
time.sleep(2)
#点击取消
alert.dismiss()
time.sleep(2)
#切换至下一个弹窗
new_alert=driver.switch_to.alert
#获取内容并点击确认
print(new_alert.text)
time.sleep(2)
new_alert.accept()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行结果

密码错误,将返回主页!
  • 1

文件处理

常见的有文件上传处理,以及文件下载处理,selenium也同样可以实现

上传文件

一般上传文件是使用input标签写的,所以说可以直接写入文件路径就行,下面是示例

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://deershare.com/send')
#查找input标签
video_element=driver.find_element(By.XPATH,'/html/body/div[1]/div[1]/div[2]/div[1]/div[3]/input')
#输入内容
video_element.send_keys(r'C:\Users\14040\Desktop\新建文本文档.txt')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

下载文件

下载文件也十分简单,找到标签点击下载即可,下面是示例代码

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.lifeofpix.com/')
driver.implicitly_wait(5)
#查找下载标签
download_element=driver.find_element(By.CLASS_NAME,'download')
download_element.click()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Cookie的操作

cookie是浏览器与服务器会话的十分重要的东西,webdriver对cookie有增删查的操作,下面是具体用法和说明

方法概述
get_cookies()以字典形式返回会话中的cookie全部信息
get_cookie(name)返回字典中key=name的cookie信息
add_cookie(cookie_dict)添加自定义cookie到会话中
delete_cookie(name)删除key=name的cookie信息
delete_all_cookies()删除会话范围内的所有cookie

一下是演示代码,只展示一部分的方法

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.apple.com/')
#打印当前所有cookie
print(driver.get_cookies())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行结果如下

[{'domain': '.apple.com', 
  'expiry': 1697020222, 
  'httpOnly': False, 
  'name': 's_vi', 
  'path': '/', 
  'sameSite': 'None',
  'secure': True,
  'value': '[CS]v1|3293391B4A21700D-4000122643359156[CE]'},
 {'domain': '.apple.com', 
  'httpOnly': False,
  'name': 'mk_epub', 
  'path': '/', 
  'sameSite': 'Lax',
  'secure': True,
  'value': '%7B%22btuid%22%3A%221q1ybut%22%2C%22prop57%22%3A%22www.us.homepage%22%7D'},
 {'domain': '.apple.com',
  'httpOnly': False, 
  'name': 's_cc',
  'path': '/',
  'sameSite': 'Lax',
  'secure': True,
  'value': 'true'},
 {'domain': '.apple.com', 
  'expiry': 1697020221, 
  'httpOnly': False, 
  'name': 's_fid', 
  'path': '/', 
  'sameSite': 'Lax',
  'secure': True, 
  'value': '63B91D4F3A5FB748-21AF8E60CCC2B67D'},
 {'domain': '.apple.com',
  'httpOnly': False, 
  'name': 'geo', 
  'path': '/', 
  'sameSite': 'Lax',
  'secure': False,
  'value': 'HK'}]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

JavaScript应用

有时候我们需要JavaScript才能实现某些功能,比如说懒加载的显示就需要我们滑到最下面才能继续加载,selenium提供了execute_script()的方法来实现对JavaScript的操控,下面介绍两种常见思想

通过页面坐标来滑动

我们来尝试一下使用页面坐标滑动来访问bilibili的首页,下面是代码示例

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.bilibili.com/')
#滑动页面
js='window.scrollTo(0,1000)'
driver.execute_script(js)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

滑动标签来实现懒加载运行

还是以b站首页为例,来演示一下一直执行懒加载,下面是代码示例

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.bilibili.com/')
driver.implicitly_wait(2)
#由于bilibili网页特殊性,先下滑
js = "window.scrollTo(0,1000);"
driver.execute_script(js)
time.sleep(2)
#写一个死循环,找到card就往下滑
while True:
    time.sleep(1)
    target=driver.find_elements(By.CLASS_NAME,'bili-video-card')[-1]
    driver.execute_script("arguments[0].scrollIntoView();", target)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

其他常用操作

东西太多不好逐个去讲解,这里的常见操作相对简单,所以就不逐一展示,我把怕们放在一个长代码中来展示并讲解,下面是代码内容及解释

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

#设置options
options=webdriver.EdgeOptions()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.bilibili.com/')

#关闭全部窗口并退出驱动
driver.quit()
#关闭当前页面
driver.close()
#对当前页面进行截图保存
driver.get_screenshot_as_file('你的路径')
# 获取当前页面url
driver.current_url
# 获取当前html源码
driver.page_source
# 获取当前页面标题
driver.title
# 获取浏览器名称(chrome)
driver.name
# 对页面进行截图,返回二进制数据
driver.get_screenshot_as_png()
# 设置浏览器尺寸
driver.get_window_size()
# 获取浏览器尺寸,位置
driver.get_window_rect()
# 获取浏览器位置(左上角)
driver.get_window_position()
# 设置浏览器尺寸
driver.set_window_size(width=100, height=100)
# 设置浏览器位置(左上角)
driver.set_window_position(x=100, y=100)
# 设置浏览器的尺寸,位置
driver.set_window_rect(x=100, y=100, width=100, height=100)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

关于反爬的一些配置

selenium虽然看上去十分强大,但是依然会被某些网站轻松检测出来,所以说我们就要对options进行一些设置来反反爬

header的设置

有时候我们会觉得selenium突然将页面弹出十分的麻烦,会导致电脑看上去十分混乱,selenium就提供了headless的方式来隐藏显示,但是headless有一个很大的缺陷,就是十分容易被网站检测到是爬虫,但是这里还是讲一下

headless

以下是不显示的无头浏览器headless的代码演示

from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
options.add_argument('--headless')
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://bot.sannysoft.com/')
#截图网页
driver.save_screenshot('page.png')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

我们会发现这是一片红,虽然说正常网站是不会太在意反爬这件事情的,但是但凡别人想反爬,我们这种方法肯定不行,所以我们尽量不使用headless来请求,那与之相对的,我们可以设置随机头来帮助我们这时就要用到一个fake-useragent的库

fake-useragent+selenium

首先我们先下载fake-useragent库,win+r并输入cmd回车进入命令提示符,输入以下代码完成下载

pip install fake-useragent
  • 1

由于fake-useragent远程访问获取的地址需要等待时间很久,所以我们使用本地加载的文件来进行获取

下载地址

下载完成后放在与你python文件运行的同级目录下,或者其他目录但要自己输入绝对路径来使用,下面来演示一下fake-useragent与selenium的结合

from fake_useragent import UserAgent
from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
ua=UserAgent(cache_path='fake_useragent.json')    #注意版本不同cache_path可能为path或者不用填写
user_agent=ua.random
options.add_experimental_option('detach', True)

#也可以在这里使用option.add_argument("--headless"),然后和下面的代码结合

options.add_argument(f'user-agent={user_agent}')
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://bot.sannysoft.com/')
#截图网页
driver.save_screenshot('page.png')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述

由上图我们可以知道,现在只有一个参数可以知道我们是爬虫了

隐藏指纹

在上面我们看到了我们还差一条就差不多躲过了大部分的网站了,我们现在将在这里实现,让上面的表格全部伪造成绿色。隐藏指纹这个事情已经有前人为我们开好了路,需要用到一个名为stealth.min.js的文件,我在这里提供下载资源和源码地址,将下好的文件放在与你python文件运行的同级目录下,或者其他目录但要自己输入绝对路径来使用

CSDN站内下载资源
源码地址

下面来演示一下使用,代码如下

from fake_useragent import UserAgent
from selenium import webdriver

#设置options
options=webdriver.EdgeOptions()
ua=UserAgent(cache_path='fake_useragent.json')    #注意版本不同cache_path可能为path或者不用填写
user_agent=ua.random
options.add_experimental_option('detach', True)
#也可以在这里使用option.add_argument("--headless"),然后和下面的代码结合
options.add_argument(f'user-agent={user_agent}')

#edge,将option传入edge中,并隐藏指纹
driver=webdriver.Edge(options=options)
with open('stealth.min.js') as f:
    js = f.read()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
  "source": js
})
#打开网站
driver.get('https://bot.sannysoft.com/')
#截图网页
driver.save_screenshot('page.png')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在这里插入图片描述

对网页Networks的记录

由于selenium的更新,新旧版本的获取networks的方法可能会有所不同,这里会进行区分,大家可以通过尝试来看是否可行,此外除了selenium自带的方法外,github上还有人提供了使用java的方法来实现记录,在下文中我也会进行呈现

selenium自带

这里将给大家讲解selenium自带的记录networks的方法,会分新旧两个版本进行讲解

较老版本

有多种方法进行实现,首先先将selenium中的方法,driver.get_log()的方法

from selenium import webdriver
import json

#设置caps
caps = {
        'browserName': 'edge',
        'loggingPrefs': {
            'browser': 'ALL',
            'driver': 'ALL',
            'performance': 'ALL',
        },
        'goog:edgeOptions': {
            'perfLoggingPrefs': {
            'enableNetwork': True,
            },
            'w3c': False,
        },
    }
driver = webdriver.Edge(desired_capabilities=caps)
driver.get('https://www.bilibili.com/')
#获取日志信息
networks = driver.get_log('performance')  
for network in networks:
    #将json格式信息转化为字典
    dic_info = json.loads(network["message"])  
    #request信息,在字典的键["message"]["params"]中
    info = dic_info["message"]["params"]    
    #打印一下request
    print(info)     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

由于并没有亲自尝试老版本的代码,可能出现纰漏,大家可以自己试试看

较新版本

在较新的版本中,selenium不在提供上面所用的方法,而是改用了selenium-wire的外部库来实现,首先下载selenium-wire库,win+r输入cmd打开命令提示符输入以下代码

pip install selenium-wire
  • 1

下面进行代码演示,并展示结果

from selenium.webdriver.edge.options import Options
from seleniumwire import webdriver

#设置options
options=Options()
options.add_experimental_option('detach', True)
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#打开网站
driver.get('https://www.bilibili.com/')
#输出network内容
for request in driver.requests:
    print(request.url)
    print(request.headers)
    print(request.method)
    print(request.response)
    print(request.date)
    break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

输出结果

#request.url
https://edge.microsoft.com/serviceexperimentation/v3/?osname=win&channel=stable&scpfull=0&scpguard=0&scpver=0&osver=10.0.19045&devicefamily=desktop&installdate=1674739257&clientversion=117.0.2045.60&experimentationmode=2

#request.headers
pragma: no-cache
cache-control: no-cache
sec-mesh-client-edge-version: 117.0.2045.60
sec-mesh-client-edge-channel: stable
sec-mesh-client-os: Windows
sec-mesh-client-os-version: 10.0.19045
sec-mesh-client-arch: x86_64
sec-mesh-client-webview: 0
x-client-data: eyIxIjoiMCIsIjEwIjoiIiwiMiI6IjAiLCIzIjoiMCIsIjQiOiI1NDUwNTU1ODEyNjE5MzA2NzIyIiwiNSI6IiIsIjYiOiJzdGFibGUiLCI3IjoiMSIsIjkiOiJkZXNrdG9wIn0=
sec-fetch-site: none
sec-fetch-mode: no-cors
sec-fetch-dest: empty
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.60
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

#request.method
GET

#request.response
200 

#request.date
2023-10-11 20:39:49.448413
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

通过js控制来获取

通过js语法对networks进行获取,以下是代码示例

from selenium import webdriver

# 打开浏览器并访问目标网页
driver = webdriver.Edge()
driver.get('https://www.bilibili.com/')
# 执行js代码,获取网页的network信息
networks = driver.execute_script('return window.performance.getEntries();')
# 输出获取到的信息
for network in networks:
    print(network)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果类似如下,可根据需要自行提取数据

{'activationStart': 0, 'connectEnd': 23.80000001192093, 'connectStart': 3, 'criticalCHRestart': 0, 'decodedBodySize': 106758, 'deliveryType': '', 'domComplete': 2404.5999999940395, 'domContentLoadedEventEnd': 1988.300000011921, 'domContentLoadedEventStart': 1986.7000000178814, 'domInteractive': 1301, 'domainLookupEnd': 1.9000000059604645, 'domainLookupStart': 1.9000000059604645, 'duration': 2418.5999999940395, 'encodedBodySize': 26255, 'entryType': 'navigation', 'fetchStart': 1.9000000059604645, 'firstInterimResponseStart': 0, 'initiatorType': 'navigation', 'loadEventEnd': 2418.5999999940395, 'loadEventStart': 2404.800000011921, 'name': 'https://www.bilibili.com/', 'nextHopProtocol': 'h2', 'redirectCount': 0, 'redirectEnd': 0, 'redirectStart': 0, 'renderBlockingStatus': 'non-blocking', 'requestStart': 23.900000005960464, 'responseEnd': 1086.9000000059605, 'responseStart': 1077.7000000178814, 'responseStatus': 200, 'secureConnectionStart': 3.5999999940395355, 'serverTiming': [], 'startTime': 0, 'toJSON': {}, 'transferSize': 26555, 'type': 'navigate', 'unloadEventEnd': 0, 'unloadEventStart': 0, 'workerStart': 0}

{'duration': 0, 'entryType': 'visibility-state', 'name': 'visible', 'startTime': 0, 'toJSON': {}}

{'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'deliveryType': '', 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 97.40000000596046, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 1081.300000011921, 'firstInterimResponseStart': 0, 'initiatorType': 'script', 'name': 'https://s1.hdslb.com/bfs/static/laputa-home/client/assets/svgfont.af80f0d3.js', 'nextHopProtocol': '', 'redirectEnd': 0, 'redirectStart': 0, 'renderBlockingStatus': 'non-blocking', 'requestStart': 0, 'responseEnd': 1178.7000000178814, 'responseStart': 0, 'responseStatus': 0, 'secureConnectionStart': 0, 'serverTiming': [], 'startTime': 1081.300000011921, 'toJSON': {}, 'transferSize': 0, 'workerStart': 0}
  • 1
  • 2
  • 3
  • 4
  • 5

外部实现

外部实现需要用到browsermob-proxy和库,以及java环境才能使用,相对较为麻烦,首先我们先下载相应的库win+r输入cmd并输入以下代码回车下载

pip install browsermob-proxy
  • 1

然后我们下载browsermob-proxy的官方文件,以下是我上传的地址和官方地址

CSDN站内地址
官网地址

现在我们来配置java环境,要想使用browsermob-proxy我们必须需要1.8以上的jdk环境才行,大家可以上网查一下jdk的配置,这里不在过多赘述,下面来展示通过browsermob-proxy实现的获取networks的代码

from selenium.webdriver.edge.options import Options
from selenium.webdriver.common.by import By
from browsermobproxy import Server
from selenium import webdriver
import time

#开启服务
server = Server(r'.\browsermob-proxy\bin\browsermob-proxy.bat')
server.start()
proxy = server.create_proxy()
#设置options
options=Options()
options.add_experimental_option('detach', True)
options.add_argument('--proxy-server={0}'.format(proxy.proxy))
#edge,将option传入edge中
driver=webdriver.Edge(options=options)
#开始捕获网络流量
proxy.new_har("example")
#打开网站
driver.get('https://www.bilibili.com/')
#由于我在打开中出现了连接不安全,所以这种方式来解决
driver.switch_to.window(driver.window_handles[-1])
driver.find_element(By.XPATH,'./html').send_keys('thisisunsafe')
time.sleep(2)
#停止捕获网络流量
result = proxy.har
for entry in result['log']['entries']:
        print(entry)
#关闭浏览器和代理服务器
driver.quit()
server.stop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

输出结果

{'pageref': 'example', 'startedDateTime': '2023-10-11T21:19:40.492+08:00', 'request': {'method': 'CONNECT', 'url': 'https://www.bilibili.com', 'httpVersion': 'HTTP/1.1', 'cookies': [], 'headers': [], 'queryString': [], 'headersSize': 0, 'bodySize': 0, 'comment': ''}, 'response': {'status': 0, 'statusText': '', 'httpVersion': 'unknown', 'cookies': [], 'headers': [], 'content': {'size': 0, 'mimeType': '', 'comment': ''}, 'redirectURL': '', 'headersSize': -1, 'bodySize': -1, 'comment': '', '_error': 'Unable to connect to host'}, 'cache': {}, 'timings': {'comment': '', 'ssl': -1, 'receive': 0, 'blocked': 0, 'connect': 161, 'send': 0, 'dns': 0, 'wait': 0}, 'serverIPAddress': '183.131.147.27', 'comment': '', 'time': 161}
......
  • 1
  • 2

参考文献以及温馨提示

selenium用法详解【从入门到实战】【Python爬虫】【4万字】_selenium学习-CSDN博客

【selenium自动化过程中的api抓包】browsermobproxy的安装和配置_browsermob-proxy-CSDN博客

Python+Selenium+Browsermob-Proxy 爬虫-获取浏览器Network请求和响应_selenium获取network-CSDN博客

Selenium获取浏览器Network数据包_selenium获取network_0xActive的博客-CSDN博客
温馨提示:

  • 有的代码可能由于网站问题定位会发生变化,可能需要大家自行调节
  • 本文章最后更新于2023年10月14日
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/108162
推荐阅读
相关标签
  

闽ICP备14008679号