搜索:ingStudio 霍格沃兹的货都很硬核本文为霍格沃兹学院学员 @felix 实用技能。
在学院学员流时,有同学说 Appium 支持自动兼容的浏览器驱动,想来 Selenium 也有类似的方法,于是在上搜索一番,并参考了 Medium 上的一篇文章所介绍的方法进行尝试,对相关步骤进行了改进,增加了对多浏览器的支持。本文就总结下整体过程与实现代码。
首先,想明白大致的几个步骤:
- 识别本地浏览器版本对应浏览器版本的驱动解压到对应文件夹记录到 pping.json 文件中
接下来就是撸起袖子开了。
定义好目录结构
|— config |— pping.json: 浏览器驱动配置信息 |— dver: 存放浏览器驱动 |— utils |— 封装的工具包 |—
数据准备
导入第三方库,定义好路径名称等常量。
import json import os import zipfile import shutil import requests import pathlib fm win32com import client as win_client # 工作目录(当前路径调试时需加上.parent) BASE_DIR = str # BASE_DIR = str(.parent) CHROME_DRIVER_BASE_L = "" EDGE_DRIVER_BASE_L = "" CHROME_DRIVER_ZIP = "" EDGE_DRIVER_ZIP = "" CHROME_DRIVER = "" EDGE_DRIVER = "" BROWSER_DRIVER_DIR = str((BASE_DIR, "dver")) DRIVER_MAPPING_FILE = (BASE_DIR, "config", "pping.json")
第一步:获取浏览器的版本
Chme 浏览器有些小版本没有对应版本的浏览器驱动,需要借助 Query API 查询对应大版本LATEST RELEASE版本,再根据查询对应的浏览器驱动。
新版 Edge 浏览器每个版本都有对应的驱动。
La Version API {version}Download Chme Dver API {version} {version}
代码如下:
def get_bwser_version(file_path): """ 获取浏览器版本 :param file_path: 浏览器文件路径 :retn: 浏览器大版本 """ # 判断路径文件是否存在 if not (file_path): raise FileNotFoundErr(f"{file_path} is not found.") win_obj = ('') version = (file_path) retn def get_bwser_jor_version(file_path): """ 获取浏览器大版本 :param file_path: 浏览器文件路径 :retn: 浏览器大版本 """ bwser_ver = get_bwser_version(file_path) bwser_jor_ver = (".")[0] retn bwser_jor_ver def get_la_bwser_version(bwser_jor_ver): """ 获取匹配大版本的release版本 :param bwser_jor_ver: 浏览器大版本 :retn: release版本 """ la_api = f"{CHROME_DRIVER_BASE_L}/LATEST_RELEASE_{bwser_jor_ver}" resp = (la_api) la_dver_version = retn la_dver_version
第二步:浏览器驱动
def download_bwser_dver(la_dver_version, bwser_name): """ 浏览器驱动压缩包 :param bwser_name: 浏览器名称 :param la_dver_version: 浏览器的版本 """ download_api = None if bwser_name == "Chme": download_api = f"{CHROME_DRIVER_BASE_L}/{la_dver_version}/{CHROME_DRIVER_ZIP}" elif bwser_name == "Edge": download_api = f"{EDGE_DRIVER_BASE_L}/{la_dver_version}/{EDGE_DRIVER_ZIP}" download_dir = (str(BROWSER_DRIVER_DIR), (download_api)) # ,设置超时时间20s resp = (download_api, stream=True, timeout=20) if with open(download_dir, 'wb') as fo: fo.wte else: raise Exception("Download chme dver failed")
第三步:解驱动压缩包
解压后将原压缩包删除。
def unzip_dver(bwser_jor_ver, bwser_name): """ 解压驱动压缩包 :param bwser_name: 浏览器名称 :param bwser_jor_ver: 浏览器大版本 :retn: 驱动文件路径 """ file_path = None dver_path = None if bwser_name == "Chme": file_path = (BROWSER_DRIVER_DIR, (CHROME_DRIVER_ZIP)) dver_path = (BROWSER_DRIVER_DIR, bwser_jor_ver, CHROME_DRIVER) elif bwser_name == "Edge": file_path = (BROWSER_DRIVER_DIR, (EDGE_DRIVER_ZIP)) dver_path = (BROWSER_DRIVER_DIR, bwser_jor_ver, EDGE_DRIVER) bwser_dver_dir = (BROWSER_DRIVER_DIR, bwser_jor_ver) # 解压到指定目录 with (file_path, 'r') as zip_ref: (bwser_dver_dir) retn dver_path def remove_dver_zip(bwser_name): """ 删除的驱动压缩包 :param bwser_name: 浏览器名称 """ file_path = None if bwser_name == "Chme": file_path = (BROWSER_DRIVER_DIR, (CHROME_DRIVER_ZIP)) elif bwser_name == "Edge": file_path = (BROWSER_DRIVER_DIR, (EDGE_DRIVER_ZIP)) (file_path)
第四步,读写配置文件信息
def read_dver_pping_json: """ 读取 pping_json :retn: 字典格式 """ if (DRIVER_MAPPING_FILE): with open(DRIVER_MAPPING_FILE) as fo: try: dver_pping_dict = (fo) # pping.json内容为空时,返回空字典 except dver_pping_dict = {} else: raise FileNotFoundErr(f"{DRIVER_MAPPING_FILE} is not found") retn dver_pping_dict def wte_dver_pping_json(bwser_jor_ver, la_dver_version, dver_path, bwser_name): """ 写入 pping_json :param bwser_jor_ver: 浏览器大版本 :param la_dver_version: 浏览器驱动版本 :param dver_path: 驱动存放路径 :param bwser_name: 浏览器名称 """ pping_dict = read_dver_pping_json # 版本在dict中(浏览器名不在dict中) if bwser_jor_ver in pping_dict: pping_dict[bwser_jor_ver][bwser_name] = { "dver_path": dver_path, "dver_version": la_dver_version } # 大版本不在dict中,且字典不为空 elif bwser_jor_ver not in pping_dict and pping_dict: pping_dict[bwser_jor_ver] = { bwser_name: { "dver_path": dver_path, "dver_version": la_dver_version } } # 字典为空 else: pping_dict = { bwser_jor_ver: { bwser_name: { "dver_path": dver_path, "dver_version": la_dver_version } } } (pping_dict) with open(DRIVER_MAPPING_FILE, 'w') as fo: (pping_dict, fo)
综合
将以上步骤整合到 totic_discover_dver 函数中,通过调用该函数返回浏览器驱动路径。
def totic_discover_dver(bwser_path, bwser_name="Chme"): """ 侦测浏览器驱动是否在pping.json有记录,否则该驱动 :param bwser_path: 浏览器路径 :param bwser_name: 浏览器名称 """ bwser_j_ver = get_bwser_jor_version(bwser_path) # Chme需要获取大版本对应的la release version # Edge 可直接用当前浏览器版本 if bwser_name == "Chme": la_bwser_ver = get_la_bwser_version(bwser_j_ver) elif bwser_name == "Edge": la_bwser_ver = get_bwser_version(bwser_path) else: raise Exception(f"{bwser_name} is not found") # 读取pping.json内容 pping_dict = read_dver_pping_json # json为空 或版本不在pping_dict中 或浏览器名不在pping_dict中 if not pping_dict or \ bwser_j_ver not in pping_dict or \ bwser_name not in pping_dict[bwser_j_ver]: # 浏览器驱动压缩包 download_bwser_dver(la_bwser_ver, bwser_name) # 解压浏览器驱动压缩包,并返回驱动路径 dver_path = unzip_dver(bwser_j_ver, bwser_name) # 将浏览器大版本、浏览器名、驱动路径、对应的浏览器版本信息写入到pping.json中 wte_dver_pping_json(bwser_j_ver, la_bwser_ver, dver_path, bwser_name) # 删除浏览器驱动压缩包 remove_dver_zip(bwser_name) # 返回浏览器驱动的路径 pping_dict = read_dver_pping_json retn pping_dict[bwser_j_ver][bwser_name]["dver_path"]
创建一个 文件验证是否可以自动对应的浏览器驱动。
import py fm time import sleep fm selenium import webdver fm class Search: _CHROME_PATH = r"C:\Pgram Fi (x86)\\Chme\Application\" _EDGE_PATH = r"C:\Pgram Fi (x86)\Micsoft\Edge\Application\" _bwser = "Edge" def setup(self): dver_path = totic(self._EDGE_PATH, self._bwser) if self._bwser == "Chme": (dver_path) elif self._bwser == "Edge": (dver_path) def teardown(self): def _search_bing(self): ("") ("_form_q").send_keys("selenium") ("_go_par").click sleep(3) if __name__ == '__in__':
实测,成打开浏览器!
详细代码可参考: