Не удалось расшифровать ответ от сообщения марионетки в скрипте безголового соскабливания Python / Firefox

Добрый день, я провел несколько поисков здесь и в Google, но пока не нашел решения этой проблемы.

Сценарий такой:

У меня есть скрипт Python (2.7), который перебирает ряд URL-адресов (например, думайте о страницах Amazon, просматривайте обзоры). Каждая страница имеет один и тот же HTML-макет, просто извлекается разная информация. Я использую Selenium с безголовым браузером, так как на этих страницах есть javascript, который необходимо выполнить, чтобы получить информацию.

Я запускаю этот сценарий на своем локальном компьютере (OSX 10.10). Firefox - последняя версия v59. Selenium имеет версию 3.11.0 и использует geckodriver v0.20.

Этот сценарий локально не имеет проблем, он может без проблем проходить через все URL-адреса и очищать страницы.

Теперь, когда я помещаю скрипт на свой сервер, единственная разница в том, что это Ubuntu 16.04 (32 бит). Я использую соответствующий geckodriver (все еще v0.20), но все остальное такое же (Python 2.7, Selenium 3.11). Кажется, что он случайно вылетает из безголового браузера, а затем все browserObjt.get('url...') больше не работают.

В сообщениях об ошибках говорится:

Сообщение: не удалось расшифровать ответ от марионетки

Любые дальнейшие запросы селена для страниц возвращают ошибку:

Сообщение: попытка выполнить команду без установления соединения


Чтобы показать код:

Когда я создаю драйвер:

    options = Options()
    options.set_headless(headless=True)

    driver = webdriver.Firefox(
        firefox_options=options,
        executable_path=config.GECKODRIVER
    )

driver передается в функцию скрипта как параметр browserObj, который затем используется для вызова определенных страниц, а затем после загрузки он передается в BeautifulSoup для анализа:

browserObj.get(url)

soup = BeautifulSoup(browserObj.page_source, 'lxml')

Ошибка может указывать на строку BeautifulSoup, которая вызывает сбой браузера.

Что, вероятно, является причиной этого, и что я могу сделать, чтобы решить эту проблему?


Изменить: добавление трассировки стека, которая указывает на одно и то же:

Traceback (most recent call last):
  File "main.py", line 164, in <module>
    getLeague
  File "/home/ps/dataparsing/XXX/yyy.py", line 48, in BBB
    soup = BeautifulSoup(browserObj.page_source, 'lxml')
  File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 670, in page_source
    return self.execute(Command.GET_PAGE_SOURCE)['value']
  File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 312, in execute
    self.error_handler.check_response(response)
  File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
WebDriverException: Message: Failed to decode response from marionette

Примечание: этот скрипт используется для работы с Chrome. Поскольку это 32-битный сервер, я могу использовать только chromedriver v0.33, который поддерживает только Chrome v60-62. В настоящее время Chrome - это v65, а в DigitalOcean у меня, похоже, нет простого способа вернуться к старой версии - вот почему я застрял в Firefox.


person Reily Bourne    schedule 09.04.2018    source источник
comment
Обновите вопрос, указав трассировку стека ошибок.   -  person DebanjanB    schedule 09.04.2018
comment
Добавлена ​​трассировка стека для каждого запроса.   -  person Reily Bourne    schedule 11.04.2018


Ответы (7)


Для тех, кто сталкивается с этой проблемой при запуске selenium webdriver в контейнере Docker, устраняет эту проблему.

Я предполагаю, что это влияет и на физические машины, если OP исправил их проблему, обновив ОЗУ сервера до 2 ГБ, но это могло быть совпадением.

person myol    schedule 17.03.2019
comment
Если бы был способ дать вам более одного голоса, я участвую! Я потратил часы на то, чтобы понять это! Большое спасибо! - person deann; 08.06.2019
comment
Спасибо, это была моя проблема. Очевидно, по умолчанию составляет всего 64 МБ ... - person Cerin; 07.11.2019
comment
Я столкнулся с такой проблемой, пытаясь сделать снимок экрана с полным содержимым, с помощью window.resize_to, а затем driver.screenshot_as, о том, насколько больше я могу масштабировать окно браузера, свободный баран кажется относительным, как вы заявили. - person Jack Wu; 04.12.2019
comment
Это потрясающе! - person Ihor Mak; 12.05.2020
comment
Большое спасибо, я бы застрял надолго - person Nate Simonsen; 26.01.2021

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

Для этого я изменил код парсинга:

import time

browserObj.get(url)

time.sleep(3)

soup = BeautifulSoup(browserObj.page_source, 'lxml')

Нет конкретной причины, по которой я выбрал 3 секунды, но после добавления этой задержки у меня не было ошибки Message: failed to decode response from marionette ни в одном из моих списков URL-адресов для очистки.


Обновление: октябрь 2018 г.

Эта проблема продолжает оставаться проблемой более шести месяцев спустя. Firefox, Geckodriver, Selenium и PyVirtualDisplay были обновлены до последних версий. Эта ошибка повторялась самопроизвольно, без закономерностей: иногда работала, а иногда нет.

Эта проблема была устранена путем увеличения ОЗУ на моем сервере с 1 ГБ до 2 ГБ. С момента роста отказов подобного рода не было.

