user-data-dir=/path/to/directory
。但是,这样做会从我的文件系统深处加载扩展程序,而无法将其纳入git中进行检查。我还尝试过将selenium导航到chrome扩展程序设置页面,但似乎selenium无法驱动
chrome://
页面。有什么想法可以在chrome driver启动时启用chrome扩展程序的隐身模式吗?
user-data-dir=/path/to/directory
。但是,这样做会从我的文件系统深处加载扩展程序,而无法将其纳入git中进行检查。chrome://
页面。以下是针对最新版本的Chrome 74的解决方案。
chrome://extensions
id
)现在我们必须导航到上述URL,然后单击始终允许进入无痕浏览按钮。
Java:
driver.get("chrome://extensions/?id=bhghoamapcdpbohphigoooaddinpkbai");
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input').click()");
Python:
driver.get("chrome://extensions/?id=bhghoamapcdpbohphigoooaddinpkbai")
driver.execute_script("return document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input').click()");
如果您想知道如何以及为什么,请继续阅读
根本原因:
作为Chrome浏览器的增强功能的一部分,谷歌将所有Chrome选项移动到了影子DOM
中。因此,您无法像使用selenium的 find_element
方法那样访问允许在隐身模式下切换元素,该方法将指向页面的原始DOM。因此,我们必须切换到影子DOM
并访问影子树
中的元素。
详情:
注意:我们将引用图片中显示的术语。因此,请参考图片以获得更好的理解。
解决方案:
为了使用影子元素,首先我们必须找到附加了影子DOM
的影子主机
。以下是一个简单的基于shadowHost
获取影子根
的方法。
private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}
然后,您可以使用shadowRoot元素访问阴影树元素。
// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));
public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
WebElement shardowRoot = getShadowRoot(driver, shadowHost);
return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}
现在你可以通过单个方法调用获取 shadowTree 元素
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");
然后像平常一样执行操作,比如 .click()
, .getText()
。
shadowTreeElement.click()
当您只有一个级别的影子DOM时,这看起来很简单。但在这种情况下,我们有多个级别的影子DOM。因此,我们必须通过到达每个影子主机和根元素来访问元素。
以下是使用上述方法(getShadowElement和getShadowRoot)的代码段。
// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("extensions-manager"));
// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "#viewManager > extensions-detail-view.active");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito");
WebElement allowToggle = shadowElementL2.findElement(By.cssSelector("label#label input"));
allowToggle.click();
WebElement allowToggle = (WebElement) js.executeScript("return document.querySelector('extensions-manager').shadowRoot.querySelector('#viewManager > extensions-detail-view.active').shadowRoot.querySelector('div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito').shadowRoot.querySelector('label#label input')");
driver.get('chrome://extensions')
go_to_extension_js_code = '''
var extensionName = 'TestRevolution';
var extensionsManager = document.querySelector('extensions-manager');
var extensionsItemList = extensionsManager.shadowRoot.querySelector(
'extensions-item-list');
var extensions = extensionsItemList.shadowRoot.querySelectorAll(
'extensions-item');
for (var i = 0; i < extensions.length; i += 1) {
var extensionItem = extensions[i].shadowRoot;
if (extensionItem.textContent.indexOf(extensionName) > -1) {
extensionItem.querySelector('#detailsButton').click();
}
}
'''
enable_incognito_mode_js_code = '''
var extensionsManager = document.querySelector('extensions-manager');
var extensionsDetailView = extensionsManager.shadowRoot.querySelector(
'extensions-detail-view');
var allowIncognitoRow = extensionsDetailView.shadowRoot.querySelector(
'#allow-incognito');
allowIncognitoRow.shadowRoot.querySelector('#crToggle').click();
'''
driver.execute_script(go_to_extension_js_code)
driver.execute_script(enable_incognito_mode_js_code)
只需记得将 var extensionName = 'TestRevolution';
这一行更改为你的扩展名即可。
我在编程方面还是新手,但是在查看Chrome的crisper.js
位于chrome://extensions/
后,我找到了另一种方法。
首先,您需要知道扩展程序的ID。您可以通过将id常量here或使用pako的方法获取id来完成。对于我的扩展程序,它是"lmpekldgmhemmmbllpdmafmlofflampm"
然后使用--incognito和addExtension启动Chrome,然后执行JavaScript以在隐身模式下启用。
例如:
public class test2 {
static String dir = System.getProperty("user.dir");
static WebDriver driver;
static JavascriptExecutor js;
public static void main(String[] args) throws InterruptedException, IOException{
ChromeOptions options = new ChromeOptions();
options.addArguments("--incognito");
options.addExtensions(new File(dir + "\\randua.crx"));
System.setProperty("webdriver.chrome.driver",dir + "\\chromedriver73.exe");
driver = new ChromeDriver(options);
js = (JavascriptExecutor) driver;
String extID = "lmpekldgmhemmmbllpdmafmlofflampm";
driver.get("chrome://extensions-frame/");
new WebDriverWait(driver, 60).until(webDriver -> js.executeScript("return document.readyState").equals("complete"));
js.executeScript("chrome.developerPrivate.updateExtensionConfiguration({extensionId: \"" + extID + "\",incognitoAccess: true})");
Thread.sleep(1000);
}
}
如果您正在尝试在隐身模式下启用已安装的扩展程序,则尝试以下代码。它应该适用于Chrome浏览器。
driver.get("chrome://extensions-frame");
WebElement checkbox = driver.findElement(By.xpath("//label[@class='incognito-control']/input[@type='checkbox']"));
if (!checkbox.isSelected()) {
checkbox.click();
}