官网:https://drissionpage.cn/

文档:https://drissionpage.cn/get_start/installation

基本使用

1
2
3
4
5
6
7
8
9
10
11
from DrissionPage import ChromiumPage, ChromiumOptions

co = ChromiumOptions().auto_port(True) # 自动分配端口和缓存,每次都启动一个新浏览器
co = co.set_argument("--start-maximized") # 最大化
co = co.set_browser_path("C:\\Program Files (x86)\\Google\\Chrome\\chrome.exe") # 指定chrome
user_data_dir = f"C:\\code\\wanxiang_login\\user_data\\{data_dir}"
co = co.set_user_data_path(user_data_dir) # 使用缓存

page = ChromiumPage(co)
page.get(url)
content = page.html

设置ck,不能含有逗号

1
2
cookies = "Z7XZP0H=GS1.1.1711853565.1.1.1711853728.39.0.0; path=/; domain=.shopee.sg;"
page.set.cookies(cookies)

获取ck

1
ck_dct = page.cookies().as_dict()

元素定位

1
2
3
4
page.ele("@aria-label=滑块")  # 属性定位
for c in password:
page.ele("#fm-login-password").input(c) # CSS选择器定位
time.sleep(0.1)

使用缓存

1
2
3
4
data_dir = hashlib.md5(account.encode()).hexdigest()
user_data_dir = f"C:\\code\\wanxiang_login\\user_data\\{data_dir}"
print("使用缓存", user_data_dir)
co = co.set_user_data_path(user_data_dir)

设置代理

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
def create_proxy_auth_extension(self, proxy_host, proxy_port, proxy_username, proxy_password, scheme='http',
plugin_path=r'tmp/proxy_auth_plugin'):
"""
创建Chromium代理插件, 支持账密认证
:param proxy_host: 代理IP
:param proxy_port: 代理端口
:param proxy_username: 代理账号
:param proxy_password: <PASSWORD>
:param scheme: 协议, 默认http
:param plugin_path: 插件目录, 默认tmp/proxy_auth_plugin
:return: 插件目录
"""
# 创建Chrome插件的manifest.json文件内容
manifest_json = '{"version":"1.0.0","manifest_version": 2,"name":"Chrome Proxy","permissions": ["proxy","tabs","unlimitedStorage","storage","<all_urls>","webRequest","webRequestBlocking"],"background": {"scripts": ["background.js"]}}'
# 创建Chrome插件的background.js文件内容
background_js = """
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: """ + f'"{proxy_host}"' + """,
port: """ + proxy_port + """,
}
}
}
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {username: """ + f'"{proxy_username}"' + """,
password: """ + f'"{proxy_password}"' + """,
}
}
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
)
"""
# 创建插件目录并写入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)
1
2
ext = create_proxy_auth_extension(ip, port)
co = co.add_extension(ext)

iframe自动定位

需要主链接iframe链接域名一致,跨域的定位不到

鼠标滑动

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
from python_ghost_cursor import path as slide_path


slider = page.ele("@aria-label=滑块")
if slider:
slider = page.ele("@aria-label=滑块")
page.actions.move_to(slider)
page.actions.hold(slider)
slide_len = 440
start = {
"x": 0,
"y": 0,
}
end = {
"x": slide_len,
"y": 0,
}
x = 0
for tu in slide_path(start, end):
move_x = tu["x"] - x
x = tu["x"]
page.actions.move(move_x, duration=random.uniform(0.08, 0.1))
page.actions.release(slider)
refresh_ele = page.ele("@id=`nc_1_refresh2`")
if not refresh_ele:
print("滑动通过")
break
else:
print(f"滑动失败,进行重试")
refresh_ele.click()
time.sleep(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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def get_mouse_array(distance):
# 从网页截取并录入鼠标轨迹
origin_mouse_array = [
[0, 0, 0],
[1, 0, 68],
[2, 0, 6],
[4, 0, 8],
[8, 0, 9],
[12, 0, 8],
[16, 0, 8],
[22, 0, 8],
[29, 0, 8],
[37, 0, 8],
[45, 0, 8],
[53, 0, 8],
[60, 0, 8],
[67, 0, 8],
[74, 0, 8],
[79, 0, 8],
[84, -1, 8],
[90, -1, 8],
[94, -1, 8],
[98, -2, 8],
[102, -2, 8],
[104, -2, 8],
[107, -2, 8],
[110, -2, 8],
[114, -2, 8],
[116, -2, 8],
[118, -2, 8],
[122, -2, 8],
[124, -2, 8],
[126, -2, 8],
[128, -2, 8],
[130, -2, 8],
[133, -2, 8],
[135, -2, 8],
[137, -2, 7],
[140, -2, 8],
[142, -2, 9],
[144, -2, 8],
[147, -2, 8],
[149, -2, 8],
[152, -2, 8],
[154, -2, 7],
[156, -2, 8],
[158, -2, 9],
[160, -2, 8],
[164, -2, 7],
[166, -2, 8],
[168, -2, 9],
[170, -2, 8],
[173, -2, 8],
[175, -2, 8],
[177, -2, 8],
[179, -2, 8],
[181, -2, 8],
[184, -2, 8],
[186, -2, 8],
[188, -2, 8],
[191, -2, 8],
[193, -2, 8],
[195, -2, 8],
[197, -2, 8],
[199, -2, 8],
[202, -2, 8],
[204, -2, 8],
[206, -2, 8],
[207, -2, 8],
[208, -2, 8],
[210, -2, 8],
[212, -2, 7],
[213, -2, 8],
[214, -2, 8],
[215, -2, 8],
[216, -2, 9],
[217, -2, 16],
[218, -2, 8],
[219, -2, 8],
[220, -2, 8],
[220, -2, 8],
[221, -2, 8],
[222, -2, 8],
[222, -2, 8],
[223, -2, 8],
[224, -2, 8],
[224, -2, 8],
[225, -2, 8],
[226, -2, 16],
[226, -2, 8],
[227, -2, 8],
[228, -2, 8],
[229, -2, 8],
[230, -2, 8],
[230, -2, 8],
[231, -2, 8],
[232, -2, 8],
[233, -2, 8],
[234, -2, 8],
[234, -2, 8],
[235, -2, 42],
[236, -2, 17],
[236, -3, 4],
[236, -3, 9],
[237, -3, 8],
[238, -4, 16],
[238, -4, 16],
]
result = []
num = -2
while len(result) < 80:
_max = random.randint(1, 10)
for _ in range(1, _max):
result.append(num)
num -= 1
result = result[:80]
print("生成的随机Y轴序列", result, len(result))
i = -1
for n in result[::-1]:
origin_mouse_array[i][1] = n
i -= 1

mouse_array = []
origin_distance = origin_mouse_array[-1][0]
per = distance / origin_distance
for i in origin_mouse_array:
new_x = round(i[0] * per)
new_y = round(i[1] * per)
new_t = round(i[2] * per)
mouse_array.append([new_x, new_y, new_t])
print("缩放后的滑动轨迹", mouse_array)
return mouse_array


slide_len = 440
ori_x, ori_y = 0, 0
for tu in get_mouse_array(slide_len):
x, y, z = tu
off_x = x - ori_x
ori_x = x
off_y = y - ori_y
ori_y = y
page.actions.move(offset_x=off_x, offset_y=off_y, duration=0)
time.sleep(z / 1000)