From 82d749f261a15eaf9b009c08791f71d5bfad6c12 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot <378351+weskerfoot@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:12:53 -0500 Subject: [PATCH] Starting a refactor of all chrome driver code (#105) * Starting a refactor of all chrome driver code * proper chrome version extraction --- deletefb/exceptions.py | 3 ++ deletefb/tools/chrome_driver.py | 67 +++++++++++++++++++++++++++------ deletefb/tools/login.py | 2 +- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/deletefb/exceptions.py b/deletefb/exceptions.py index 6f22085..c316d44 100644 --- a/deletefb/exceptions.py +++ b/deletefb/exceptions.py @@ -1,2 +1,5 @@ class UnknownOSException(Exception): pass + +class ChromeError(Exception): + pass diff --git a/deletefb/tools/chrome_driver.py b/deletefb/tools/chrome_driver.py index e048716..1f6081d 100644 --- a/deletefb/tools/chrome_driver.py +++ b/deletefb/tools/chrome_driver.py @@ -1,19 +1,16 @@ -from ..exceptions import UnknownOSException +from ..exceptions import UnknownOSException, ChromeError from .common import NO_CHROME_DRIVER from clint.textui import puts, colored from selenium import webdriver +from shutil import which +from subprocess import check_output from urllib.request import urlretrieve import os, sys, stat, platform import progressbar import re import zipfile - -chrome_drivers = { - "Windows" : "https://chromedriver.storage.googleapis.com/80.0.3987.16/chromedriver_win32.zip", - "Darwin" : "https://chromedriver.storage.googleapis.com/80.0.3987.16/chromedriver_mac64.zip", - "Linux" : "https://chromedriver.storage.googleapis.com/80.0.3987.16/chromedriver_linux64.zip" -} +import requests def extract_zip(filename): """ @@ -45,7 +42,54 @@ def setup_selenium(driver_path, options): # Configures selenium to use a custom path return webdriver.Chrome(executable_path=driver_path, options=options) -def get_webdriver(): +def parse_version(output): + """ + Attempt to extract version number from chrome version string. + """ + return [c for c in re.split('([0-9]+)\.?', output.decode("utf-8")) if all(d.isdigit() for d in c) and c][0] + +def get_chrome_version(chrome_binary_path=None): + """ + Extract the chrome major version. + """ + driver_locations = [which(loc) for loc in ["google-chrome", "google-chrome-stable", "chromium", "chrome.exe"]] + + for location in driver_locations: + print(location) + if location: + return parse_version(check_output([location, "--version"]).strip()) + return None + +def construct_driver_url(chrome_binary_path=None): + """ + Construct a URL to download the Chrome Driver. + """ + + platform_string = platform.system() + chrome_drivers = { + "Windows" : "https://chromedriver.storage.googleapis.com/{0}/chromedriver_win32.zip", + "Darwin" : "https://chromedriver.storage.googleapis.com/{0}/chromedriver_mac64.zip", + "Linux" : "https://chromedriver.storage.googleapis.com/{0}/chromedriver_linux64.zip" + } + + version = get_chrome_version() + + if version is None: + raise ChromeError("Chrome version not found") + + latest_release_url = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_{0}".format(version) + + return chrome_drivers.get(platform_string).format(requests.get(latest_release_url).text) + + # First, construct a LATEST_RELEASE URL using Chrome's major version number. + # For example, with Chrome version 73.0.3683.86, use URL "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_73". + # Try to download a small file from this URL. If it successful, the file contains the ChromeDriver version to use. + # If the above step failed, reduce the Chrome major version by 1 and try again. + # For example, with Chrome version 75.0.3745.4, use URL "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_74" + # to download a small file, which contains the ChromeDriver version to use. + # You can also use ChromeDriver Canary build. + +def get_webdriver(chrome_binary_path): """ Ensure a webdriver is available If Not, Download it. @@ -65,7 +109,8 @@ def get_webdriver(): else: # Download it according to the current machine - chrome_webdriver = chrome_drivers.get(platform.system(), False) + chrome_webdriver = construct_driver_url(chrome_binary_path) + if not chrome_webdriver: raise UnknownOSException("Unknown Operating system platform") @@ -91,8 +136,8 @@ def get_webdriver(): file_name = chrome_webdriver.split('/')[-1] response = urlretrieve(chrome_webdriver, file_name, show_progress) - if int(response[1].get('Content-Length')) == total_size: - puts(colored.green(f"DONE!")) + if int(response[1].get("Content-Length")) == total_size: + puts(colored.green("Completed downloading the Chrome Driver.")) return "{0}/{1}".format(os.getcwd(), extract_zip(file_name)) diff --git a/deletefb/tools/login.py b/deletefb/tools/login.py index daae1d5..17866cf 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -40,7 +40,7 @@ def login(user_email_address, chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('log-level=2') - driver_path = get_webdriver() + driver_path = get_webdriver(chrome_binary_path) driver = setup_selenium(driver_path, chrome_options) driver.implicitly_wait(10)