前言

  • 平时做爬虫我比较喜欢用selenium chrome ,一直困扰我一个问题,就是只要谷歌浏览器更新了,就要重新去下载对应版本的chromedriver_win32,这让我十分烦恼

  • 比如我的谷歌浏览器已经94版本了,但是 chromedriver_win32还停留在92版本,就会报出下面的错误

  • selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 92
    Current browser version is 94.0.4606.71 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

  • 下面就解决这个痛点,实现自动下载和本地谷歌浏览器匹配的chromedriver_win32

文章目录

  • 前言
  • selenium基本代码,抛出问题
  • 实现自动下载匹配的chromedriver ,解决问题
    • 问题1,怎么获取本地谷歌浏览器的版本?
    • 问题2,怎么知道本地的 `chromedriver_win32`版本不匹配?
    • 问题3,怎么下载最新的`chromedriver.exe`?
    • 问题4,下载的怎么解压并换掉旧版`?
    • 完善selenium主代码
  • 总结


selenium基本代码,抛出问题

① 我们新建一个selenium_test.py,下面代码是打开百度页面的基本selenium代码,


from selenium import webdriver
import timeclass MySelenium(object):def __init__(self):self.basic_url = "https://www.baidu.com/"self.executable_path = r"./chromedriver_win32/chromedriver.exe"@propertydef start_driver(self):self.browser = webdriver.Chrome(executable_path=self.executable_path)self.browser.maximize_window()def request_url(self, url):""":param url:"""self.browser.get(url)
if __name__ == '__main__':start_time = time.time()ms = MySelenium()ms.start_driverms.request_url(ms.basic_url)#ms.close()test_time = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))print(test_time)

② 因为这个代码是我在很早之前写的,当时本地的谷歌浏览器版本还是92,现在已经升级到94了,于是就报了下面的错误,就是版本不匹配

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 92
Current browser version is 94.0.4606.71 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

实现自动下载匹配的chromedriver ,解决问题

问题1,怎么获取本地谷歌浏览器的版本?

①,一般获取本地应用的版本信息,用的都是win32com库的接口,新建文件 download_driver.py具体代码如下

  • 请先知道谷歌浏览器在本地的安装位置,代码中列出来一般情况,特殊安装位置要加进列表local_chrome_paths
from win32com.client import Dispatch
class auto_download_chromedrive(object):def __init__(self):self.local_chrome_paths = [r"C:\Program Files\Google\Chrome\Application\chrome.exe",r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"]def get_version_via_com(self, filename):parser = Dispatch("Scripting.FileSystemObject")try:version = parser.GetFileVersion(filename)except Exception:return Nonereturn versiondef start(self):version = list(filter(None, [self.get_version_via_com(p) for p in self.local_chrome_paths]))[0]if not version:print("check chrome browser version failed!")return Noneprint("chrome browser version:", version)if __name__ == "__main__":chrome = auto_download_chromedrive()chrome.start()

②,输出结果可以得到本地浏览器的版本是94版本的。


问题2,怎么知道本地的 chromedriver_win32版本不匹配?

①,我们再看下chrome不匹配的报错,具体的报错位SessionNotCreatedException我们修改下selenium的脚本,加上
try except捕捉这个错误

  • 更改下 selenium_test.py文件的脚本, 导入SessionNotCreatedExceptiontry,捕捉到这个报错 return 0
from selenium import webdriver
from selenium.common.exceptions import SessionNotCreatedException    #导入SessionNotCreatedException
import timeclass MySelenium(object):def __init__(self):self.basic_url = "https://www.baidu.com/"self.executable_path = r"./chromedriver_win32/chromedriver.exe"@propertydef start_driver(self):try:self.browser = webdriver.Chrome(executable_path=self.executable_path)self.browser.maximize_window()except SessionNotCreatedException:print("Chrome version unmatch. ")return 0return 1

问题3,怎么下载最新的chromedriver.exe

①,首先肯定不能用selenium了,这里我选择了requestslxml 库完成下载任务

如下图 chromedriver.exe 下载地址 和页面结构

②,更新download_driver.py,添加一个函数 get_chromedriver_urls,用来解析页面

from win32com.client import Dispatch
import requests
from lxml import etree
class auto_download_chromedrive(object):def __init__(self):self.chromedrive_url = "https://chromedriver.chromium.org/downloads"self.local_chrome_paths = [r"C:\Program Files\Google\Chrome\Application\chrome.exe",r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"]self.headers = {'content-type': 'application/json','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}def get_version_via_com(self, filename):parser = Dispatch("Scripting.FileSystemObject")try:version = parser.GetFileVersion(filename)except Exception:return Nonereturn versiondef get_chromedriver_urls(self):try:r = requests.Session()response = r.get(self.chromedrive_url, headers=self.headers)print(response.status_code, response.encoding)html = etree.HTML(response.text, etree.HTMLParser())  # 解析HTML文本内容version_href = html.xpath(".//strong//..//@href")return version_hrefexcept Exception:return Nonedef start(self):'''读取本地chrome version'''version = list(filter(None, [self.get_version_via_com(p) for p in self.local_chrome_paths]))[0]if not version:print("check chrome browser version failed!")return Noneprint("chrome browser version:", version)'''下载网页端与本地匹配的chromedriver.exe'''version_href = self.get_chromedriver_urls()if not version_href:print("request %s failed!"%self.chromedrive_url)return Noneprint("all chrome browser versions can be choosed:\n{}".format(version_href))if __name__ == "__main__":chrome = auto_download_chromedrive()chrome.start()

③,输出结果如下图,得到所有的chromedriver的下载地址

休息下1分钟。。。

④,更新download_driver.py,目的是在所有的版本中找到本地浏览器匹配的版本,并下载下来

  • 新加函数 find_local_version,在所有的版本中找到本地浏览器匹配的版本
  • 然后删减和拼接下url,组成新的url,直指 chromedriver_win32.zip
  • 新加函数 download_chromadrive,根据上面的url,下载指定版本
from win32com.client import Dispatch
import re
import requests
from lxml import etree
class auto_download_chromedrive(object):def __init__(self):self.chromedrive_url = "https://chromedriver.chromium.org/downloads"self.local_chrome_paths = [r"C:\Program Files\Google\Chrome\Application\chrome.exe",r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"]self.headers = {'content-type': 'application/json','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}def get_version_via_com(self, filename):parser = Dispatch("Scripting.FileSystemObject")try:version = parser.GetFileVersion(filename)except Exception:return Nonereturn versiondef get_chromedriver_urls(self):try:r = requests.Session()response = r.get(self.chromedrive_url, headers=self.headers)print(response.status_code, response.encoding)html = etree.HTML(response.text, etree.HTMLParser())  # 解析HTML文本内容version_href = html.xpath(".//strong//..//@href")print("all chrome browser versions can be choosed:")for href in version_href:print(href)return version_hrefexcept Exception:return Nonedef download_chromadrive(self, url):try:r = requests.Session()response = r.get(url, headers=self.headers)if response.status_code == 200:with open("chromedriver_win32.zip", "wb") as f:f.write(response.content)print("下载完成")return 1else:print('Url请求返回错误,错误码为: %d' % response.status_code)return Noneexcept Exception:print("request download chromedriver_win32.zip failed!")return Nonedef find_local_version(self, loc_ver, all_ver):""":param loc_ver: 本地浏览器的版本:param all_ver: 下载的所有版本浏览器版本:return: 找到匹配的,return url,否则return None"""for href in all_ver:try:res = re.search(r"path=(.*?)/", href)find_ver = res.group(1).split(".")[0] #截取大版本if loc_ver == find_ver:return hrefexcept Exception:continueprint("not find match chrome browser{} version!".format(loc_ver))return Nonedef start(self):'''读取本地chrome version'''version = list(filter(None, [self.get_version_via_com(p) for p in self.local_chrome_paths]))[0]if not version:print("check chrome browser version failed!")return Noneprint("chrome browser version:", version)'''下载网页端与本地匹配的chromedriver.exe'''version_href = self.get_chromedriver_urls()if not version_href:print("request %s failed!"%self.chromedrive_url)return None'''找到'''find_url = self.find_local_version(version.split(".")[0], version_href)print("找到匹配的版本:\n%s"%find_url)if not find_url:return Noneversion_num = re.search(r"path=(.*?)/", find_url).group(1)find_url_2 = find_url.rsplit('/', 2)[0]new_url = "{}/{}/chromedriver_win32.zip".format(find_url_2, version_num)print("downloading......\n%s"%new_url)ret = self.download_chromadrive(new_url)if not ret:return Noneif __name__ == "__main__":chrome = auto_download_chromedrive()chrome.start()

⑤,输出结果如下图

问题4,下载的怎么解压并换掉旧版`?

①,直接删除是肯定不行的,因为,当你使用过selenium之后,必须要在进程找那个杀掉chromedriver.exe才可以替换掉旧版本的。

  • 定义一个新函数 kill_process,如果进程中存在chromedriver.exe就杀掉
    def kill_process(self, process_name):print("检测{}进程是否存在,存在则杀掉。".format(process_name))pl = psutil.pids()for pid in pl:if psutil.Process(pid).name() == process_name:print('{} 存在进程中,杀掉'.format(process_name))os.popen('taskkill /f /im %s' %process_name)return pidprint('{} 不存在进程中。'.format(process_name))return None
  • 下面一段代码是清除chromedriver_win32文件夹内文件的只读属性(因为我的代码从托管平台同步后就只读了)
        old_driver_path = os.path.join(os.getcwd(), "chromedriver_win32")if os.path.exists(old_driver_path):for sub_file in os.listdir(old_driver_path):os.chmod(os.path.join(old_driver_path, sub_file), stat.S_IRWXU)time.sleep(1) #这个delay必须要有,os操作还是需要时间的
  • 下面一段代码解压新版本的chromedriver,替换掉旧版本
        print('''解压 chromedriver_win32.zip,覆盖旧版本''')zFile = zipfile.ZipFile(os.path.join(os.getcwd(), "chromedriver_win32.zip"), "r")for fileM in zFile.namelist():zFile.extract(fileM, old_driver_path)zFile.close()
  • download_driver.py 完整代码如下:
