【问题标题】:Python Selenium Failing When Some Threads Create Webdriver当某些线程创建 Webdriver 时 Python Selenium 失败
【发布时间】:2016-06-02 09:33:13
【问题描述】:

我有一个线程,它接受一个 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)

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

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

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

有时线程会完美运行,然后突然停止而无法发出请求。

更新:

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

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

但它会很高兴地坐在那里几个小时,直到我物理关闭控制台。然后它会弹出 socket.error 并为死掉的线程打印“scraping: link”消息。

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

更新 #2:

在运行完全相同代码的单个线程时,运行几个小时似乎很愉快。

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

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

更新#3:

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

【问题讨论】:

    标签: python multithreading selenium


    【解决方案1】:

    我在多线程和多处理以及使用 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

    【讨论】:

    • timeoutcontext 仅在主线程中有效,因为它使用 signal.alarm() 并且 Python 强制所有信号仅传递到主线程。因此,如果您是多线程并从非主线程调用 webdriver,您将无法使用此解决方案;您必须改为多进程(或设置一些方法让主线程为您创建所有新的 webdriver 实例)。
    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 2020-03-19
    • 2012-08-15
    • 2013-04-06
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多