pyppeteer控制Chromium在隐身模式下启用插件

基础

启用隐身模式

1
2
3
4
5
6
7
8
9
10
11
12
from pyppeteer import launch


async def start_browser():
browser = await launch(**{"headless": False})
browser_context = await browser.createIncognitoBrowserContext()
page = await browser_context.newPage()

await page.goto("http://www.baidu.com")
await browser.close()
return


非隐身模式启用插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pyppeteer import launch


async def start_browser():
chrome_extension_path = "插件所在目录"
args = [
"--load-extension={}".format(chrome_extension_path),
"--disable-extensions-except={}".format(chrome_extension_path),
]

browser = await launch(**{"headless": False, "args": args})
page = await browser.newPage()

await page.goto("http://www.baidu.com")
await browser.close()
return

正文

如果是非隐身模式启用插件的话,上面的代码就可以了。但很蛋疼的是,有个场景必须得在隐身模式下运行,还需要插件。如果是人为操作的话,启用步骤如下:

  1. 打开插件管理页面 chrome://extensions/
  2. 找到需要启动的插件,点击详细信息,进入插件详情。
  3. 在详情中寻找: 在无痕模式下启用的选项并勾选

然后就可以在隐身模式下使用了。

BUT,我的目的是自动隐身模式下启用插件。Google大法开始启用。。。
一个小时后。。。WTF,反正我是没找到正常的实现方式,貌似pyppeteer不支持,不知道是不是有什么隐藏的chrome参数能用的,但找起来太费劲了,放弃。

其实在Google过程中也找到了一个办法,只是不那么优雅而已。其实很简单,就是把上面人为操作的步骤自动化一下。

代码并不是很复杂,不过在实现过程中还是学到了点新东西的。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import asyncio
from pyppeteer.browser import Browser


async def enable_extension_for_incognito(browser: Browser, extension_name: str) -> bool:
"""
在隐身模式下启用指定插件
Args:
extension_name: 插件名称

Returns:

"""
# 新开非隐身窗口并打开扩展程序页面
page = await browser.newPage()
await page.goto("chrome://extensions/")
# 执行js代码获取指定的扩展id
get_eid_js = (
"""() => {
var extension_id;
document.querySelector("extensions-manager").shadowRoot
.querySelector("extensions-item-list").shadowRoot
.querySelectorAll("extensions-item").forEach(function (e) {
var e_name = e.shadowRoot.querySelector("#name").textContent.trim();
if (e_name == "%s") {
extension_id = e.getAttribute("id")
}
})
return extension_id
}"""
% extension_name
)
extension_id = await page.evaluate(get_eid_js)
await asyncio.sleep(1)
# 进入扩展详情页面
await page.goto("chrome://extensions/?id={}".format(extension_id))
# 判断插件是否启用
get_extension_status_js = """
() => {
return document.querySelector("extensions-manager").shadowRoot
.querySelector("extensions-detail-view").shadowRoot
.querySelector("extensions-toggle-row#allow-incognito").shadowRoot
.querySelector("#crToggle").getAttribute("aria-pressed")
}
"""
r = await page.evaluate(get_extension_status_js)
if r != "true":
# 点击在无痕模式下启用
click_enable_js = """
() => {document.querySelector("extensions-manager").shadowRoot
.querySelector("extensions-detail-view").shadowRoot
.querySelector("extensions-toggle-row#allow-incognito").shadowRoot
.querySelector("#crToggle").shadowRoot
.querySelector("button").click()}
"""
await page.evaluate(click_enable_js)
await asyncio.sleep(1)
# 确认是否启用成功
r = await page.evaluate(get_extension_status_js)
assert r == "true"
await page.close()
return True

需要注意的地方有两个:

  1. shadowRoot这个东西第一次遇到。。。
  2. 浏览器有记忆功能。如果你已经启用了某个插件,那么之后再打开的时候插件就已经是启用状态了。