1.drissionpage
drissionpage是2023年新开发的一款自动化框架。
它的特点是可以抓取到shadow-root.
通过这个可以越过cloudflare以及recaptcha v2(只能使用播放音频的方式去选择越过).
5s盾越过方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
if 'Just a moment' in tab.title or '请稍候' in tab.title:
if tab.ele('x://div[@id="rvwE0"]', timeout=10):
# 这里是有可能会出现的button。
if tab.ele('x://div[@id="rvwE0"]/div/input', timeout=0.1):
tab.ele('x://div[@id="rvwE0"]/div/input').click()
iframe = tab.ele('x://div[@id="rvwE0"]/div/div').sr('x://iframe', timeout=10)
if iframe:
body = iframe.ele('x://body', timeout=10)
if body:
checkbox = body.sr('x://input[@type="checkbox"]', timeout=10)
if checkbox:
print("检测到 Cloudflare 验证,尝试点击复选框")
checkbox.click()
print("已点击 Cloudflare 验证框")
if tab.ele('x://div[@id="rvwE0"]/div/input', timeout=20):
tab.ele('x://div[@id="rvwE0"]/div/input').click()
|
2.记录一个头疼的迁移问题
众所周知脚本的开发调试在win上基本上是没问题的。问题是在linux下可能就执行不了。
同一套代码不但是运行的问题以及环境差异的导致。
这里我一共出现两个问题。
1. 脚本无法在linux系统上安装chrome插件。
2. 同一个方法在windows和linux上有差异?
a.首先第一点安装chrome插件。
1.编写简易插件,不起作用。
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# 代理服务器信息(以 SOCKS5 代理为例)
proxyHost = "38.60.xx.xx" # SOCKS5 代理地址
proxyPort = "10888" # SOCKS5 代理端口
def create_proxy_extension(proxy_host, proxy_port, scheme='socks5', plugin_path=None):
# 创建Chrome插件的manifest.json文件内容
manifest_json = """
{
"version": "1.0.0",
"manifest_version": 2,
"name": "SOCKS5 Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
"""
# 创建Chrome插件的background.js文件内容
background_js = string.Template(
"""
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "${scheme}",
host: "${host}",
port: parseInt(${port})
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {}; // No credentials needed for SOCKS5 without authentication
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);
"""
).substitute(
host=proxy_host,
port=proxy_port,
scheme=scheme,
)
# 创建插件目录并写入manifest.json和background.js文件
os.makedirs(plugin_path, exist_ok=True)
with open(os.path.join(plugin_path, "manifest.json"), "w+") as f:
f.write(manifest_json)
with open(os.path.join(plugin_path, "background.js"), "w+") as f:
f.write(background_js)
return os.path.join(plugin_path)
proxy_auth_plugin_path = create_proxy_extension(
plugin_path="/tmp/drissionpage", # 插件保存路径
proxy_host=proxyHost,
proxy_port=proxyPort
)
co = ChromiumOptions().add_extension(path=proxy_auth_plugin_path)
|
尽管background_js编写最简单的输出代码都无法安装上。
2.通过API添加浏览器插件。
co.add_extension('/opt/proxy_switchyomega-2.5.20-an+fx')
确保有这个文件夹
这里添加之后前往插件页面验证。
1
2
3
|
tab.get("chrome://extensions")
tab.wait(3)
print("Extensions page HTML: ", tab.html)
|
打印出的页面最终显示是空的.看extensions-manager标签。仍然不起作用。
1
2
3
4
|
<body>
<extensions-manager></extensions-manager>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
</body></html>
|
3.命令行添加插件
google-chrome --no-sandbox --headless --load-extension=/tmp/drissionpage
还是不起作用。
最终无奈只能安装远程桌面
最终不知道什么原因,依旧无法安装插件,这里我最终安装了linux桌面环境来进行安装。
1
2
3
4
5
6
7
8
|
#安装XFCE桌面环境
sudo apt install -y xfce4 xfce4-goodies
#安装XRDP
sudo apt install -y xrdp
echo "startxfce4" > ~/.xsession
chmod +x ~/.xsession
sudo systemctl enable xrdp
sudo systemctl start xrdp
|
安装完成之后就可以在本地windows上打开远程桌面进行互联了。
账号密码可以用root的
连接后,可以更改服务区上的代码。
可以先将无头模式取消,这样在桌面上,可以看到chrome的运行情况,方便调试。
1
2
3
4
5
6
7
8
9
10
|
# 设置浏览器选项
co = ChromiumOptions()
co.set_user_agent(user_agent=windows_user_agent)
# co.set_argument("--headless=new")
co.set_argument('--incognito')
co.set_argument("--no-sandbox")
co.set_local_port(9211)
co.add_extension('/opt/proxy_switchyomega-2.5.20-an+fx')
self.browser = Chromium(co)
self.browser.set.auto_handle_alert()
|
然后手动进去settings-》Extensions-》
进入页面后,点击Developer mode-》点击Load unPacked
然后将GitHub上下载的SwitchyOmega目录打开。
解压的文件夹。然后应该打开就会和我一样。安装插件成功了(终于)。
这是切换ip的方法。
原理是通过插件进行自动化来更改代理,插件也算网页可以通过捕捉元素来进行操作。
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
|
def switch_ip(self,tab,ip_port=None, proxy_type=None):
global set_proxy
if ip_port:
# 设置proxy
if proxy_type is None:
proxy_type = 'HTTP'
else:
proxy_type = proxy_type.upper()
ip, port = ip_port.split(":")
tab.get("chrome-extension://padekgcemlokbadohgkifijomclgjgif/options.html#!/profile/proxy")
tab.wait(3)
print(tab.url)
print(tab.html)
tab.ele('x://select[@ng-model="proxyEditors[scheme].scheme"]').select(proxy_type)
tab.ele('x://input[@ng-model="proxyEditors[scheme].host"]').clear(by_js=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].host"]').input(ip, clear=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].port"]').clear(by_js=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].port"]').input(port, clear=True)
tab.ele('x://a[@ng-click="applyOptions()"]').click()
# 提示框
txt = tab.handle_alert()
print("提示框", txt)
tab.handle_alert(accept=False)
if not set_proxy:
# 切换proxy
tab.get("chrome-extension://padekgcemlokbadohgkifijomclgjgif/popup/index.html#")
tab.wait(1)
tab.ele('x://span[text()="proxy"]').click()
set_proxy = True
else:
tab = self.browser.new_tab()
tab.get("chrome-extension://padekgcemlokbadohgkifijomclgjgif/popup/index.html#")
tab.ele('x://span[text()="[直接连接]"]').click()
if len(self.browser.tab_ids) > 1:
print("当前tab个数", len(self.browser.tab_ids))
tab.close()
self.switch_ip(tab,f"38.60.xx.xx:10888", "socks5")
|
b.无键盘驱动问题
.input(ip, clear=True)
这里clear看文档,是通过按键去清空的,但是linux上好像没有键盘驱动,似乎无法在输入之前清空掉文本框。
这里需要使用js去清空。
.clear(by_js=True)
至少我在windows上
tab.ele(‘x://input[@ng-model=“proxyEditors[scheme].host”]’).input(ip, clear=True)
是可以清空的。但是linux上没有正确清空掉文本框,导致代理无法配置成功。
前面要加上tab.ele(‘x://input[@ng-model=“proxyEditors[scheme].host”]’).clear(by_js=True)
1
2
3
4
5
6
|
tab.ele('x://select[@ng-model="proxyEditors[scheme].scheme"]').select(proxy_type)
tab.ele('x://input[@ng-model="proxyEditors[scheme].host"]').clear(by_js=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].host"]').input(ip, clear=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].port"]').clear(by_js=True)
tab.ele('x://input[@ng-model="proxyEditors[scheme].port"]').input(port, clear=True)
tab.ele('x://a[@ng-click="applyOptions()"]').click()
|
最后改完之后确实可以跑了,似乎互联网上没有相关问题产生,绕了很多弯路。其实主要还是解决的是代理的问题。
因为cloudflare对机房ip似乎有风控,机房ip点击时,无法成功。最后就完成了无头模式使用drissionpage越过cf。