2.1.0 - multiple (hot)fixes and added emulate_touch argument
added a keyword argument to the Chrome constructor: emulate_touch, which, when set to True will mimick the presense of a touch(screen/device) for certain tests. This is mainly for bet365 detections. Otherwise i would not recommend setting it. credits to @boganfoo for this excellent find! - removed `enable_console_log` - reverted back to storing chromedriver binary in current workdir after several reports of users entire project folder being deleted (sorry for that btw). - some code cleanup - added a fix for useragent in headless mode in v2 (which reported 'Headless'). still headless mode in v2 is under construction and not fully functional. - fixed bug in latest chrome which closes the window when using v2 in contextmanager mode or get_in method.
This commit is contained in:
commit
de55331c53
2
setup.py
2
setup.py
|
@ -16,7 +16,7 @@ from setuptools import setup
|
|||
|
||||
setup(
|
||||
name="undetected-chromedriver",
|
||||
version="2.0.2",
|
||||
version="2.1.0",
|
||||
packages=["undetected_chromedriver"],
|
||||
install_requires=["selenium",],
|
||||
url="https://github.com/ultrafunkamsterdam/undetected-chromedriver",
|
||||
|
|
|
@ -37,7 +37,7 @@ TARGET_VERSION = 0
|
|||
|
||||
|
||||
class Chrome:
|
||||
def __new__(cls, *args, enable_console_log=False, **kwargs):
|
||||
def __new__(cls, *args, emulate_touch=False, **kwargs):
|
||||
|
||||
if not ChromeDriverManager.installed:
|
||||
ChromeDriverManager(*args, **kwargs).install()
|
||||
|
@ -61,28 +61,25 @@ class Chrome:
|
|||
{
|
||||
"source": """
|
||||
|
||||
Object.defineProperty(window, 'navigator', {
|
||||
value: new Proxy(navigator, {
|
||||
has: (target, key) => (key === 'webdriver' ? false : key in target),
|
||||
get: (target, key) =>
|
||||
key === 'webdriver'
|
||||
? undefined
|
||||
: typeof target[key] === 'function'
|
||||
? target[key].bind(target)
|
||||
: target[key]
|
||||
})
|
||||
});
|
||||
"""
|
||||
+ (
|
||||
"console.log = console.dir = console.error = function(){};"
|
||||
if not enable_console_log
|
||||
else ""
|
||||
)
|
||||
Object.defineProperty(window, 'navigator', {
|
||||
value: new Proxy(navigator, {
|
||||
has: (target, key) => (key === 'webdriver' ? false : key in target),
|
||||
get: (target, key) =>
|
||||
key === 'webdriver'
|
||||
? undefined
|
||||
: typeof target[key] === 'function'
|
||||
? target[key].bind(target)
|
||||
: target[key]
|
||||
})
|
||||
});
|
||||
"""
|
||||
},
|
||||
)
|
||||
return instance._orig_get(*args, **kwargs)
|
||||
|
||||
instance.get = _get_wrapped
|
||||
instance.get = _get_wrapped
|
||||
instance.get = _get_wrapped
|
||||
|
||||
original_user_agent_string = instance.execute_script(
|
||||
"return navigator.userAgent"
|
||||
|
@ -91,11 +88,22 @@ class Chrome:
|
|||
"Network.setUserAgentOverride",
|
||||
{"userAgent": original_user_agent_string.replace("Headless", ""),},
|
||||
)
|
||||
if emulate_touch:
|
||||
instance.execute_cdp_cmd(
|
||||
"Page.addScriptToEvaluateOnNewDocument",
|
||||
{
|
||||
"source": """
|
||||
Object.defineProperty(navigator, 'maxTouchPoints', {
|
||||
get: () => 1
|
||||
})"""
|
||||
},
|
||||
)
|
||||
logger.info(f"starting undetected_chromedriver.Chrome({args}, {kwargs})")
|
||||
return instance
|
||||
|
||||
|
||||
class ChromeOptions:
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not ChromeDriverManager.installed:
|
||||
ChromeDriverManager(*args, **kwargs).install()
|
||||
|
|
|
@ -119,8 +119,9 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
keep_alive=True,
|
||||
debug_addr=None,
|
||||
user_data_dir=None,
|
||||
factor=0.5,
|
||||
delay=1,
|
||||
factor=1,
|
||||
delay=2,
|
||||
emulate_touch=False,
|
||||
):
|
||||
|
||||
p = Patcher(target_path=executable_path)
|
||||
|
@ -165,6 +166,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
extra_args = []
|
||||
if options.headless:
|
||||
extra_args.append("--headless")
|
||||
extra_args.append("--window-size=1920,1080")
|
||||
|
||||
self.browser_args = [
|
||||
find_chrome_executable(),
|
||||
|
@ -195,12 +197,60 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
keep_alive=keep_alive,
|
||||
)
|
||||
|
||||
if options.headless:
|
||||
|
||||
orig_get = self.get
|
||||
|
||||
def get_wrapped(*args, **kwargs):
|
||||
if self.execute_script("return navigator.webdriver"):
|
||||
self.execute_cdp_cmd(
|
||||
"Page.addScriptToEvaluateOnNewDocument",
|
||||
{
|
||||
"source": """
|
||||
Object.defineProperty(window, 'navigator', {
|
||||
value: new Proxy(navigator, {
|
||||
has: (target, key) => (key === 'webdriver' ? false : key in target),
|
||||
get: (target, key) =>
|
||||
key === 'webdriver'
|
||||
? undefined
|
||||
: typeof target[key] === 'function'
|
||||
? target[key].bind(target)
|
||||
: target[key]
|
||||
})
|
||||
});
|
||||
"""
|
||||
},
|
||||
)
|
||||
|
||||
self.execute_cdp_cmd(
|
||||
"Network.setUserAgentOverride",
|
||||
{
|
||||
"userAgent": self.execute_script(
|
||||
"return navigator.userAgent"
|
||||
).replace("Headless", "")
|
||||
},
|
||||
)
|
||||
return orig_get(*args, **kwargs)
|
||||
|
||||
self.get = get_wrapped
|
||||
|
||||
if emulate_touch:
|
||||
self.execute_cdp_cmd(
|
||||
"Page.addScriptToEvaluateOnNewDocument",
|
||||
{
|
||||
"source": """
|
||||
Object.defineProperty(navigator, 'maxTouchPoints', {
|
||||
get: () => 1
|
||||
})"""
|
||||
},
|
||||
)
|
||||
|
||||
def start_session(self, capabilities=None, browser_profile=None):
|
||||
if not capabilities:
|
||||
capabilities = self.options.to_capabilities()
|
||||
super().start_session(capabilities, browser_profile)
|
||||
|
||||
def get_in(self, url: str, delay=2.5, factor=1):
|
||||
def get_in(self, url: str, delay=2, factor=1):
|
||||
"""
|
||||
:param url: str
|
||||
:param delay: int
|
||||
|
@ -233,10 +283,11 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
try:
|
||||
self.get(url)
|
||||
finally:
|
||||
self.close()
|
||||
self.service.stop()
|
||||
# threading.Timer(factor or self.factor, self.close).start()
|
||||
time.sleep(delay or self.delay)
|
||||
self.start_session()
|
||||
self.service.start()
|
||||
# self.start_session()
|
||||
|
||||
def quit(self):
|
||||
try:
|
||||
|
@ -263,9 +314,10 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.close()
|
||||
threading.Timer(self.factor, self.start_session).start()
|
||||
self.service.stop()
|
||||
#threading.Timer(self.factor, self.service.start).start()
|
||||
time.sleep(self.delay)
|
||||
self.service.start()
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.options.debugger_address)
|
||||
|
@ -274,10 +326,9 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|||
class Patcher(object):
|
||||
url_repo = "https://chromedriver.storage.googleapis.com"
|
||||
|
||||
def __init__(self, target_path=None, force=False, version_main: int = 0):
|
||||
|
||||
if not target_path:
|
||||
target_path = os.path.join(tempfile.gettempdir(), 'undetected_chromedriver', 'chromedriver')
|
||||
def __init__(
|
||||
self, target_path="./chromedriver", force=False, version_main: int = 0
|
||||
):
|
||||
if not IS_POSIX:
|
||||
if not target_path[-4:] == ".exe":
|
||||
target_path += ".exe"
|
||||
|
@ -446,8 +497,8 @@ class Patcher(object):
|
|||
linect += 1
|
||||
return linect
|
||||
|
||||
def __del__(self):
|
||||
shutil.rmtree(os.path.dirname(self.target_path), ignore_errors=True)
|
||||
|
||||
|
||||
|
||||
|
||||
class ChromeOptions(selenium.webdriver.chrome.webdriver.Options):
|
||||
|
|
Loading…
Reference in New Issue