代码实现对selenium的驱动器WebDrive的配置

2023-11-17

1.条件

1.使用的浏览器是Microsoft Edge。

2.简述过程(代码实现)

1.pip 安装

2.下载

3.解压

4.运行

3.发现一个报错

1)原因

在给出代码之前,我发现一个报错,很离谱。且听笔者慢慢细说。首先,安装了selenium4.11.2,也配置edge webdriver。在其中一个项目中,解释器是python3.10,运行如下代码

from selenium import webdriver
browser = webdriver.Edge()
browser.get('https://www.baidu.com')

发现报错了,报错的原因,在最后有这样一段话

selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for MicrosoftEdge using Selenium Manager.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

如果去网上搜原因,如下结果

selenium打开浏览器报错成功解决selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain..._sinnp的博客-CSDN博客

可惜,可以这位大佬的解决不适应于笔者的报错。虽然报错是一样的,但是终究还是不一样,具体情况具体分析。

2)推理

因此笔者把报错全部写出来

Traceback (most recent call last):
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\selenium_manager.py", line 124, in run
    stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
AttributeError: 'str' object has no attribute 'decode'. Did you mean: 'encode'?

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\driver_finder.py", line 38, in get_path
    path = SeleniumManager().driver_location(options) if path is None else path
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\selenium_manager.py", line 90, in driver_location
    output = self.run(args)
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\selenium_manager.py", line 129, in run
    raise WebDriverException(f"Unsuccessful command executed: {command}") from err
selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\windows\selenium-manager.exe --browser MicrosoftEdge --output json


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\520\PycharmProjects\pythonProject4\selenium的故事\6.py", line 2, in <module>
    browser = webdriver.Edge()
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\edge\webdriver.py", line 45, in __init__
    super().__init__(
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\chromium\webdriver.py", line 51, in __init__
    self.service.path = DriverFinder.get_path(self.service, options)
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\driver_finder.py", line 41, in get_path
    raise NoSuchDriverException(msg) from err
selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for MicrosoftEdge using Selenium Manager.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

从browser = webdriver.Edge()开始。

往下走,走到这里 self.service.path = DriverFinder.get_path(self.service, options),进去看看源代码。再进get_path方法,其中代码如下

    @staticmethod
    def get_path(service: Service, options: BaseOptions) -> str:
        path = service.path
        try:
            path = SeleniumManager().driver_location(options) if path is None else path

        except Exception as err:
            msg = f"Unable to obtain driver for {options.capabilities['browserName']} using Selenium Manager."
            raise NoSuchDriverException(msg) from err

        if path is None or not Path(path).is_file():
            raise NoSuchDriverException(f"Unable to locate or obtain driver for {options.capabilities['browserName']}")

        return path

可以尝试打印path,第一个path为空,第二个path没有打印出来就报错了。再看报错中的内容,其中有这段话

Traceback (most recent call last):
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\driver_finder.py", line 38, in get_path
    path = SeleniumManager().driver_location(options) if path is None else path

也指出这行代码有问题,所以进入这行代码中的driver_location方法,看看其中的内容,再看下一个报错

  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\selenium_manager.py", line 89, in driver_location
    output = self.run(args)

可以在driver_location方法发现有这行代码,所以猜测这行代码有问题,也可以打印一些变量,比如,args,最后可以确定这个猜测。

因此,进入self.run方法。其中主要代码如下

    @staticmethod
    def run(args: List[str]) -> dict:
        """
        Executes the Selenium Manager Binary.
        :Args:
         - args: the components of the command being executed.
        :Returns: The log string containing the driver location.
        """
        if logger.getEffectiveLevel() == logging.DEBUG:
            args.append("--debug")
        args.append("--output")
        args.append("json")

        command = " ".join(args)
        logger.debug(f"Executing process: {command}")
        try:
            if sys.platform == "win32":
                completed_proc = subprocess.run(
                    args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW
                )
            else:
                completed_proc = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
            stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
            output = json.loads(stdout)
            result = output["result"]

再看报错

Traceback (most recent call last):
  File "C:\Users\520\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\pythonProject4\lib\site-packages\selenium\webdriver\common\selenium_manager.py", line 123, in run
    stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
AttributeError: 'str' object has no attribute 'decode'. Did you mean: 'encode'?

很明显是self.run中的stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")有问题,报错的原因是str没有这个decode属性,确实是没有。

打印一下completed_proc,返回的结果如下

CompletedProcess(args=['C:\\Users\\520\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\pythonProject4\\lib\\site-packages\\selenium\\webdriver\\common\\windows\\selenium-manager.exe', '--browser', 'MicrosoftEdge', '--output', 'json'], returncode=0, stdout='{\n  "logs": [\n    {\n      "level": "INFO",\n      "timestamp": 1692601797,\n      "message": "Driver path: C:\\\\Users\\\\520\\\\AppData\\\\Local\\\\Programs\\\\Python\\\\Python310\\\\msedgedriver.exe"\n    },\n    {\n      "level": "INFO",\n      "timestamp": 1692601797,\n      "message": "Browser path: C:\\\\Program Files (x86)\\\\Microsoft\\\\Edge\\\\Application\\\\msedge.exe"\n    }\n  ],\n  "result": {\n    "code": 0,\n    "message": "C:\\\\Users\\\\520\\\\AppData\\\\Local\\\\Programs\\\\Python\\\\Python310\\\\msedgedriver.exe",\n    "driver_path": "C:\\\\Users\\\\520\\\\AppData\\\\Local\\\\Programs\\\\Python\\\\Python310\\\\msedgedriver.exe",\n    "browser_path": "C:\\\\Program Files (x86)\\\\Microsoft\\\\Edge\\\\Application\\\\msedge.exe"\n  }\n}', stderr=b'')

返回是个CompletedProcess对象,没错,再次打印completed_proc.stdout,代码如下

{
  "logs": [
    {
      "level": "INFO",
      "timestamp": 1692601871,
      "message": "Driver path: C:\\Users\\520\\AppData\\Local\\Programs\\Python\\Python310\\msedgedriver.exe"
    },
    {
      "level": "INFO",
      "timestamp": 1692601871,
      "message": "Browser path: C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
    }
  ],
  "result": {
    "code": 0,
    "message": "C:\\Users\\520\\AppData\\Local\\Programs\\Python\\Python310\\msedgedriver.exe",
    "driver_path": "C:\\Users\\520\\AppData\\Local\\Programs\\Python\\Python310\\msedgedriver.exe",
    "browser_path": "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
  }
}

这个结果是字符串,很明显,str是没有decode属性。以此这个才是报错的根本原因。

3)思考