person Reily Bourne    schedule 12.04.2018
comment
Ваша проблема исправлена ​​?. Я также случайно получаю такую ​​же ошибку. stackoverflow .com / questions / 49831841 /. - person Saurabh Shrivastava; 14.04.2018
comment
Вероятно, из-за этой ошибки - person Levon; 19.08.2018
comment
Некоторое время меня это мучило, прежде чем я обнаружил способ правильно подождать в DOM. Смотрите мой ответ, если вы еще не исправили это. Надеюсь, это поможет! - person Fmstrat; 20.03.2019
comment
Подтверждение того, что увеличение ОЗУ на моем экземпляре Droplet с 1 ГБ до 2 ГБ также решило эту проблему. - person NFB; 27.05.2019

Это сообщение об ошибке ...

Message: failed to decode response from marionette

... означает, что связь между GeckoDriver и Marionette была прервана / прервана.


Вот некоторые из причин и способов решения этой проблемы:

Шаги: настройте размер SHM в контейнере докеров

  • Точно так же при выполнении теста на локальном хосте рекомендуется сохранить следующую (минимальную) конфигурацию:

    --memory 1024mb
    

Дополнительные соображения

Эта проблема также может возникать из-за несовместимости между версиями используемых вами двоичных файлов.

Решение:


GeckoDriver, Selenium < / em> и браузер Firefox таблица совместимости

GeckoDriverVersions


tl; dr

[e10s] Сбой в libyuv :: ARGBSetRow_X86


Ссылка

Вы можете найти соответствующее подробное обсуждение в:

person DebanjanB    schedule 11.02.2020

Проблема в том, что вы не закрываете драйвер. Я совершил ту же ошибку. Whit htop в Linux, я заметил, что я занимаю все 26 ГБ моего компьютера с незакрытым процессом firefox.

person Carlos Rodriguez    schedule 01.06.2019
comment
Да! Это было проблемой и для меня, я заметил, что многие процессы geckodriver.exe все еще работают, поэтому их устранение исправило. - person Teo J.; 30.01.2021

Вероятно, реальная проблема заключается в том, что модель DOM еще не загружена, и вы запускаете поиск на следующей странице. Вот почему sleep(3) работает в большинстве случаев. Правильное решение - использовать класс ожидания.

Это пример тестового случая с использованием функции ожидания для Nextcloud. Это из моего образа docker-selenium-firefox-python: https://hub.docker.com/r/nowsci/selenium

Обратите внимание, как вызывается класс wait, окружающий любые вызовы click или get. По сути, это использует тот факт, что селен изменяет идентификатор тега HTML при загрузке страницы. Функция ожидания проверяет, отличается ли новый идентификатор от старого, и если это так, DOM загружена.

import time
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.keys import Keys

class wait(object):

    def __init__(self, browser):
        self.browser = browser

    def __enter__(self):
        self.old_page = self.browser.find_element_by_tag_name('html')

    def page_has_loaded(self):
        new_page = self.browser.find_element_by_tag_name('html')
        return new_page.id != self.old_page.id

    def __exit__(self, *_):
        start_time = time.time()
        while time.time() < start_time + 5:
            if self.page_has_loaded():
                return True
            else:
                time.sleep(0.1)
        raise Exception('Timeout waiting for page load.')

def test():
    try:
        opts = Options()
        opts.headless = True
        assert opts.headless  # Operating in headless mode
        browser = Firefox(options=opts)
    except Exception as e:
        print("  -=- FAIL -=-: Browser setup - ", e)
        return

    # Test title
    try:
        with wait(browser):
            browser.get('https://nextcloud.mydomain.com/index.php/login')
        assert 'Nextcloud' in browser.title
    except Exception as e:
        print("  -=- FAIL -=-: Initial load - ", e)
        return
    else:
        print("  Success: Initial load")

    try:
        # Enter user
        elem = browser.find_element_by_id('user')
        elem.send_keys("MYUSER")

        # Enter password
        elem = browser.find_element_by_id('password')
        elem.send_keys("MYPASSWORD")

        # Submit form
        elem = browser.find_element_by_id('submit')
        with wait(browser):
            elem.click()

        # Check title for success
        assert 'Files' in browser.title
    except Exception as e:
        print("  -=- FAIL -=-: Login - ", e)
        return
    else:
        print("  Success: Login")

    print("  Finished.")

print("Testing nextcloud...")
test()

Объедините это с ответом @myol, если вы используете Docker.

person Fmstrat    schedule 20.03.2019

Я надеюсь, что это спасет какую-нибудь другую беднягу от часов, которые я только что потратил на это.

Загрузите старую версию firefox (в частности, v66 для меня) и укажите селен там:

firefox_binary='/home/user/Downloads/old_firefox/firefox/firefox'
person jason m    schedule 13.07.2019

Попробуйте это для Ubuntu 16.04:

  1. Установить firefox
sudo apt update
sudo apt install firefox
  1. Убедитесь, что firefox правильно установлен
which firefox

Верну /usr/bin/firefox

  1. Перейдите на страницу geckodriver выпусков. Найдите последнюю версию драйвера для своей платформы и загрузите ее. Например:
wget https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-linux64.tar.gz
  1. Распакуйте файл с помощью:
tar -xvzf geckodriver*
  1. Сделайте его исполняемым:
chmod +x geckodriver
  1. Переместите его в $PATH и предоставьте root доступ
sudo mv geckodriver /usr/bin/
cd /usr/bin
sudo chown root:root geckodriver
  1. Установить selenium
pip3 install selenium
  1. Добавьте firefox и geckodriver к $PATH
sudo vim ~/.bashrc

Добавьте две строки:

export PATH=$PATH:"/usr/bin/firefox"
export PATH=$PATH:"/usr/bin/geckodriver"
  1. Перезагрузите свой экземпляр
sudo reboot
person sashaboulouds    schedule 18.07.2019