from win32com.client import Dispatch
import re
import stat,zipfile,os,psutil
import requests
from lxml import etree
import timeclass auto_download_chromedrive(object):def __init__(self):self.chromedrive_url = "https://chromedriver.chromium.org/downloads"self.local_chrome_paths = [r"C:\Program Files\Google\Chrome\Application\chrome.exe",r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"]self.headers = {'content-type': 'application/json','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}def get_version_via_com(self, filename):parser = Dispatch("Scripting.FileSystemObject")try:version = parser.GetFileVersion(filename)except Exception:return Nonereturn versiondef get_chromedriver_urls(self):try:r = requests.Session()response = r.get(self.chromedrive_url, headers=self.headers)print(response.status_code, response.encoding)html = etree.HTML(response.text, etree.HTMLParser())  # 解析HTML文本内容version_href = html.xpath(".//strong//..//@href")print("all chrome browser versions can be choosed:")for href in version_href:print(href)return version_hrefexcept Exception:return Nonedef download_chromadrive(self, url):try:r = requests.Session()response = r.get(url, headers=self.headers)if response.status_code == 200:with open("chromedriver_win32.zip", "wb") as f:f.write(response.content)print("下载完成")return 1else:print('Url请求返回错误,错误码为: %d' % response.status_code)return Noneexcept Exception:print("request download chromedriver_win32.zip failed!")return Nonedef find_local_version(self, loc_ver, all_ver):""":param loc_ver: 本地浏览器的版本:param all_ver: 下载的所有版本浏览器版本:return: 找到匹配的,return url,否则return None"""for href in all_ver:try:res = re.search(r"path=(.*?)/", href)find_ver = res.group(1).split(".")[0] #截取大版本if loc_ver == find_ver:return hrefexcept Exception:continueprint("not find match chrome browser{} version!".format(loc_ver))return Nonedef kill_process(self, process_name):print("检测{}进程是否存在,存在则杀掉。".format(process_name))pl = psutil.pids()for pid in pl:if psutil.Process(pid).name() == process_name:print('{} 存在进程中,杀掉'.format(process_name))os.popen('taskkill /f /im %s' %process_name)return pidprint('{} 不存在进程中。'.format(process_name))return Nonedef unzip(self):self.kill_process("chromedriver.exe")print("去除旧版本chromedriver_win32文件夹内文件的只读属性(如果是只读)")old_driver_path = os.path.join(os.getcwd(), "chromedriver_win32")if os.path.exists(old_driver_path):for sub_file in os.listdir(old_driver_path):os.chmod(os.path.join(old_driver_path, sub_file), stat.S_IRWXU)time.sleep(1) #这个delay必须要有,os操作还是需要时间的print('''解压 chromedriver_win32.zip,覆盖旧版本''')zFile = zipfile.ZipFile(os.path.join(os.getcwd(), "chromedriver_win32.zip"), "r")for fileM in zFile.namelist():zFile.extract(fileM, old_driver_path)zFile.close()def start(self):'''读取本地chrome version'''version = list(filter(None, [self.get_version_via_com(p) for p in self.local_chrome_paths]))[0]if not version:print("check chrome browser version failed!")return Noneprint("chrome browser version:", version)'''下载网页端与本地匹配的chromedriver.exe'''version_href = self.get_chromedriver_urls()if not version_href:print("request %s failed!"%self.chromedrive_url)return Nonefind_url = self.find_local_version(version.split(".")[0], version_href)print("找到匹配的版本:\n%s"%find_url)if not find_url:return Noneversion_num = re.search(r"path=(.*?)/", find_url).group(1)find_url_2 = find_url.rsplit('/', 2)[0]new_url = "{}/{}/chromedriver_win32.zip".format(find_url_2, version_num)print("downloading......\n%s"%new_url)ret = self.download_chromadrive(new_url)if not ret:return Noneself.unzip()
if __name__ == "__main__":chrome = auto_download_chromedrive()chrome.start()

真舒服。。。

完善selenium主代码

我们只需要在selenium_test.py中引用download_driver.py中的auto_download_chromedrive类即可
源码我放在git上,如需自取


from selenium import webdriver
from selenium.common.exceptions import SessionNotCreatedException    #导入NoSuchElementException
import time
from download_driver import auto_download_chromedriveclass MySelenium(object):def __init__(self):self.basic_url = "https://www.baidu.com/"self.executable_path = r"./chromedriver_win32/chromedriver.exe"@propertydef start_driver(self):try:self.browser = webdriver.Chrome(executable_path=self.executable_path)self.browser.maximize_window()except SessionNotCreatedException:print("Chrome version unmatch. ")return Nonereturn 1def request_url(self, url):self.browser.get(url)if __name__ == '__main__':start_time = time.time()ms = MySelenium()if not ms.start_driver:chrome = auto_download_chromedrive()chrome.start()ms.start_driverms.request_url(ms.basic_url)#ms.close()test_time = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))print(test_time)

源码我放在git上,如需自取

总结

  • 本博客谢绝转载

  • 要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
  • 如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。当然执意选择白嫖也常来哈。

关于selenium, 你还在因为chromedriver的版本与Chrome的版本不一致,需要手动更新chromedriver而烦恼吗?相关推荐

  1. 使用Selenium时,如何选择ChromeDriver驱动版本对应Chrome浏览器版本

    参考 http://chromedriver.storage.googleapis.com/index.html

  2. 根据本地浏览器的版本自动更新chromedriver

    webdriver-manager 是一个 Python 库,它可以自动下载和管理 Webdriver 驱动程序,包括 ChromeDriver.GeckoDriver.EdgeDriver.IEDr ...

  3. 已解决selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary

    已解决selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary ...

  4. mac本更新chromedriver版本

    1.chromedriver的版本要和chrome的版本保持一致,如果chrome的版本升级了 chromedriver也要升级,否则执行web自动化会登录失败 2.因chromedriver的官网打 ...

  5. Selenium 与(Firefox、GeckoDriver)和(Chrome、ChromeDriver)版本对应关系

    找了一圈,竟然一个靠谱的版本对应表都找不到,这里整理一下 下载地址 Selenium ChromeDriver Chrome GeckoDriver Firefox Selenium Firefox ...

  6. chromedriver与chrome各版本及下载地址,截止到2018.5.30

    下载地址 https://chromedriver.storage.googleapis.com/index.html 官网2.3.9版本打开后点击notes.txt文件打开后看到 对应版本 ---- ...

  7. Chrome的版本和Selenium支持的版本不一致

    chrome的版本和Selenium支持的版本不一致,报错如下: selenium.common.exceptions.SessionNotCreatedException: Message: ses ...

  8. 找不到和chrome浏览器版本不同的chromedriver的解决方法

    某一天我很久没有chromedriver之后,发现我的google版本是下图这样 打开这个网站下载新版本的chromedriver,我发现没有103.0.5060.114.虽然我不知道为什么没有但是问 ...

  9. linux下载google chrome,chromedriver,使用webdriver.Chrome()

    1.安装google chrome 首先,查看自己Linux是什么系统,系统不同,好像安装也不一样,我的是centos7 cat /etc/redhat-release #查看系统版本 我的安装过程是 ...

最新文章

  1. c语言四则运算实验报告,c语言四则运算实验报告.doc
  2. python 内推_网易有道2017内推编程题 洗牌(python)
  3. how tomcat works 1 simple web server
  4. SAP ERP项目各模块设计重点
  5. 快速上手Ubuntu搭建Python编程环境
  6. java 日期 区间_如何实现时间区间的分割??
  7. 阿里十年DBA经验产品经理:真的不要再有一起删库跑路事件了
  8. spring+hibernate+Struts2 整合(全注解及注意事项)
  9. excel导入导出工具类_Hutool Java工具类库导出Excel,超级简单
  10. 以太坊代码标准是什么_以太坊:什么是ERC20标准?
  11. 一步一步写算法(之字符串查找 上篇)
  12. 查找出现次数 oracle,ORACLE计算某个列中出现次数最多的值
  13. CocoaPods 安装
  14. log4j的使用 slf4j简单介绍
  15. Java实现校园论坛系统
  16. Twaver-HTML5基础学习(13)连线(Link)连线的绑定与展开
  17. Vue开发需要的网站
  18. 【H3C模拟器】配置交换机的链路聚合
  19. 供应链库存管理-库存控制策略
  20. 《都挺好》苏大强,锦鲤杨超越,表情包为何会刷屏?

热门文章

  1. 常用快捷键,不积硅步无以至千里
  2. ntp时间同步,各种配置方法
  3. My97 DatePicker图标触发
  4. 摆弄教研室的服务器,为教研室写服务器使用指南的时候记录下的一些linux知识
  5. 教育界「拼多多」卖课套路解析
  6. Mermaid流程图
  7. 重量(计量单位)英文缩写和转换表
  8. STM32控制编码器电机实现【速度闭环控制】与【位置闭环控制】
  9. javascript学习笔记下篇--浏览器对象
  10. 转贴: 浅析多声道LPCM TRUE HD DTS HD之异同