为什么print(completed_proc.stdout),打印的对象的类型是str,很明显根据代码的理解,应该打印是个bytes类型,才会有decode。可以去官网看看解释,如下图。

 返回的是字节序列或者字符串,这个或有意思

因为笔者的电脑上有·python310和python311,但笔者使用python311作为编辑器创建的项目,运行代码没有报错,而且打印的completed_proc.stdout是字节序列,因此没有报错。

为什么同样的代码,在不用python环境中运行结果不一样,至于原因我也不知道。

4)修改

既然completed_proc.stdout是字符串,那么直接注释掉decode,代码如下

            stdout=completed_proc.stdout
            # stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
            # stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
            output = json.loads(stdout)

运行没有报错。

4.正文

上面的报错只是个插曲。现在要实现真正的配置了,首先我看到这位大佬的代码

https://blog.csdn.net/weixin_49958813/article/details/125580029

写得好,于是我就有个想法,这位大佬的代码中只有更新。感觉不完善。

因此,代码如下:

import time
from xml.dom import minidom as xml
from xml.dom.minicompat import NodeList
from xml.dom.minidom import Element
from tqdm import tqdm
import requests
import re
import getpass
from zipfile import ZipFile
from logging import StreamHandler,getLogger,DEBUG
from colorlog import ColoredFormatter
import sys
from pathlib import Path
import subprocess
class WebDriver:
    def __init__(self,output_path,zip_file=None):
        self.has_zip=False
        self.dom = xml.parse(r'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.VisualElementsManifest.xml')
        self.logger=self.log()
        self.output_path=output_path
        self.zip_file='C:/Users/'+self.user+'/Downloads/edgedriver.zip'
    def log(self):
        """
        日志的配置
        :return:
        """
        colors = {
            'DEBUG': 'bold_red',
            'INFO': 'bold_blue',
            'WARNING': 'bold_yellow',
        }
        logger = getLogger(__file__)
        stream_handler = StreamHandler()
        logger.setLevel(DEBUG)
        color_formatter = ColoredFormatter(
            fmt='%(log_color)s %(asctime)s %(filename)s  %(funcName)s line:%(lineno)d %(levelname)s : %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S',
            log_colors=colors
        )
        stream_handler.setFormatter(color_formatter)
        logger.addHandler(stream_handler)
        return logger
    def decompression(self,delete_zip=True):
        """
        解压
        :return:
        """
        if self.has_zip:
            zip=ZipFile(self.zip_file)
            zip.extractall(self.output_path)
            zip.close()
            self.logger.info(f'解压成功,webdriver的路径为{self.output_path}')
            if delete_zip:
                Path(self.zip_file).unlink()
                self.logger.debug('删除webdriver.zip文件')
        else:
            self.logger.warning('没有发现webdriver.zip文件')
    def download(self):
        """
        下载webriver
        :return:
        """
        if Path(self.zip_file).exists():
            self.has_zip=True
            self.logger.info('找到webdriver.zip文件,即将积压')
            return
        self.logger.info('没有发现webdriver.zip,即将下载!')
        version=self.get_version
        url = 'https://msedgedriver.azureedge.net/' + version + '/edgedriver_win64.zip'
        self.logger.info('正在发送请求...')
        response=requests.get(url=url)
        self.logger.info('请求成功')
        total=response.headers['Content-Length']
        total = int(total)
        self.logger.info('文件大小为 '+str(total)+' B')
        with open(self.zip_file,'wb') as f:
            with tqdm(total=total,desc="webdriver下载") as p:
                    for i in response.iter_content(1024*100):
                        f.write(i)
                        time.sleep(0.2)
                        p.update(1024*100)
        self.logger.debug('webdriver.zip 下载完成!!')
        self.has_zip=True
    def __display(self):
        """
        安装、运行、更新
        :return:
        """
        try:
            from selenium import webdriver
            from selenium.common.exceptions import SessionNotCreatedException,NoSuchDriverException
            self.logger.info('selenium存在,即将打开edge')
            browser = webdriver.Edge()
            browser.get('https://www.baidu.com')
            browser.quit()
            self.logger.info('edge关闭,运行成功')
        except ModuleNotFoundError as e:
            self.logger.warning('selenium 不存在,即将安装...')
            cmd='pip install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium'
            result=subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            self.logger.debug('安装过程:\n'+result.stdout)
            self.logger.info('下载selenium成功,')
            self.logger.info('等待安装..')
            time.sleep(10)
            self.__display()
        except SessionNotCreatedException as e:
            self.logger.warning('需要更新webdriver!!!!')
            self.download()
            self.decompression()
            self.logger.info('更新成功')
            self.logger.info('再次运行seleniun')
            self.__display()
    def up_to_date(self):
        """
        更新webdriver版本
        :return:
        """
    @property
    def get_version(self):
        """
        得到edge的版本
        :return:
        """
        dom = self.dom.documentElement
        nodeList:NodeList = dom.getElementsByTagName('VisualElements')
        element:Element=nodeList[0]
        text=element.toxml()
        version='.'.join(re.findall('(\d+)\.(\d+)\.(\d+)\.(\d+)', text)[0])
        return version
    @property
    def user(self):
        """
        得到当前的使用者
        :return:
        """
        return getpass.getuser()
    def install(self):
        self.__display()
