Code to implement the configuration of Selenium's driver WebDrive

1.Conditions

1. The browser used is Microsoft Edge.

2. Briefly describe the process (code implementation)

1.pip installation

2.Download

3. Unzip

4. Run

3. Found an error

1) Reason

Before giving the code, I found an error, which was outrageous. Let the author explain slowly and in detail. First, selenium4.11.2 is installed and edge webdriver is also configured. In one of the projects, the interpreter is python3.10 and the following code is run

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

I found that an error was reported. The reason for the error was reported at the end.

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

If you search the Internet for the reason, you will find the following results:

selenium opens the browser and reports an error, successfully solving selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain..._sinnp's blog-CSDN blog

It's a pity that this boss's solution is not suitable for the author's error report. Although the error report is the same, it is still different after all. The specific situation must be analyzed in detail.

2) Reasoning

Therefore, the author writes out all the errors reported.

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

Start with browser = webdriver.Edge().

Go down and go here self.service.path = DriverFinder.get_path(self.service, options), go in and look at the source code. Then enter the get_path method, the code is as follows

    @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

You can try to print the path. The first path is empty, and the second path is not printed and an error is reported. Look at the contents of the error report again, including this paragraph

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

It also pointed out that there is a problem with this line of code, so enter the driver_location method in this line of code, look at the content, and then look at the next error report

  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)

This line of code can be found in the driver_location method, so I guess there is something wrong with this line of code. You can also print some variables, such as args, and finally confirm this guess.

So, enter the self.run method. The main codes are as follows

    @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"]

Look at the error report again

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'?

Obviously there is a problem with stdout = completed_proc.stdout.decode("utf-8").rstrip("\n") in self.run. The reason for the error is that str does not have this decode attribute. It does not.

Print completed_proc and the returned results are as follows

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'')

The return is a CompletedProcess object, yes, print completed_proc.stdout again, the code is as follows

{
  "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"
  }
}

This result is a string. Obviously, str has no decode attribute. This is the root cause of the error.

3) Thinking

Why print(completed_proc.stdout), the type of the printed object is str, obviously according to the understanding of the code, it should be printed as bytes type, then there will be decode. You can go to the official website to see the explanation, as shown below.

 What is returned is a byte sequence or string, which may be interesting

Because I have python310 and python311 on my computer, but I used python311 as the editor to create the project. No error was reported when running the code, and the printed completed_proc.stdout is a byte sequence, so no error was reported.

Why do the same codes have different results when running in an environment other than Python? I don't know the reason.

4) Modify

Since completed_proc.stdout is a string, comment out decode directly. The code is as follows

            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)

No errors were reported when running.

4.Text

The above error report is just an episode. Now to achieve the real configuration, first I saw the code of this boss

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

Well written, so I had an idea. There are only updates in this boss's code. It feels incomplete.

So the code is as follows:

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()



With this code, selenium and webdriver can be installed directly and updated. If you encounter the above error report, if the content of the error report is the same, you can modify it according to the content. If there are other errors, you can see your personal analysis.

For other browsers, not much can be found.

5.Results

 The author found that it seems that msedgedriver.exe will be automatically downloaded the first time it is run, and selenium has become advanced, which was not the case before. The author’s path is as follows

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

 

Guess you like

Origin blog.csdn.net/qq_63401240/article/details/132406123