Espero que un experto pueda ayudarme con un misterio de Selenium/Cloudflare. Puedo hacer que un sitio web se cargue en Selenium normal (sin cabeza), pero no importa lo que intente, no puedo hacer que se cargue sin cabeza.
He seguido las sugerencias de las publicaciones de StackOverflow como ¿Existe una versión de Selenium WebDriver que no sea detectable? . También miré todas las propiedades de los objetos window y window.navigator y arreglé todas las diferencias entre headless y nonheadless, pero de alguna manera todavía se detecta headless. En este punto, tengo mucha curiosidad sobre cómo Cloudflare podría descubrir la diferencia. ¡Gracias por el tiempo!
Lista de las cosas que he probado:
cdc_ con otra cadena en chromedriveroptions.add_experimental_option("excludeSwitches", ["enable-automation"])options.add_experimental_option('useAutomationExtension', False)options.add_argument('--disable-blink-features=AutomationControlled') (esto era necesario para que el sitio web se cargara sin interfaz)navigator.webdriver = undefinednavigator.plugins , navigator.languages y navigator.mimeTypeswindow.ScreenY , window.screenTop , window.outerWidth , window.outerHeight para que no sea cerowindow.chrome y window.navigator.chromeModernizrReplicando el experimento
Para que el sitio web se cargue en Selenium normal (sin cabeza), debe seguir un enlace _blank desde otro sitio web (para que el sitio web de destino se abra en otra pestaña). Para replicar el experimento, primero cree un archivo html con el contenido <a href="https://poocoin.app" target="_blank">link</a> y luego pegue la ruta a este archivo html en el siguiente código.
La versión a continuación (sin cabeza) funciona bien y carga el sitio web, pero si configura options.headless = True , se atascará en Cloudflare.
from selenium import webdriver import time # Replace this with the path to your html file FULL_PATH_TO_HTML_FILE = 'file:///Users/simplepineapple/html/url_page.html' def visit_website(browser): browser.get(FULL_PATH_TO_HTML_FILE) time.sleep(3) links = browser.find_elements_by_xpath("//a[@href]") links[0].click() time.sleep(10) # Switch webdriver focus to new tab so that we can extract html tab_names = browser.window_handles if len(tab_names) > 1: browser.switch_to.window(tab_names[1]) time.sleep(1) html = browser.page_source print(html) print() print() if 'Charts' in html: print('Success') else: print('Fail') time.sleep(10) options = webdriver.ChromeOptions() # If options.headless = True, the website will not load options.headless = False options.add_argument("--window-size=1920,1080") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) options.add_argument('--disable-blink-features=AutomationControlled') options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36') browser = webdriver.Chrome(options = options) browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { "source": ''' Object.defineProperty(navigator, 'webdriver', { get: () => undefined }); Object.defineProperty(navigator, 'plugins', { get: function() { return {"0":{"0":{}},"1":{"0":{}},"2":{"0":{},"1":{}}}; } }); Object.defineProperty(navigator, 'languages', { get: () => ["en-US", "en"] }); Object.defineProperty(navigator, 'mimeTypes', { get: function() { return {"0":{},"1":{},"2":{},"3":{}}; } }); window.screenY=23; window.screenTop=23; window.outerWidth=1337; window.outerHeight=825; window.chrome = { app: { isInstalled: false, }, webstore: { onInstallStageChanged: {}, onDownloadProgress: {}, }, runtime: { PlatformOs: { MAC: 'mac', WIN: 'win', ANDROID: 'android', CROS: 'cros', LINUX: 'linux', OPENBSD: 'openbsd', }, PlatformArch: { ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64', }, PlatformNaclArch: { ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64', }, RequestUpdateCheckStatus: { THROTTLED: 'throttled', NO_UPDATE: 'no_update', UPDATE_AVAILABLE: 'update_available', }, OnInstalledReason: { INSTALL: 'install', UPDATE: 'update', CHROME_UPDATE: 'chrome_update', SHARED_MODULE_UPDATE: 'shared_module_update', }, OnRestartRequiredReason: { APP_UPDATE: 'app_update', OS_UPDATE: 'os_update', PERIODIC: 'periodic', }, }, }; window.navigator.chrome = { app: { isInstalled: false, }, webstore: { onInstallStageChanged: {}, onDownloadProgress: {}, }, runtime: { PlatformOs: { MAC: 'mac', WIN: 'win', ANDROID: 'android', CROS: 'cros', LINUX: 'linux', OPENBSD: 'openbsd', }, PlatformArch: { ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64', }, PlatformNaclArch: { ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64', }, RequestUpdateCheckStatus: { THROTTLED: 'throttled', NO_UPDATE: 'no_update', UPDATE_AVAILABLE: 'update_available', }, OnInstalledReason: { INSTALL: 'install', UPDATE: 'update', CHROME_UPDATE: 'chrome_update', SHARED_MODULE_UPDATE: 'shared_module_update', }, OnRestartRequiredReason: { APP_UPDATE: 'app_update', OS_UPDATE: 'os_update', PERIODIC: 'periodic', }, }, }; ['height', 'width'].forEach(property => { const imageDescriptor = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, property); // redefine the property with a patched descriptor Object.defineProperty(HTMLImageElement.prototype, property, { ...imageDescriptor, get: function() { // return an arbitrary non-zero dimension if the image failed to load if (this.complete && this.naturalHeight == 0) { return 20; } return imageDescriptor.get.apply(this); }, }); }); const getParameter = WebGLRenderingContext.getParameter; WebGLRenderingContext.prototype.getParameter = function(parameter) { if (parameter === 37445) { return 'Intel Open Source Technology Center'; } if (parameter === 37446) { return 'Mesa DRI Intel(R) Ivybridge Mobile '; } return getParameter(parameter); }; const elementDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight'); Object.defineProperty(HTMLDivElement.prototype, 'offsetHeight', { ...elementDescriptor, get: function() { if (this.id === 'modernizr') { return 1; } return elementDescriptor.get.apply(this); }, }); ''' }) visit_website(browser) browser.quit()La protección de cloudflare IUAM se usa principalmente para evitar ataques ddos y, en consecuencia, también protege los sitios de la explotación de bots de automatización, por lo que no importa lo que esté usando en el lado del cliente, el servidor de cloudflare lo está tomando. Después de eso, envían al lado del cliente cf_clearance una cookie que le permite conectarse durante los próximos 15 minutos.