if __name__ == '__main__':
    webdriver=WebDriver(output_path=sys.path[6])
    webdriver.install()



这个代码,可以直接安装selenium和webdriver,并且可以更新。如果遇到上面的报错,如果报错的内容是一样的,那么可以按照其中的内容修改,如果有其他报错,可看个人具体分析。

对于其他浏览器,查不多。

5.结果

 笔者发现好像第一次运行,会自动下载msedgedriver.exe,selenium变高级了,以前都没有。笔者的路径如下

C:/Users/520/.cache/selenium/msedgedriver/win64/115.0.1901.203/msedgedriver.exe

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

代码实现对selenium的驱动器WebDrive的配置 的相关文章

随机推荐

  • DeBlurGANv2图像去模糊 训练自己的数据集

    之前在有位博主的DeblurGANv2教程的页面下留了言 很多小伙伴来私信我 config yaml怎么调参数 predict py和train py需要怎么修改 之前只跑了predict 有些问题也没办法解答 最近自己跑了一下train
  • MTU 和 MSS 区别

    MTU Maximum Transmit Unit 最大传输单元 即物理接口 数据链路层 提供给其上层 通常是IP层 最大一次传输数据的大小 以普遍使用的以太网接口为例 缺省MTU 1500 Byte 这是以太网接口对IP层的约束 如果IP
  • HPE Microserver GEN10升级BIOS

    到手的机子BIOS版本还是ZA10A290 非常有必要升级 便从HPE官网下载了最新的版本 ZA10A360 选择UEFI Shell方式更新 官网下载地址 https support hpe com hpesc public km pro
  • Cutter - Web视频剪辑工具原理浅析

    大厂技术 坚持周更 精选好文 最近一直在开发 web视频剪辑工具 cutter 这个工具可以方便老师们编辑拍摄好的视频 这是一个挺有意思的项目 预计分多章和大家分享介绍 本期主要介绍下其大体流程 方便大家对其原理有一个简单认知 Cutter
  • Docker安全设置

    Docker安全 Linux内核的命名空间机制提供的容器隔离安全 Linux控制组机制对容器资源的控制能力安全 Linux内核的能力机制所带来的操作权限安全 Docker程序 特别是服务端 本身的抗攻击性 其他安全增强机制对容器安全性的影响
  • elementui不生效

    1 element依赖vue 引入element js之前要引入vue js 2 element无法脱离Vue使用 html中必须new Vue el app 挂载上去
  • C语言函数大全--f开头的函数(下)

    f开头的函数 下 21 floor floorf floorl 21 1 函数说明 21 2 演示示例 21 3 运行结果 22 flushall 22 1 函数说明 22 2 演示示例 22 3 运行结果 23 fma fmaf fmal
  • php发送请求写请求头,PHP发送请求头和接收打印请求头

    一 发送请求头 发送地址 url http 127 0 0 1 2 php 请求头内容 headers array Authorization basic suibianzhi basic 使用curl发送 ch curl init url
  • 计算机缺失VCRUNTIME140.dll怎么办,那个修复方法可以解决

    计算机提示缺失VCRUNTIME140 dll怎么办 无法启动运行软件程序 如photoshop pr ae等等都是无法启动 打开电脑就报错 由于找不到VCRUNTIME140 dll 无法继续执行此代码 让我们先来了解一下VCRUNTIM
  • Gitee初练 --- 问题合集(一)

    Gitee 一 Windows找不到gpedit msc请确定文件名是否正确的提示 二 windows 10 凭据无法保存 三 解决 git pull push 每次都要输入用户名密码的问题 一 Windows找不到gpedit msc请确
  • C++ 读写二进制文件

    描述 C 来读取二进制文件 二进制文件的格式可以多种多样 比如dat index等 还可以是自行定义的格式 C 来写二进制文件 一 读二进制文件 结构体定义及头文件 include
  • 38 匹配字符串——findall()方法

    文章目录 语法 案例 语法 findall 方法用于在整个字符串中搜索所有符合正则表达式的字符串 并以列表的形式返回 如果匹配成功 则返回包含匹配结构的列表 否则返回空列表 findall 方法的语法格式如下 re findall patt
  • css实现图片叠加的几种思路(记录笔记)

    背景 实现点击事件 触发原图的img透明度降低 成为透明背景 并且加一个不透明的原图 可以用于加水印 一个div覆盖几个样式 使用的是vue vue cli搭建项目 几种思路 1 切换背景样式 设置一个key 当div元素触发点击事件 di
  • (SUB)选择排序时间、空间复杂度

    基本思想 将一组数据分为两部分 前面是已排序部分 后面是未排序部分 初始状态可认为位置 0 为已排序部分 数组下标从0开始 其余为未排序部分 每一次都从未排序部分选择一个最小元素放在已排序部分的末尾 然后已排序部分增加一个元素 未排序部分减
  • 腾讯云微计算实践:从Serverless说起,谈谈边缘计算的未来

    欢迎大家前往云 社区 获取更多腾讯海量技术实践干货哦 作者 黄文俊 腾讯云高级产品经理 曾经历过企业级存储 企业级容器平台等产品的架构与开发 对容器 微服务 无服务器 DevOps等都有浓厚兴趣 由 腾讯云serverless团队 发布在
  • selenium版本不匹配

    window10解决selenium版本不匹配问题 如运行出现以下错误 File C Python37 lib site packages selenium webdriver chrome webdriver py line 73 in
  • 【Google测试之道】 第二章 软件测试开发工程师

  • 方法简单手把手教你,空闲时间在家剪辑视频,一天收入300多

    做一个视频剪辑号 不开玩笑 认真做一个月真的能做到1w 有不少人都不知道 我们平时在手机上刷到的横屏视频都是可以赚钱的 而且也可以不用露脸拍摄视频 下班在家也可以赚取一份额外收入 很多人就会有疑问了 不露脸 不拍摄视频怎么赚钱 其实做视频剪
  • 【netty】netty HashedWheelTimer 延时队列

    1 概述 想要研究这个是因为 Flink Flink 写入 Clickhouse 大对象直接进入老年代 导致OOM 遇到了这个问题 在这个问题中 我将时间轮改小了 时间轮 512改成16个 Netty中提供的HashedWheelTimer
  • 代码实现对selenium的驱动器WebDrive的配置

    1 条件 1 使用的浏览器是Microsoft Edge 2 简述过程 代码实现 1 pip 安装 2 下载 3 解压 4 运行 3 发现一个报错 1 原因 在给出代码之前 我发现一个报错 很离谱 且听笔者慢慢细说 首先 安装了seleni