python selenium之chromedriver与chrome版本匹配问题(二)

  很多使用selenium的用户都会遇到一个问题,我们的chromedriver经常与本地的chrome浏览器版本不兼容,导致我们实例化webdriver.Chrome失败,错误信息大致如下:

发生异常: SessionNotCreatedException
 Message: session not created: This version of ChromeDriver only supports Chrome version 90 Current browser version is 95.0.4638.69 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

  小爬在之前的文中(python selenium自动化之chrome与chromedriver版本兼容问题,封装了方法来分别获取chrome版本和chromedriver版本,当两者版本的主版本号存在差异时,自动联网在淘宝源仓库:ChromeDriver Mirror (taobao.org)中下载对应的版本chromedriver,实现chromedriver基于需求的自动更新,使得两者能长期匹配。

  实际上经过一番摸索,小爬发现有第三方的专业python库webdriver_manager优雅地解决了这一问题,且其后台更新chromedriver使用的是谷歌官方的chromedriver仓库。该URL(http://chromedriver.storage.googleapis.com/index.html)在国内是可以正常访问的,相对于淘宝源仓库最大的优势是,它永远存有chrome最新版的chromedriver,仓库更新的频率更快,如下图所示:

 

  实上,webdriver-manager库(通过pip install webdriver-manager安装即可)也可以用来更新EdgeChromiumDriver、GeckoDriver、IEDriver、OperaDriver文件,具体如何操作呢,其实我们执行时就两三行代码:

driver_path=ChromeDriverManager().install() 
driver = webdriver.Chrome(executable_path=driver_path)
  当然,我们如果多具备些探究竟精神,不妨看下其源码,了解其精髓。其中ChromeDriverManager类的源码如下:
class ChromeDriverManager(DriverManager):
    def __init__(self, version="latest",
                 os_type=utils.os_type(),
                 path=None,
                 name="chromedriver",
                 url="https://chromedriver.storage.googleapis.com",
                 latest_release_url="https://chromedriver.storage.googleapis.com/LATEST_RELEASE",
                 chrome_type=ChromeType.GOOGLE,
                 log_level=logging.INFO,
                 print_first_line=True,
                 cache_valid_range=1):
        super().__init__(path, log_level=log_level, print_first_line=print_first_line,
                         cache_valid_range=cache_valid_range)

        self.driver = ChromeDriver(name=name,
                                   version=version,
                                   os_type=os_type,
                                   url=url,
                                   latest_release_url=latest_release_url,
                                   chrome_type=chrome_type)

    def install(self):
        log(f"Current {self.driver.chrome_type} version is {self.driver.browser_version}", first_line=True)
        driver_path = self._get_driver_path(self.driver)

        os.chmod(driver_path, 0o755)
        return driver_path

chromedriver类的源码如下:

class ChromeDriver(Driver):
    def __init__(self, name, version, os_type, url, latest_release_url,
                 chrome_type=ChromeType.GOOGLE):
        super(ChromeDriver, self).__init__(name, version, os_type, url,
                                           latest_release_url)
        self.chrome_type = chrome_type
        self.browser_version = get_browser_version_from_os(chrome_type)

    def get_os_type(self):
        if "win" in super().get_os_type():
            return "win32"
        return super().get_os_type()

    def get_latest_release_version(self):
        log(f"Get LATEST driver version for {self.browser_version}")
        resp = requests.get(f"{self._latest_release_url}_{self.browser_version}")
        validate_response(resp)
        return resp.text.rstrip()

该方法会默认调用DriverCache类的find_driver方法:

    def find_driver(self, browser_version, driver_name, os_type, driver_version):
        metadata = self.get_metadata()

        key = f"{os_type}_{driver_name}_{driver_version}_for_{browser_version}"
        if key not in metadata:
            log(f"There is no [{os_type}] {driver_name} for browser {browser_version} in cache")
            return None

        driver_info = metadata[key]

        if not self.__is_valid(driver_info):
            return None

        path = driver_info['binary_path']
        log(f"Driver [{path}] found in cache")
        return path

如果系统能在特定路径下找到对应版本的driver,则可以直接调用,否则调用get_latest_release_version方法来联网获取最新的driver,并放在对应的系统路径下,比如我电脑上chromedriver最新版统一存储在下图所示路径下,供参考:

 

   因电脑端chrome浏览器自动升级策略,导致本地的chromedriver总是不能及时兼容。有这类问题的你,还不赶紧动手试下?

欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!

 

 

posted @ 2021-11-07 14:57  NewJune  阅读(3356)  评论(0编辑  收藏  举报