6

I'm trying to set MutationObserver for observing page mutation while loading.

In order to do that, MutationObserver should be configured before page loading.

With selenium-chromedriver, couldn't find the way to inject JS for such purpose.

I know chrome extension can do that but extensions won't work on headless mode.

That's the problem.

nemo
  • 171
  • 2
  • 12
  • 1
    A similar [question](https://stackoverflow.com/questions/31354352/)'s answers suggest using a MitM proxy for that. – wOxxOm Nov 15 '17 at 02:04

2 Answers2

16

It's possible via the DevTool API by calling Page.addScriptToEvaluateOnNewDocument

from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
import json

def send(driver, cmd, params={}):
  resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
  url = driver.command_executor._url + resource
  body = json.dumps({'cmd': cmd, 'params': params})
  response = driver.command_executor._request('POST', url, body)
  if response['status']:
    raise Exception(response.get('value'))
  return response.get('value')

def add_script(driver, script):
  send(driver, "Page.addScriptToEvaluateOnNewDocument", {"source": script})

WebDriver.add_script = add_script


# launch Chrome
driver = webdriver.Chrome()

# add a script which will be executed when the page starts loading
driver.add_script("""
  if (window.self === window.top) { // if main document
    console.log('add script');
  }
  """)

# load a page
driver.get("https://stackoverflow.com/questions")
Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • Is there an equivalent Java version? Thank you! – Dickeylth Mar 12 '19 at 08:47
  • 1
    Nope, but it shouldn't be too hard to convert it from this answer: https://stackoverflow.com/questions/45199076/take-full-page-screenshot-in-chrome-with-selenium/45201692#45201692 – Florent B. Mar 12 '19 at 09:05
  • 1
    Couldn't you also use [`execute_cdp_cmd`](https://selenium-python.readthedocs.io/api.html?highlight=cdp#selenium.webdriver.chrome.webdriver.WebDriver.execute_cdp_cmd)? – phk Aug 13 '19 at 06:53
0

We can now use execute_cdp_cmd(cmd, cmd_args) to execute Chrome Devtools Protocol command in Selenium

from selenium import webdriver

driver = webdriver.Chrome()

driver.execute_cdp_cmd(
    "Page.addScriptToEvaluateOnNewDocument",
    {
        "source": """// Your JavaScript here"""
    }
)

driver.get("https://stackoverflow.com")
driver.quit()

The argument for "source" is just a string. So you can actually write your script in a .js file (for syntax highlighting) and read it using Python

NRVulture
  • 18
  • 3