Skip to main content
 首页 » 编程设计

当某些线程创建 Webdriver 时 Python Selenium 失败

2024年10月17日3952php

我有一个线程,它接受一个 URL,在 selenium 中请求它并解析数据。

大多数时候这个线程工作正常。但有时它似乎卡在创建 webdriver 上,我似乎无法对其进行异常处理。

这是线程的开始:

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) 

这是一个片段,但这是重要的部分,因为当它正常工作时,它会继续正常工作。

但是当某个线程停止时,其中一个线程将向控制台发送一个“scraping: link”,而不是向控制台发送一个“Requesting link: link”。

这意味着在实际设置 webdriver 时线程正在停止。据我所知,这是线程安全的,我尝试使用 lock.aquire 并从一批 20 个中随机给它一个 .exe,结果相同。

有时线程会完美地工作然后突然停止而无法发出请求。

更新:

有时当我关闭控制台时,它会告诉我有一个 socket.error。你可以在那个片段中看到尝试的开始,我在最后有这个:

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

但它会愉快地坐在那里数小时,直到我实际关闭控制台。然后它会弹出 socket.error 并为死掉的线程打印“scraping: link”消息。

这实际上表明它甚至在开始 while 之前就失败了,但是 trry 在该线程开始时被设置为 0,并且在其他任何地方都没有被引用。另外,如果它没有 selenium webdriver,就不会出现 socket.error,因此它也必须阻止较早的消息。

更新#2:

当运行完全相同代码的单个线程时,它看起来很高兴运行几个小时。

但是线程锁并没有什么不同。

有点难过。将尝试使用子进程而不是线程来查看它的作用。

更新 #3:

线程并不稳定,但子处理是。好的 Python。

请您参考如下方法:

我在多线程和多处理中以及在使用 Firefox、Chrome 或 PhantomJS 时都遇到过这种情况。无论出于何种原因,实例化浏览器的调用(例如 driver = webdriver.Chrome())永远不会返回。

我的大多数脚本的生命周期都相对较短,线程/进程很少,因此问题并不常见。然而,我有几个脚本会运行几个小时并创建和销毁数百个浏览器对象,而且我保证每次运行都会遇到几次挂起。

我的解决方案是将浏览器实例化放入它自己的函数/方法中,然后使用 PyPI 提供的众多超时和重试装饰器之一装饰函数/方法:

(这是未经测试的)

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