Python Selenium falla cuando algunos subprocesos crean Webdriver

Tengo un hilo que toma una URL, la solicita en selenium y analiza los datos.

La mayoría de las veces este hilo funciona bien. Pero a veces parece fallar en la creación del controlador web y parece que no puedo manejar la excepción.

Este es el comienzo del hilo:

def GetLink(eachlink): trry = 0 #10 Attempts at getting the data while trry < 10: print "Scraping: ", eachlink try: Numbergrab = [] Namegrab = [] Positiongrab = [] nextproxy = (random.choice(ProxyList)) nextuseragent = (random.choice(UseragentsList)) proxywrite = '--proxy=',nextproxy service_args = [ proxywrite, '--proxy-type=http', '--ignore-ssl-errors=true', ] dcap = dict(DesiredCapabilities.PHANTOMJS) dcap["phantomjs.page.settings.userAgent"] = (nextuseragent) pDriver = webdriver.PhantomJS('C:\phantomjs.exe',desired_capabilities=dcap, service_args=service_args) pDriver.set_window_size(1024, 768) # optional pDriver.set_page_load_timeout(20) print "Requesting link: ", eachlink pDriver.get(eachlink) try: WebDriverWait(pDriver, 10).until(EC.presence_of_element_located((By.XPATH, "//div[@class='seat-setting']"))) except: time.sleep(10) 

Eso es un fragmento, pero esa es la parte importante porque cuando esté funcionando, seguirá bien.

Pero cuando algo se detenga, uno de los hilos enviará un “enlace de raspado:” a la consola, pero no un “enlace de solicitud: enlace” a la consola.

Lo que significa que el hilo se está estancando cuando se configura el controlador web. Por lo que he visto, esto es seguro para subprocesos y he intentado usar lock.aquire y darle un archivo .exe aleatorio de un lote de 20 con los mismos resultados.

A veces, los subprocesos funcionarán perfectamente y de la nada, uno se detiene sin poder realizar la solicitud.

Actualizar:

A veces, cuando cierro la consola, me dice que había un socket.error. Puedes ver el inicio del bash en ese fragmento de código que tengo al final:

 except: trry +=1 e = sys.exc_info()[0] print "Problem scraping link: ", e 

Pero estará felizmente sentado durante horas sin decir nada hasta que cierre físicamente la consola. Luego aparece con socket.error y el mensaje de impresión “raspado: enlace” para el hilo que murió.

Lo que en realidad sugiere que está fallando incluso antes de comenzar el tiempo, pero ese trry se establece en 0 al comienzo de ese hilo y no se hace referencia en ningún otro lugar. Además, no habría ningún socket.error si no tuviera un controlador web de selenium, por lo que también debe estar bloqueando el mensaje anterior.

Actualización # 2:

Parece que está feliz de correr durante horas cuando se ejecuta un solo hilo del mismo código exacto.

Pero un locking de hilo no hizo una diferencia.

Poco perplejo. Voy a probar un subproceso en lugar de un hilo para ver qué hace eso.

Actualización # 3:

El enhebrado no es estable por mucho tiempo, pero el subprocesamiento sí lo es. OK Python.

Me he encontrado con esto tanto en multiproceso como en multiproceso, y cuando uso Firefox, Chrome o PhantomJS. Por cualquier razón, la llamada para crear una instancia del navegador (eq driver = webdriver.Chrome() ), nunca regresa.

La mayoría de mis scripts son relativamente de corta duración con pocos procesos / subprocesos, por lo que el problema no se ve a menudo. Sin embargo, tengo algunos scripts que se ejecutarán durante varias horas y crearán y destruirán varios cientos de objetos del navegador, y tengo la garantía de que el problema se cuelga varias veces por ejecución.

Mi solución es poner la instanciación del navegador en su propia función / método, y luego decorar la función / método con uno de los muchos decoradores de tiempo de espera y rebashs disponibles en PyPI:

(esto no ha sido probado)

 from retrying import retry from selenium import webdriver from timeoutcontext import timeout, TimeoutException def retry_if_timeoutexception(exception): return isinstance(exception, TimeoutException) @retry(retry_on_exception=retry_if_timeoutexception, stop_max_attempt_number=3) @timeout(30) # Allow the function 30 seconds to create and return the object def get_browser(): return webdriver.Chrome() 

https://pypi.python.org/pypi/retrying

https://pypi.python.org/pypi/timeoutcontext