breuerfelix / chromedriver-py

chromedriver self updated binaries for all platforms
https://pypi.org/project/chromedriver-py/
Apache License 2.0
50 stars 16 forks source link

Do we want logic to handle chrome - chromedriver-py missmatch? #18

Closed lundstrj closed 7 months ago

lundstrj commented 2 years ago

Hello,

Long time fan by the way.

I've written a bit of logic to handle the times when my version of Chrome is higher than the current latest version that chromedriver-py can offer. Sometimes an outdated but still very recent version of chromedriver will still get the job done so I wrote code to handle that for my users.

Maybe other people would find that useful too?

I'd be happy to work with you to adapt my code to fit into this project.

breuerfelix commented 2 years ago

Hey @lundstrj , thanks mate :)

well currently I don't do any version comparisons in my package and the user has to manually install the correct chromedriver version by himself so right now i don't really know how your check looks like but it would be awesome if you could just create a PR with your changes and we can look over it :) And then we can still determine whether we merge it or improve it a little bit ! but contributions are always welcome!

lundstrj commented 2 years ago

I imagine this would be a little install helper. I have code to check what version of chrome you have installed and then looks for a matching chromedriver-py version. If there is no matching version available and if your chrome version is higher than the current highest version of chromedriver-py, I also offer the user to try a lower version number of chromedriver-py as that sometimes still will let you run your selenium code. But yeah, let's make a PR.

lundstrj commented 2 years ago

Better late than never. https://github.com/breuerfelix/chromedriver-py/pull/21

RileyXX commented 1 year ago

This is my code for the chrome version check which supports Windows, Linux and MacOS. Tested and working on Windows, untested on Linux and MacOS.

def get_chrome_version():
    system = platform.system()
    if system == 'Windows':
        from winreg import ConnectRegistry, HKEY_CURRENT_USER, OpenKey, QueryValueEx

        try:
            registry = ConnectRegistry(None, HKEY_CURRENT_USER)
            key = OpenKey(registry, r'Software\Google\Chrome\BLBeacon')
            version, _ = QueryValueEx(key, 'version')
            return version.split('.')[0]
        except:
            return None

    elif system == 'Darwin':
        try:
            plist_path = '/Applications/Google Chrome.app/Contents/Info.plist'
            with open(plist_path, 'rb') as plist_file:
                plist_content = plist_file.read().decode('utf-8')
            version_start = plist_content.index('<key>CFBundleShortVersionString</key>') + 38
            version_end = plist_content.index('</string>', version_start)
            return plist_content[version_start:version_end].split('.')[0]
        except:
            return None

    elif system == 'Linux':
        try:
            process = subprocess.run(['google-chrome', '--version'], capture_output=True, text=True)
            version = process.stdout.strip().split(' ')[2].split('.')[0]
            return version
        except:
            return None

    return None

Been running as part of my project that uses chromedriver for some time now and no issues to report from users. Code is based on: https://github.com/RileyXX/IMDB-Trakt-Syncer/blob/main/IMDBTraktSyncer/checkChromedriver.py.

The full code below checks the users current chrome version and downloads the correct version when appropriate. You should be able to just plug this into any project you're working on.

import feedparser
import subprocess
import pkg_resources
import platform
import sys

def get_chrome_version():
    system = platform.system()
    if system == 'Windows':
        from winreg import ConnectRegistry, HKEY_CURRENT_USER, OpenKey, QueryValueEx

        try:
            registry = ConnectRegistry(None, HKEY_CURRENT_USER)
            key = OpenKey(registry, r'Software\Google\Chrome\BLBeacon')
            version, _ = QueryValueEx(key, 'version')
            return version.split('.')[0]
        except:
            return None

    elif system == 'Darwin':
        try:
            plist_path = '/Applications/Google Chrome.app/Contents/Info.plist'
            with open(plist_path, 'rb') as plist_file:
                plist_content = plist_file.read().decode('utf-8')
            version_start = plist_content.index('<key>CFBundleShortVersionString</key>') + 38
            version_end = plist_content.index('</string>', version_start)
            return plist_content[version_start:version_end].split('.')[0]
        except:
            return None

    elif system == 'Linux':
        try:
            process = subprocess.run(['google-chrome', '--version'], capture_output=True, text=True)
            version = process.stdout.strip().split(' ')[2].split('.')[0]
            return version
        except:
            return None

    return None

def install_chromedriver(version):
    # Install the chromedriver-py package using the Python interpreter
    subprocess.run([sys.executable, '-m', 'pip', 'install', '--no-cache-dir', f'chromedriver-py=={version}'])

def install_chromedriver_fallback_method():
    print("Using install chromedriver-py fallback method")
    # Install the chromedriver-py package using the Python interpreter
    feed = feedparser.parse('https://pypi.org/rss/project/chromedriver-py/releases.xml')
    # Get the latest release version
    version = feed.entries[0].title
    # Install the chromedriver-py package using pip
    subprocess.run([sys.executable, '-m', 'pip', 'install', '--no-cache-dir', f'chromedriver-py=={version}'])

# Check if chromedriver-py is already installed
try:
    dist = pkg_resources.get_distribution('chromedriver-py')
    installed_version = dist.version.split('.')[0]  # Retrieve only the prefix
    chrome_version = get_chrome_version()

    if chrome_version and installed_version != chrome_version:
        # Make a request to the RSS feed
        feed = feedparser.parse('https://pypi.org/rss/project/chromedriver-py/releases.xml')

        # Find the corresponding chromedriver-py version
        matching_version = None
        for entry in feed.entries:
            title = entry.title
            if title.startswith(chrome_version):
                matching_version = title
                break

        if matching_version:
            # Install the corresponding chromedriver-py version
            install_chromedriver(matching_version)
        else:
            print(f"No matching chromedriver-py version found for Chrome {chrome_version}")
    else:
        # print("chromedriver-py is already installed with the correct version.")
        pass
except pkg_resources.DistributionNotFound:
    chrome_version = get_chrome_version()

    if chrome_version:
        # Make a request to the RSS feed
        feed = feedparser.parse('https://pypi.org/rss/project/chromedriver-py/releases.xml')

        # Find the corresponding chromedriver-py version
        matching_version = None
        for entry in feed.entries:
            title = entry.title
            if title.startswith(chrome_version):
                matching_version = title
                break

        if matching_version:
            # Install the corresponding chromedriver-py version
            install_chromedriver(matching_version)
        else:
            print(f"No matching chromedriver-py version found for Chrome {chrome_version}")
            install_chromedriver_fallback_method()
    else:
        print("Failed to retrieve Chrome version.")
        install_chromedriver_fallback_method()
breuerfelix commented 1 year ago

The problem is, that i can't add this code to this repo since this would need to fit into another package. otherwhise this would be a "meta" package ... if you bundle a python app, it always has pinned versions, so you cannot really install a different version afterwards.

But thanks for sharing the code! maybe i can put it into the readme :)