from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exceptions import WebDriverException from bs4 import BeautifulSoup import time import random # Genera un User Agent aleatorio def generate_random_user_agent(): browsers = { "Chrome": range(70, 115), "Firefox": range(60, 110), "Safari": ["13.1", "14.0", "15.0", "16.0", "17.0"], "Edge": range(80, 105), "Opera": range(50, 90), "Brave": range(1, 40), "Vivaldi": range(2, 6), "UC Browser": [f"13.{v}" for v in range(0, 21)] } operating_systems = [ "Windows NT 10.0; Win64; x64", "Windows NT 11.0; Win64; x64", "Macintosh; Intel Mac OS X 10_15_7", "X11; Linux x86_64", "Linux; Android 12; Pixel 5", "iPhone; CPU iPhone OS 16_2 like Mac OS X" ] architectures = ["x86", "x86_64", "ARM", "ARM64"] languages = ["en-US", "en-GB", "es-ES", "fr-FR", "de-DE", "it-IT", "pt-BR", "ru-RU", "zh-CN", "ja-JP", "ko-KR"] browser, version_range = random.choice(list(browsers.items())) version = random.choice(version_range) os_version = random.choice(operating_systems) architecture = random.choice(architectures) language = random.choice(languages) return f"Mozilla/5.0 ({os_version}; {architecture}; {language}) AppleWebKit/537.36 (KHTML, like Gecko) {browser}/{version} Safari/537.36" # Generar un tamaño de ventana aleatorio def get_random_window_size(): window_sizes = [ (1920, 1080), (1366, 768), (1440, 900), (1536, 864), (1280, 800), (1280, 720), (1024, 768) ] return random.choice(window_sizes) # Generar cabeceras HTTP aleatorias def generate_random_headers(): languages = ["es-ES,es;q=0.9", "en-US,en;q=0.9", "fr-FR,fr;q=0.9", "de-DE,de;q=0.9"] accept = ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "application/json,text/html;q=0.9"] return { 'accept-language': random.choice(languages), 'accept': random.choice(accept) } # Simular scroll en la página def simulate_scroll(driver): scroll_pause_time = random.uniform(1, 3) driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(scroll_pause_time) def extract_data(user_input, mode): options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') # Usa un User Agent aleatorio para cada petición options.add_argument(f"user-agent={generate_random_user_agent()}") # Generar cabeceras HTTP aleatorias headers = generate_random_headers() options.add_argument(f"accept-language={headers['accept-language']}") options.add_argument(f"accept={headers['accept']}") wd = None try: wd = webdriver.Chrome(options=options) window_size = get_random_window_size() wd.set_window_size(window_size[0], window_size[1]) # Ajusta el tamaño de la ventana aleatoriamente # Construir la URL de búsqueda url_busqueda = f"https://app.neilpatel.com/es/traffic_analyzer/keywords?domain={user_input}&lang=es&locId=2724&mode={mode}" wd.get(url_busqueda) # Simular scroll en la página simulate_scroll(wd) # Espera aleatoria para simular el comportamiento humano time.sleep(random.uniform(4, 6)) # Espera más larga para simular un comportamiento humano # Obtener el contenido de la página page_content = wd.page_source # Borrar cookies después de cargar la página wd.delete_all_cookies() except WebDriverException as e: return [] finally: if wd: wd.quit() # Parsear el HTML soup = BeautifulSoup(page_content, 'html.parser') # Buscar el div con id="root" root_div = soup.find('div', id='root') if not root_div: return [] # Imprimir el contenido del div con id="root" print(root_div.prettify()) # Extraer el texto plano dentro del div texto_plano = root_div.get_text(separator='\n', strip=True) # Buscar la palabra clave específica "Última actualización" y descartar todo lo anterior keyword = "Última actualización" index = texto_plano.find(keyword) if index != -1: texto_plano = texto_plano[index + len(keyword):].strip() # Eliminar todas las líneas que contienen la palabra "Búsquedas" lineas = texto_plano.split('\n') lineas_filtradas = [linea for linea in lineas if "Búsquedas" not in linea] # Eliminar todo lo que vaya después de la primera línea que incluya "ACTUALIZA A PRO" for i, linea in enumerate(lineas_filtradas): if "ACTUALIZA A PRO" in linea: lineas_filtradas = lineas_filtradas[:i] break # Función para parsear el texto en el formato deseado def parsear_texto(lineas): datos_parseados = [] for i in range(0, len(lineas), 7): if i + 6 < len(lineas): palabra_clave = lineas[i] url = lineas[i + 1] volumen = lineas[i + 2] posicion = lineas[i + 3] visitas = lineas[i + 4] sd = lineas[i + 5] ultima_actualizacion = lineas[i + 6] datos_parseados.append({ "Palabras clave": palabra_clave, "URL": url, "Volumen": volumen, "Posición": posicion, "Visitas": visitas, "SD": sd, "Última actualización": ultima_actualizacion }) return datos_parseados # Parsear el texto filtrado datos_parseados = parsear_texto(lineas_filtradas) return datos_parseados