diff --git a/README.md b/README.md index ea8e553..2960b45 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Automatically downloads the driver binary and patches it. ## Installation ## ``` -pip install git+https://github.com/ultrafunkamsterdam/undetected-chromedriver.git +pip install undetected-chromedriver ``` ## Usage ## diff --git a/setup.py b/setup.py index 844e297..f6eb334 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ - """ 888 888 d8b @@ -15,19 +14,24 @@ BY ULTRAFUNKAMSTERDAM (https://github.com/ultrafunkamsterdam)""" from setuptools import setup - - setup( - name='undetected-chromedriver', - version='1.3.5', - packages=['undetected_chromedriver'], - install_requires=[ - 'selenium', + name="undetected-chromedriver", + version="1.3.7", + packages=["undetected_chromedriver"], + install_requires=["selenium",], + url="https://github.com/ultrafunkamsterdam/undetected_chromedriver", + license="GPL-3.0", + author="UltrafunkAmsterdam", + author_email="info@blackhat-security.nl", + description=""" + Optimized Selenium/Chromedriver drop-in replacement for selenium.webdriver, using the same interface for Chrome and ChromeOptions, but which does NOT trigger anti-bot services like Distil / Imperva / DataDome and such. + All required anti-detection settings are built-in, yet overridable if you\'d really want. Be aware: any customization in settings could potentially trigger detection, + For more information check out the README.""", + long_description=open("README.md").read(), + long_description_content_type="text/markdown", + classifiers=[ + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", ], - url='https://github.com/ultrafunkamsterdam/undetected_chromedriver', - license='MIT', - author='UltrafunkAmsterdam', - author_email='', - description='Optimized Selenium Chromedriver patch which does not trigger anti-bot services like Distil Network. ' - 'Automatically downloads the driver binary and patches it.' ) diff --git a/undetected_chromedriver/__init__.py b/undetected_chromedriver/__init__.py index 3977f7c..effcd37 100644 --- a/undetected_chromedriver/__init__.py +++ b/undetected_chromedriver/__init__.py @@ -30,23 +30,23 @@ from selenium.webdriver import ChromeOptions as _ChromeOptions logger = logging.getLogger(__name__) - __IS_PATCHED__ = 0 TARGET_VERSION = 0 class Chrome: - def __new__(cls, *args, **kwargs): if not ChromeDriverManager.installed: ChromeDriverManager(*args, **kwargs).install() if not ChromeDriverManager.selenium_patched: ChromeDriverManager(*args, **kwargs).patch_selenium_webdriver() - if not kwargs.get('executable_path'): - kwargs['executable_path'] = './{}'.format(ChromeDriverManager(*args, **kwargs).executable_path) - if not kwargs.get('options'): - kwargs['options'] = ChromeOptions() + if not kwargs.get("executable_path"): + kwargs["executable_path"] = "./{}".format( + ChromeDriverManager(*args, **kwargs).executable_path + ) + if not kwargs.get("options"): + kwargs["options"] = ChromeOptions() instance = object.__new__(_Chrome) instance.__init__(*args, **kwargs) instance.execute_cdp_cmd( @@ -72,9 +72,7 @@ class Chrome: ) instance.execute_cdp_cmd( "Network.setUserAgentOverride", - { - "userAgent": original_user_agent_string.replace("Headless", ""), - }, + {"userAgent": original_user_agent_string.replace("Headless", ""),}, ) logger.info(f"starting undetected_chromedriver.Chrome({args}, {kwargs})") return instance @@ -86,7 +84,7 @@ class ChromeOptions: ChromeDriverManager(*args, **kwargs).install() if not ChromeDriverManager.selenium_patched: ChromeDriverManager(*args, **kwargs).patch_selenium_webdriver() - + instance = object.__new__(_ChromeOptions) instance.__init__() instance.add_argument("start-maximized") @@ -104,30 +102,31 @@ class ChromeDriverManager(object): DL_BASE = "https://chromedriver.storage.googleapis.com/" - def __init__(self, executable_path=None, target_version=None, *args, **kwargs): _platform = sys.platform - - if TARGET_VERSION: # user override using global + + if TARGET_VERSION: # user override using global self.target_version = TARGET_VERSION - if target_version: - self.target_version = target_version # user override + if target_version: + self.target_version = target_version # user override if not self.target_version: # if target_version still not set, fetch the current major release version - self.target_version = self.get_release_version_number().version[0] # only major version int - + self.target_version = self.get_release_version_number().version[ + 0 + ] # only major version int + self._base = base_ = "chromedriver{}" exe_name = self._base - if _platform in ('win32',): + if _platform in ("win32",): exe_name = base_.format(".exe") - if _platform in ('linux',): - _platform+='64' - exe_name = exe_name.format('') - if _platform in ('darwin',): - _platform = 'mac64' - exe_name = exe_name.format('') + if _platform in ("linux",): + _platform += "64" + exe_name = exe_name.format("") + if _platform in ("darwin",): + _platform = "mac64" + exe_name = exe_name.format("") self.platform = _platform self.executable_path = executable_path or exe_name self._exe_name = exe_name @@ -140,14 +139,12 @@ class ChromeDriverManager(object): """ import selenium.webdriver.chrome.service import selenium.webdriver + selenium.webdriver.Chrome = Chrome selenium.webdriver.ChromeOptions = ChromeOptions - logger.warning( - "Selenium patched. Safe to import Chrome / ChromeOptions" - ) + logger.warning("Selenium patched. Safe to import Chrome / ChromeOptions") self_.__class__.selenium_patched = True - def install(self, patch_selenium=True): """ Initialize the patch @@ -168,7 +165,6 @@ class ChromeDriverManager(object): if patch_selenium: self.patch_selenium_webdriver() - def get_release_version_number(self): """ Gets the latest major version available, or the latest major version of self.target_version if set explicitly. @@ -182,7 +178,6 @@ class ChromeDriverManager(object): ) return LooseVersion(urlopen(self.__class__.DL_BASE + path).read().decode()) - def fetch_chromedriver(self): """ Downloads ChromeDriver from source and unpacks the executable @@ -201,11 +196,10 @@ class ChromeDriverManager(object): with zipfile.ZipFile(zip_name) as zf: zf.extract(self._exe_name) os.remove(zip_name) - if sys.platform != 'win32': + if sys.platform != "win32": os.chmod(self._exe_name, 0o755) return self._exe_name - def patch_binary(self): """ Patches the ChromeDriver binary