Chrome падает через несколько часов при многопроцессорной обработке с использованием Selenium через Python - PullRequest
1 голос
/ 12 февраля 2020

Это трассировка ошибки после нескольких часов очистки:

The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.

Это мои настройки селена python:

#scrape.py
from selenium.common.exceptions import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.options import Options

def run_scrape(link):
    chrome_options = Options()
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument("--headless")
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument("--lang=en")
    chrome_options.add_argument("--start-maximized")
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
    chrome_options.binary_location = "/usr/bin/google-chrome"
    browser = webdriver.Chrome(executable_path=r'/usr/local/bin/chromedriver', options=chrome_options)
    browser.get(<link passed here>)
    try:
        #scrape process
    except:
        #other stuffs
    browser.quit()
#multiprocess.py
import time,
from multiprocessing import Pool
from scrape import *

if __name__ == '__main__':
    start_time = time.time()
    #links = list of links to be scraped
    pool = Pool(20)
    results = pool.map(run_scrape, links)
    pool.close()
    print("Total Time Processed: "+"--- %s seconds ---" % (time.time() - start_time))

Chrome, ChromeDriver Setup, Selenium Version

ChromeDriver 79.0.3945.36 (3582db32b33893869b8c1339e8f4d9ed1816f143-refs/branch-heads/3945@{#614})
Google Chrome 79.0.3945.79
Selenium Version: 4.0.0a3

Мне интересно, почему chrome закрывается, а другие процессы работают?

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Я взял ваш код, немного его изменил, чтобы он соответствовал моей Тестовой среде , и вот результаты выполнения:

  • Блок кода:

    • multiprocess.py :

      import time
      from multiprocessing import Pool
      from multiprocessingPool.scrape import run_scrape
      
      if __name__ == '__main__':
          start_time = time.time()
          links = ["https://selenium.dev/downloads/", "https://selenium.dev/documentation/en/"] 
          pool = Pool(2)
          results = pool.map(run_scrape, links)
          pool.close()
          print("Total Time Processed: "+"--- %s seconds ---" % (time.time() - start_time)) 
      
    • scrape.py :

      from selenium import webdriver
      from selenium.common.exceptions import NoSuchElementException, TimeoutException
      from selenium.webdriver.common.by import By
      from selenium.webdriver.chrome.options import Options
      
      def run_scrape(link):
          chrome_options = Options()
          chrome_options.add_argument('--no-sandbox')
          chrome_options.add_argument("--headless")
          chrome_options.add_argument('--disable-dev-shm-usage')
          chrome_options.add_argument("--lang=en")
          chrome_options.add_argument("--start-maximized")
          chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
          chrome_options.add_experimental_option('useAutomationExtension', False)
          chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
          chrome_options.binary_location=r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
          browser = webdriver.Chrome(executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe', options=chrome_options)
          browser.get(link)
          try:
              print(browser.title)
          except (NoSuchElementException, TimeoutException):
              print("Error")
          browser.quit()
      
  • Вывод на консоль:

    Downloads
    The Selenium Browser Automation Project :: Documentation for Selenium
    Total Time Processed: --- 10.248600006103516 seconds ---
    

Заключение

Довольно очевидно, что ваша программа логически безупречна и просто идеальна.


Этот сценарий использования

Поскольку вы упоминали, что эта ошибка появляется после нескольких часов очистки, я подозреваю, что это связано с тем, что WebDriver не является потоком -safe . Тем не менее, если вы можете сериализовать доступ к базовому экземпляру драйвера, вы можете поделиться ссылкой более чем в одном потоке. Это не рекомендуется. Но вы всегда можете создать один экземпляр WebDriver для каждого потока.

В идеале проблема thread-safety не в вашем коде, а в реальных привязках браузера. Все они предполагают, что будет только одна команда за раз (например, как настоящий пользователь). Но с другой стороны, вы всегда можете создать один экземпляр WebDriver для каждого потока, который будет запускать несколько вкладок просмотра / windows. До этого момента кажется, что ваша программа идеальна.

Теперь разные потоки могут быть запущены на одном Webdriver , но тогда результаты тестов не будут вы ожидаете. Причина в том, что когда вы используете многопоточность для запуска разных тестов на разных вкладках / windows требуется немного кодирования безопасности потока, иначе вы будете выполнять такие действия, как click() или send_keys(), будет go к открытой вкладке / окну, которое в настоящее время имеет focus независимо от того, какой поток вы ожидаете запустить. По сути, это означает, что все тесты будут выполняться одновременно на одной вкладке / окне с focus , но , а не на предполагаемой вкладке / окне.

0 голосов
/ 13 февраля 2020

Сейчас я использую этот модуль потоков для создания по одному Webdriver каждому потоку

import threading
threadLocal = threading.local()

def get_driver():
    browser = getattr(threadLocal, 'browser', None)
    if browser is None:
        chrome_options = Options()
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument("--headless")
        chrome_options.add_argument('--disable-dev-shm-usage')
        chrome_options.add_argument("--lang=en")
        chrome_options.add_argument("--start-maximized")
        chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
        chrome_options.add_experimental_option('useAutomationExtension', False)
        chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
        chrome_options.binary_location = "/usr/bin/google-chrome"
        browser = webdriver.Chrome(executable_path=r'/usr/local/bin/chromedriver', options=chrome_options)
        setattr(threadLocal, 'browser', browser)
    return browser

, и это действительно помогает мне очистить быстрее, чем запускать один драйвер за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...