Подтвердить что ты не робот

Selenium: Как вставлять/выполнять Javascript на странице перед загрузкой/выполнением каких-либо других скриптов на странице?

Я использую selenium python webdriver для просмотра некоторых страниц. Я хочу ввести код javascript на страницы, прежде чем загружать и выполнять любые другие коды Javascript. С другой стороны, мне нужен мой JS-код, который будет выполнен как первый JS-код этой страницы. Есть ли способ сделать это с помощью Selenium?

Я отправил его в течение нескольких часов, но я не нашел подходящего ответа!

4b9b3361

Ответ 1

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

String name = (String) ((JavascriptExecutor) driver).executeScript(
    "(function () { ... })();" ...

Документация оставляет неуказанным момент начала выполнения кода. Вы хотите, чтобы это было до того, как DOM начнет загрузку, так что гарантия может быть выполнена только с прокси-сервером или контентом script.

Если вы можете измерить свою страницу с минимальной привязкой, вы можете обнаружить наличие специального параметра запроса url и загрузить дополнительный контент, но вам нужно сделать это с помощью встроенного script. Псевдокод:

 <html>
    <head>
       <script type="text/javascript">
       (function () {
       if (location && location.href && location.href.indexOf("SELENIUM_TEST") >= 0) {
          var injectScript = document.createElement("script");
          injectScript.setAttribute("type", "text/javascript");

          //another option is to perform a synchronous XHR and inject via innerText.
          injectScript.setAttribute("src", URL_OF_EXTRA_SCRIPT);
          document.documentElement.appendChild(injectScript);

          //optional. cleaner to remove. it has already been loaded at this point.
          document.documentElement.removeChild(injectScript);
       }
       })();
       </script>
    ...

Ответ 2

Если вы хотите внедрить что-либо в html-страницу, прежде чем она будет проанализирована и выполнена браузером, я бы посоветовала вам использовать прокси-сервер, такой как Mitmproxy.

Ответ 3

Начиная с версии 1.0.9, selenium-wire получила функциональность для изменения ответов на запросы. Ниже приведен пример этой функции для вставки скрипта в страницу, прежде чем он достигнет веб-браузера.

import os
from seleniumwire import webdriver
from gzip import compress, decompress
from urllib.parse import urlparse

from lxml import html
from lxml.etree import ParserError
from lxml.html import builder

script_elem_to_inject = builder.SCRIPT('alert("injected")')

def inject(req, req_body, res, res_body):
    # various checks to make sure we're only injecting the script on appropriate responses
    # we check that the content type is HTML, that the status code is 200, and that the encoding is gzip
    if res.headers.get_content_subtype() != 'html' or res.status != 200 or res.getheader('Content-Encoding') != 'gzip':
        return None
    try:
        parsed_html = html.fromstring(decompress(res_body))
    except ParserError:
        return None
    try:
        parsed_html.head.insert(0, script_elem_to_inject)
    except IndexError: # no head element
        return None
    injected.append((req, req_body, res, res_body, parsed_html))
    return compress(html.tostring(parsed_html))

drv = webdriver.Firefox(seleniumwire_options={'custom_response_handler': inject}')
drv.header_overrides = {'Accept-Encoding': 'gzip'} # ensure we only get gzip encoded responses

Ответ 4

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

const {Builder, By, Key, until, Capabilities} = require('selenium-webdriver');
const capabilities = new Capabilities();
cap.setPageLoadStrategy('eager'); // Options are 'eager', 'none', 'normal'
let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(capabilities).build();
await driver.get('http://example.com');
driver.executeScript(\'
  console.log('hello'
\')

Этот вариант "рвение" работает для меня. Возможно, вам придется использовать опцию "none". Документация: https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/capabilities_exports_PageLoadStrategy.html

РЕДАКТИРОВАТЬ: Обратите внимание, что опция 'нетерпеливый' еще не был реализован в Chrome...

Ответ 5

Теперь есть https://pypi.org/project/selenium-wire/, который позволяет относительно легко получить доступ/изменить все запросы.