Получать тело запросов, используя селен и прокси - PullRequest
0 голосов
/ 29 ноября 2018

Я хочу иметь возможность получить тело конкретного подзапроса, используя селен за прокси.

Теперь я использую python + selenium + chromedriver.При ведении журнала я могу получить заголовки каждого подзапроса, но не тело.Мои настройки ведения журнала:

caps ['loggingPrefs'] = {'performance': 'ALL', 'browser': 'ALL'}

caps ['perfLoggingPrefs'] ={"enableNetwork": True, "enablePage": True, "enableTimeline": True}

Я знаю, что есть несколько вариантов формирования HAR с селеном:

  • Используйте geckodriver и har-export-trigger .Я попытался заставить его работать со следующим кодом:

window.foo = HAR.triggerExport (). Then (harLog => {return (harLog);});return window.foo;

К сожалению, я не вижу тела ответа в возвращаемых данных.

  • Использовать прокси-сервер browsermob.Решение кажется вполне приемлемым, но я не нашел способа заставить прокси-сервер browsermob работать за прокси-сервером.

Итак, вопрос: как я могу получить тело конкретного сетевого ответа на запрос?сделано во время загрузки веб-страницы с селеном И с использованием прокси.

UPD: На самом деле, с har-export-trigger я получаю тела ответа, но не все из них: тело ответаМне нужно это в JSON, это MIME-тип 'text / html;charset = utf-8 ', и он отсутствует в создаваемом мной файле HAR, поэтому решение по-прежнему отсутствует.

UPD2: После дальнейшего изучения я понял, что тело ответа отсутствует даже на моем настольном Firefox, когданадстройка har-export-trigger включена, поэтому это решение может быть тупиковым ( проблема на Github )

UPD3: эта ошибка можетбыть увиденным только с последней версией har-export-trigger.С версией 0.6.0.все работает просто отлично.

Итак, для будущих гуглов: вы можете использовать har-export-trigger v. 0.6.0.или подход из принятого ответа.

1 Ответ

0 голосов
/ 17 февраля 2019

Я только что закончил реализацию сценария HAR для селена с помощью инструментов, о которых вы упоминали в этом вопросе.Как HAR, получаемый из har-export-trigger и BrowserMob, проверяются с помощью Google HAR Analyzer.

Класс, использующий селен, драйвер gecko и har-export-trigger:

class MyWebDriver(object):
    # a inner class to implement custom wait
    class PageIsLoaded(object):
        def __call__(self, driver):
            state = driver.execute_script('return document.readyState;')
            MyWebDriver._LOGGER.debug("checking document state: " + state)
            return state == "complete"

    _FIREFOX_DRIVER = "geckodriver"
    # load HAR_EXPORT_TRIGGER extension
    _HAR_TRIGGER_EXT_PATH = os.path.abspath(
        "har_export_trigger-0.6.1-an+fx_orig.xpi")
    _PROFILE = webdriver.FirefoxProfile()
    _PROFILE.set_preference("devtools.toolbox.selectedTool", "netmonitor")
    _CAP = DesiredCapabilities().FIREFOX
    _OPTIONS = FirefoxOptions()
    # add runtime argument to run with devtools opened
    _OPTIONS.add_argument("-devtools")
    _LOGGER = my_logger.get_custom_logger(os.path.basename(__file__))

    def __init__(self, log_body=False):
        self.browser = None
        self.log_body = log_body

    # return the webdriver instance
    def get_instance(self):
        if self.browser is None:
            self.browser = webdriver.Firefox(capabilities=
                                             MyWebDriver._CAP,
                                             executable_path=
                                             MyWebDriver._FIREFOX_DRIVER,
                                             firefox_options=
                                             MyWebDriver._OPTIONS,
                                             firefox_profile=
                                             MyWebDriver._PROFILE)
            self.browser.install_addon(MyWebDriver._HAR_TRIGGER_EXT_PATH,
                                       temporary=True)
            MyWebDriver._LOGGER.info("Web Driver initialized.")
        return self.browser

    def get_har(self):
        # JSON.stringify has to be called to return as a string
        har_harvest = "myString = HAR.triggerExport().then(" \
                      "harLog => {return JSON.stringify(harLog);});" \
                      "return myString;"
        har_dict = dict()
        har_dict['log'] = json.loads(self.browser.execute_script(har_harvest))
        # remove content body
        if self.log_body is False:
            for entry in har_dict['log']['entries']:
                temp_dict = entry['response']['content']
                try:
                    temp_dict.pop("text")
                except KeyError:
                    pass
        return har_dict

    def quit(self):
        self.browser.quit()
        MyWebDriver._LOGGER.warning("Web Driver closed.")

Добавление подклассаПрокси BrowserMob для вашей справки:

class MyWebDriverWithProxy(MyWebDriver):

    _PROXY_EXECUTABLE = os.path.join(os.getcwd(), "venv", "lib",
                                     "browsermob-proxy-2.1.4", "bin",
                                     "browsermob-proxy")

    def __init__(self, url, log_body=False):
        super().__init__(log_body=log_body)
        self.server = Server(MyWebDriverWithProxy._PROXY_EXECUTABLE)
        self.server.start()
        self.proxy = self.server.create_proxy()
        self.proxy.new_har(url,
                           options={'captureHeaders': True,
                                    'captureContent': self.log_body})
        super()._LOGGER.info("BrowserMob server started")
        super()._PROFILE.set_proxy(self.proxy.selenium_proxy())

    def get_har(self):
        return self.proxy.har

    def quit(self):
        self.browser.quit()
        self.proxy.close()
        MyWebDriver._LOGGER.info("BroswerMob server and Web Driver closed.")
...