Selenium использует слишком много оперативной памяти с Firefox

Я использую селен с Firefox для автоматизации некоторых задач в Instagram. Он в основном перемещается между профилями пользователей и страницами уведомлений и выполняет задачи в зависимости от того, что он находит.

У этого есть один бесконечный цикл, который гарантирует, что задача продолжается. У меня есть функция sleep() каждые несколько шагов, но использование памяти продолжает расти. У меня есть что-то вроде этого в Python:

while(True):
    expected_conditions()
    ...doTask()
    driver.back()
    expected_conditions()
    ...doAnotherTask()
    driver.forward()
    expected_conditions()

Я никогда не закрываю драйвер, потому что это сильно замедлит работу программы, поскольку у нее много запросов для обработки. Есть ли какой-нибудь способ не допустить увеличения объема используемой памяти без закрытия или выхода из драйвера?

РЕДАКТИРОВАТЬ: Добавлены явные условия, но это тоже не помогло. Я использую безголовый режим Firefox.

3 ответа

Решение

Для начала, у Selenium очень мало контроля над объемом оперативной памяти, используемой Firefox. Как вы упомянули, клиент браузера, то есть Mozilla, перемещается назад и вперед между профилями пользователей и страницей уведомлений в Instagram и выполняет задачи, основанные на том, что он считает слишком широким для одного варианта использования. Итак, первой и главной задачей было бы разбить бесконечный цикл, относящийся к вашему сценарию использования, на более мелкие тесты.


time.sleep()

Склонение time.sleep() жизненно ставит одеяло над основной проблемой. Однако при использовании Selenium и WebDriver для автоматизации используется time.sleep(secs) без каких-либо конкретных условий для достижения поражений цели автоматизации и следует избегать любой ценой. Согласно документации:

time.sleep(secs) приостанавливает выполнение текущего потока на указанное количество секунд. Аргумент может быть числом с плавающей запятой, чтобы указать более точное время сна. Фактическое время приостановки может быть меньше запрошенного, потому что любой перехваченный сигнал прервет sleep() после выполнения процедуры перехвата этого сигнала. Кроме того, время приостановки может быть дольше, чем запрошено на произвольную величину из-за планирования других действий в системе.

Вы можете найти подробное обсуждение в разделе Как перевести webdriver в Python на миллисекунды.


Анализ

В предыдущих случаях Firefox потреблял около 80% оперативной памяти.

Однако, согласно этому обсуждению, некоторые пользователи считают, что чем больше памяти используется, тем лучше, потому что это означает, что у вас не тратится ОЗУ. Firefox использует оперативную память для ускорения своих процессов, поскольку данные приложений передаются в оперативную память гораздо быстрее.


Решение

Вы можете реализовать один / все общие / конкретные шаги следующим образом:

  • Обновление Selenium до текущих уровней Версия 3.141.59.
  • Обновите GeckoDriver до уровня GeckoDriver v0.24.0.
  • Обновите версию Firefox до уровня Firefox v65.0.2.
  • Очистите рабочее пространство проекта через IDE и перестройте проект только с необходимыми зависимостями.
  • Если ваша базовая версия веб-клиента устарела, удалите ее и установите последнюю версию GA и выпущенную версию веб-клиента.
  • Некоторые расширения позволяют вам блокировать такой ненужный контент, например:

    • uBlock Origin позволяет скрывать рекламу на сайтах.
    • NoScript позволяет выборочно включать и отключать все скрипты, работающие на сайтах.
    • Чтобы открыть клиент Firefox с расширением, вы можете скачать расширение, т.е. XPI файл с https://addons.mozilla.org/ и использовать add_extension(extension='webdriver.xpi') метод для добавления расширения в FirefoxProfile следующим образом:

      from selenium import webdriver
      
      profile = webdriver.FirefoxProfile() 
      profile.add_extension(extension='extension_name.xpi')
      driver = webdriver.Firefox(firefox_profile=profile, executable_path=r'C:\path\to\geckodriver.exe') 
      
  • Если ваши тесты не требуют CSS, вы можете отключить CSS, следуя этому обсуждению.

Что ж, это серьезная проблема, с которой я сталкивался несколько дней. Но я нашел решение. Вы можете добавить несколько флагов для оптимизации использования памяти.

options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
options.add_argument('--no-sandbox')
options.add_argument('--disable-application-cache')
options.add_argument('--disable-gpu')
options.add_argument("--disable-dev-shm-usage")

Я добавил эти флаги. До того, как я добавил флаги, использование ОЗУ продолжало увеличиваться после того, как оно превысило 4 ГБ (8 ГБ на моей машине), моя машина зависла. после того, как я добавил эти флаги, использование памяти не превышало 50 МБ. И, как отвечает DebanjanB, если вы запустите for loop или же while loop пытается перевести в режим сна на несколько секунд после каждого выполнения, это дает время, чтобы убить неиспользуемый поток.

  • Используйте явные ожидания или неявные ожидания.
  • Используйте driver.quit(), чтобы закрыть все окна браузера и завершить сеанс WebDriver, потому что если вы не используете quit () в конце программы, сеанс WebDriver не будет закрыт должным образом и файлы не будут удалены из памяти., И это может привести к ошибкам утечки памяти.

Создание нового профиля Firefox и использование его каждый раз во время выполнения тестовых примеров в Firefox в конечном итоге повысит производительность выполнения, поскольку без этого всегда будет создаваться новый профиль и там будет выполняться кеширование информации, и если driver.quit не вызывается каким-либо образом раньше сбой в этом случае, каждый раз, когда мы в конечном итоге создаем новые профили с некоторой кэшированной информацией, которая будет занимать память.

// ------------ Создание нового профиля Firefox -------------------

1. If Firefox is open, close Firefox.
2. Press Windows +R on the keyboard. A Run dialog will open.
3. In the Run dialog box, type in firefox.exe -P
Note: You can use -P or -ProfileManager(either one should work).
4. Click OK.
5. Create a new profile and sets its location to the RAM Drive.

// ----------- Связывание профиля Firefox -------------------

ProfilesIni profile = new ProfilesIni();
FirefoxProfile myprofile = profile.getProfile("automation_profile");
WebDriver driver = new FirefoxDriver(myprofile);

Пожалуйста, поделитесь эффективностью выполнения с сообществом, если вы планируете реализовать этот способ.

На данный момент для этого нет исправления. Я предлагаю вам использовать подход driver.close(). Я также боролся с проблемой RAM, и я подсчитал количество циклов, и когда количество циклов достигло определенного числа (для меня это было 200), я вызвал driver.close(), а затем снова запустил драйвер а также сбросить счетчик. Таким образом, мне не нужно было закрывать драйвер каждый раз при выполнении цикла, и это также меньше влияло на производительность. Попробуй это. Может быть, и в твоем случае это поможет.

Другие вопросы по тегам