qrpa 1.0.84__py3-none-any.whl → 1.0.85__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qrpa might be problematic. Click here for more details.
qrpa/shein_lib.py
CHANGED
|
@@ -27,37 +27,31 @@ class SheinLib:
|
|
|
27
27
|
|
|
28
28
|
self.deal_auth()
|
|
29
29
|
|
|
30
|
-
# 处理鉴权
|
|
30
|
+
# 处理鉴权
|
|
31
31
|
def deal_auth(self):
|
|
32
32
|
web_page = self.web_page
|
|
33
33
|
|
|
34
34
|
# 定义最大重试次数
|
|
35
|
-
MAX_RETRIES =
|
|
35
|
+
MAX_RETRIES = 5
|
|
36
36
|
retries = 0
|
|
37
37
|
wait_count = 0
|
|
38
38
|
is_send = False
|
|
39
39
|
|
|
40
|
+
# close_modal(web_page) # 不能开启 需要勾选协议弹窗
|
|
41
|
+
|
|
40
42
|
while retries < MAX_RETRIES:
|
|
41
43
|
try:
|
|
42
|
-
# 检查页面是否已崩溃,如果是则重新创建页面
|
|
43
|
-
if self.is_page_crashed():
|
|
44
|
-
self.recreate_page()
|
|
45
|
-
web_page = self.web_page
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
self.wait_for_page_stable()
|
|
45
|
+
retries += 1
|
|
49
46
|
|
|
50
47
|
while not web_page.locator('//div[contains(text(),"商家后台")]').nth(1).is_visible():
|
|
51
48
|
|
|
52
|
-
# 处理鉴权确定按钮
|
|
53
49
|
if web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).is_visible():
|
|
54
50
|
if 'https://sso.geiwohuo.com/#/home' not in web_page.url:
|
|
55
51
|
log("鉴权确定按钮可见 点击'确定'按钮", web_page.title(), web_page.url, self.store_username, self.store_name)
|
|
56
52
|
web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).click()
|
|
57
|
-
|
|
58
|
-
self.wait_for_navigation()
|
|
53
|
+
web_page.wait_for_timeout(5000)
|
|
59
54
|
|
|
60
|
-
# 处理验证码
|
|
61
55
|
while web_page.locator('//div[text()="验证码"]').is_visible():
|
|
62
56
|
log(f'等待输入验证码: {wait_count}', self.store_username, self.store_name)
|
|
63
57
|
if not is_send:
|
|
@@ -68,223 +62,112 @@ class SheinLib:
|
|
|
68
62
|
time.sleep(5)
|
|
69
63
|
wait_count += 1
|
|
70
64
|
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
if web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
|
|
66
|
+
while web_page.locator('//div[contains(text(),"同意签署协议")]').count() == 0:
|
|
67
|
+
log('等待协议内容出现')
|
|
68
|
+
web_page.wait_for_timeout(1000)
|
|
69
|
+
|
|
70
|
+
if web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
|
|
71
|
+
log('检测到同意签署协议')
|
|
72
|
+
web_page.wait_for_timeout(1000)
|
|
73
|
+
log('点击同意复选框')
|
|
74
|
+
web_page.locator('//i[@class="so-checkinput-indicator so-checkinput-checkbox"]').click()
|
|
75
|
+
web_page.wait_for_timeout(1000)
|
|
76
|
+
log('点击同意按钮')
|
|
77
|
+
web_page.locator('//button[span[text()="同意"]]').click()
|
|
73
78
|
|
|
74
|
-
# 处理登录按钮
|
|
75
79
|
if web_page.locator('//input[@name="username"]').is_visible():
|
|
76
80
|
log("用户名输入框可见 等待5秒点击'登录'按钮", self.store_username, self.store_name)
|
|
77
81
|
web_page.wait_for_timeout(5000)
|
|
78
82
|
log('点击"登录"', self.store_username, self.store_name)
|
|
79
83
|
web_page.locator('//button[contains(@class,"login_btn")]').click()
|
|
80
|
-
# 等待登录完成
|
|
81
|
-
self.wait_for_navigation()
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
log('再延时5秒', self.store_username, self.store_name)
|
|
86
|
+
web_page.wait_for_timeout(5000)
|
|
87
|
+
|
|
84
88
|
if web_page.locator('//span[contains(text(),"商品管理")]').nth(1).is_visible():
|
|
85
89
|
log('商品管理菜单可见 退出鉴权处理', self.store_username, self.store_name)
|
|
86
90
|
return
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
log('商家后台不可见', web_page.title(), web_page.url, self.store_username, self.store_name)
|
|
93
|
+
if 'https://sso.geiwohuo.com/#/home' in web_page.url:
|
|
94
|
+
web_page.wait_for_timeout(5000)
|
|
95
|
+
web_page.reload()
|
|
96
|
+
|
|
97
|
+
# while r'=/CN' in web_page.url:
|
|
98
|
+
# safe_goto(web_page, 'https://sso.geiwohuo.com/#/home?q=0')
|
|
99
|
+
#
|
|
100
|
+
# web_page.wait_for_timeout(5000)
|
|
101
|
+
# if web_page.locator('//input[@name="username"]').is_visible():
|
|
102
|
+
# log("用户名输入框可见 等待5秒点击'登录'按钮", self.store_username, self.store_name)
|
|
103
|
+
# web_page.wait_for_timeout(5000)
|
|
104
|
+
# log('点击"登录"', self.store_username, self.store_name)
|
|
105
|
+
# web_page.locator('//button[contains(@class,"login_btn")]').click()
|
|
106
|
+
#
|
|
107
|
+
# log('再延时5秒', self.store_username, self.store_name)
|
|
108
|
+
# web_page.wait_for_timeout(5000)
|
|
90
109
|
|
|
91
110
|
web_page.wait_for_timeout(3000)
|
|
92
111
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
if 'https://sso.geiwohuo.com/#/home' in web_page.url:
|
|
113
|
+
|
|
114
|
+
if 'SHEIN全球商家中心' in web_page.title() or '后台首页' in web_page.title() or '商家后台' in web_page.title():
|
|
115
|
+
log(web_page.title(), '中断循环', self.store_username, self.store_name)
|
|
116
|
+
web_page.wait_for_timeout(5000)
|
|
117
|
+
break
|
|
118
|
+
|
|
119
|
+
if 'mrs.biz.sheincorp.cn' in web_page.url and '商家后台' in web_page.title():
|
|
120
|
+
try:
|
|
121
|
+
web_page.goto('https://sso.geiwohuo.com/#/home?q=1', wait_until='domcontentloaded', timeout=10000)
|
|
122
|
+
web_page.wait_for_timeout(3000)
|
|
123
|
+
except Exception as nav_error:
|
|
124
|
+
log(f"导航失败,尝试重新加载: {nav_error}", self.store_username, self.store_name)
|
|
125
|
+
web_page.reload(wait_until='domcontentloaded', timeout=10000)
|
|
126
|
+
web_page.wait_for_timeout(5000)
|
|
127
|
+
|
|
128
|
+
if web_page.locator('//h1[contains(text(),"鉴权")]').is_visible():
|
|
129
|
+
log('检测到鉴权 刷新页面', self.store_username, self.store_name)
|
|
130
|
+
web_page.reload()
|
|
131
|
+
web_page.wait_for_timeout(5000)
|
|
132
|
+
web_page.reload()
|
|
133
|
+
web_page.wait_for_timeout(5000)
|
|
96
134
|
|
|
97
|
-
|
|
135
|
+
if web_page.title() == 'SHEIN':
|
|
136
|
+
try:
|
|
137
|
+
web_page.goto('https://sso.geiwohuo.com/#/home?q=2', wait_until='domcontentloaded', timeout=10000)
|
|
138
|
+
web_page.wait_for_timeout(3000)
|
|
139
|
+
except Exception as nav_error:
|
|
140
|
+
log(f"导航失败,尝试重新加载: {nav_error}", self.store_username, self.store_name)
|
|
141
|
+
web_page.reload(wait_until='domcontentloaded', timeout=10000)
|
|
142
|
+
web_page.wait_for_timeout(5000)
|
|
98
143
|
|
|
144
|
+
break
|
|
99
145
|
except Exception as e:
|
|
100
146
|
log(f"错误发生: {e}, 重试中...({self.store_username}, {self.store_name})")
|
|
101
147
|
log(traceback.format_exc())
|
|
102
|
-
|
|
103
|
-
# 特殊处理页面崩溃错误
|
|
104
148
|
if 'crashed' in str(e):
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
149
|
+
try:
|
|
150
|
+
if 'https://sso.geiwohuo.com//#/auth/SSLS' in web_page.url:
|
|
151
|
+
log("检测到页面崩溃,尝试恢复到首页", self.store_username, self.store_name)
|
|
152
|
+
web_page.wait_for_load_state("networkidle", timeout=5000)
|
|
153
|
+
web_page.goto('https://sso.geiwohuo.com/#/home', wait_until='domcontentloaded', timeout=10000)
|
|
154
|
+
else:
|
|
155
|
+
log("页面崩溃,尝试重新加载当前页面", self.store_username, self.store_name)
|
|
156
|
+
web_page.reload(wait_until='domcontentloaded', timeout=10000)
|
|
157
|
+
web_page.wait_for_timeout(3000)
|
|
158
|
+
except Exception as recovery_error:
|
|
159
|
+
log(f"页面恢复失败: {recovery_error}", self.store_username, self.store_name)
|
|
160
|
+
web_page.wait_for_timeout(5000)
|
|
108
161
|
retries += 1
|
|
109
162
|
if retries >= MAX_RETRIES:
|
|
110
163
|
log(f"达到最大重试次数,停止尝试({self.store_username}, {self.store_name})")
|
|
111
|
-
|
|
164
|
+
break
|
|
165
|
+
time.sleep(2) # 错误时等待2秒后重试
|
|
112
166
|
|
|
113
|
-
# 指数退避等待
|
|
114
|
-
time.sleep(2 ** retries)
|
|
115
|
-
|
|
116
|
-
# 辅助方法
|
|
117
|
-
def is_page_crashed(self):
|
|
118
|
-
"""检查页面是否已崩溃"""
|
|
119
|
-
try:
|
|
120
|
-
# 尝试访问页面基本属性
|
|
121
|
-
self.web_page.url
|
|
122
|
-
self.web_page.title()
|
|
123
|
-
return False
|
|
124
|
-
except Exception as e:
|
|
125
|
-
if 'crashed' in str(e):
|
|
126
|
-
return True
|
|
127
|
-
return False
|
|
128
|
-
|
|
129
|
-
def recreate_page(self):
|
|
130
|
-
"""重新创建页面实例"""
|
|
131
|
-
try:
|
|
132
|
-
# 关闭当前页面
|
|
133
|
-
if hasattr(self, 'web_page') and self.web_page:
|
|
134
|
-
try:
|
|
135
|
-
self.web_page.close()
|
|
136
|
-
except:
|
|
137
|
-
pass
|
|
138
|
-
|
|
139
|
-
# 重新创建页面
|
|
140
|
-
self.web_page = self.browser.new_page()
|
|
141
|
-
|
|
142
|
-
# 设置页面选项
|
|
143
|
-
self.web_page.set_default_timeout(30000) # 30秒超时
|
|
144
|
-
self.web_page.set_default_navigation_timeout(30000)
|
|
145
|
-
|
|
146
|
-
# 导航到目标页面
|
|
147
|
-
self.safe_goto('https://sso.geiwohuo.com/#/home')
|
|
148
|
-
|
|
149
|
-
except Exception as e:
|
|
150
|
-
log(f"重新创建页面失败: {e}")
|
|
151
|
-
raise
|
|
152
|
-
|
|
153
|
-
def wait_for_page_stable(self, timeout=10000):
|
|
154
|
-
"""等待页面稳定加载"""
|
|
155
|
-
try:
|
|
156
|
-
# 等待网络空闲
|
|
157
|
-
self.web_page.wait_for_load_state('networkidle', timeout=timeout)
|
|
158
|
-
# 额外等待一下确保JavaScript执行完成
|
|
159
|
-
self.web_page.wait_for_timeout(2000)
|
|
160
|
-
except Exception as e:
|
|
161
|
-
log(f"等待页面稳定超时: {e}")
|
|
162
|
-
|
|
163
|
-
def wait_for_navigation(self, timeout=30000):
|
|
164
|
-
"""等待导航完成"""
|
|
165
|
-
try:
|
|
166
|
-
self.web_page.wait_for_load_state('networkidle', timeout=timeout)
|
|
167
|
-
self.web_page.wait_for_timeout(2000)
|
|
168
|
-
except Exception as e:
|
|
169
|
-
log(f"等待导航完成超时: {e}")
|
|
170
|
-
|
|
171
|
-
def safe_goto(self, url, retries=3):
|
|
172
|
-
"""安全的页面导航"""
|
|
173
|
-
for i in range(retries):
|
|
174
|
-
try:
|
|
175
|
-
# 设置较长的超时时间处理302重定向
|
|
176
|
-
response = self.web_page.goto(url, wait_until='networkidle', timeout=60000)
|
|
177
|
-
|
|
178
|
-
# 检查响应状态
|
|
179
|
-
if response and response.status >= 400:
|
|
180
|
-
log(f"页面返回错误状态: {response.status}")
|
|
181
|
-
if i < retries - 1:
|
|
182
|
-
time.sleep(2)
|
|
183
|
-
continue
|
|
184
|
-
|
|
185
|
-
# 等待页面稳定
|
|
186
|
-
self.wait_for_page_stable()
|
|
187
|
-
return
|
|
188
|
-
|
|
189
|
-
except Exception as e:
|
|
190
|
-
log(f"导航到 {url} 失败 (尝试 {i + 1}/{retries}): {e}")
|
|
191
|
-
if 'crashed' in str(e):
|
|
192
|
-
# 页面崩溃,需要重新创建
|
|
193
|
-
if i < retries - 1:
|
|
194
|
-
self.recreate_page()
|
|
195
|
-
continue
|
|
196
|
-
else:
|
|
197
|
-
raise
|
|
198
|
-
|
|
199
|
-
if i < retries - 1:
|
|
200
|
-
time.sleep(2 ** i) # 指数退避
|
|
201
|
-
continue
|
|
202
|
-
raise
|
|
203
|
-
|
|
204
|
-
def handle_agreement(self):
|
|
205
|
-
"""处理协议签署"""
|
|
206
|
-
if self.web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
|
|
207
|
-
# 等待协议内容完全加载
|
|
208
|
-
self.web_page.wait_for_selector('//div[contains(text(),"同意签署协议")]', timeout=10000)
|
|
209
|
-
log('检测到同意签署协议')
|
|
210
|
-
self.web_page.wait_for_timeout(1000)
|
|
211
|
-
log('点击同意复选框')
|
|
212
|
-
self.web_page.locator('//i[@class="so-checkinput-indicator so-checkinput-checkbox"]').click()
|
|
213
|
-
self.web_page.wait_for_timeout(1000)
|
|
214
|
-
log('点击同意按钮')
|
|
215
|
-
self.web_page.locator('//button[span[text()="同意"]]').click()
|
|
216
|
-
# 等待处理完成
|
|
217
|
-
self.wait_for_navigation()
|
|
218
|
-
|
|
219
|
-
def handle_page_states(self):
|
|
220
|
-
"""处理各种页面状态"""
|
|
221
|
-
current_url = self.web_page.url
|
|
222
|
-
current_title = self.web_page.title()
|
|
223
|
-
|
|
224
|
-
log(f'当前页面状态 - URL: {current_url}, Title: {current_title}', self.store_username, self.store_name)
|
|
225
|
-
|
|
226
|
-
if 'https://sso.geiwohuo.com/#/home' in current_url:
|
|
227
|
-
if current_title == 'SHEIN' or '后台首页' in current_title or '商家后台' in current_title:
|
|
228
|
-
log(f'{current_title} 页面加载完成', self.store_username, self.store_name)
|
|
229
|
-
self.web_page.wait_for_timeout(5000)
|
|
230
|
-
else:
|
|
231
|
-
# 页面可能还在加载,刷新一下
|
|
232
|
-
self.web_page.reload()
|
|
233
|
-
self.wait_for_page_stable()
|
|
234
|
-
|
|
235
|
-
elif 'mrs.biz.sheincorp.cn' in current_url and '商家后台' in current_title:
|
|
236
|
-
self.safe_goto('https://sso.geiwohuo.com/#/home?q=1')
|
|
237
|
-
|
|
238
|
-
elif self.web_page.locator('//h1[contains(text(),"鉴权")]').is_visible():
|
|
239
|
-
log('检测到鉴权页面,刷新页面', self.store_username, self.store_name)
|
|
240
|
-
self.web_page.reload()
|
|
241
|
-
self.wait_for_page_stable()
|
|
242
|
-
|
|
243
|
-
elif current_title == 'SHEIN' and 'sso.geiwohuo.com' not in current_url:
|
|
244
|
-
self.safe_goto('https://sso.geiwohuo.com/#/home?q=2')
|
|
245
|
-
|
|
246
|
-
def is_auth_successful(self):
|
|
247
|
-
"""检查鉴权是否成功"""
|
|
248
|
-
try:
|
|
249
|
-
current_url = self.web_page.url
|
|
250
|
-
current_title = self.web_page.title()
|
|
251
|
-
|
|
252
|
-
success_conditions = [
|
|
253
|
-
'SHEIN全球商家中心' in current_title,
|
|
254
|
-
'后台首页' in current_title,
|
|
255
|
-
'商家后台' in current_title,
|
|
256
|
-
self.web_page.locator('//span[contains(text(),"商品管理")]').nth(1).is_visible()
|
|
257
|
-
]
|
|
258
|
-
|
|
259
|
-
return any(success_conditions)
|
|
260
|
-
except:
|
|
261
|
-
return False
|
|
262
|
-
|
|
263
|
-
def handle_page_crash(self):
|
|
264
|
-
"""处理页面崩溃"""
|
|
265
|
-
try:
|
|
266
|
-
log("处理页面崩溃...")
|
|
267
|
-
|
|
268
|
-
# 如果是特定URL的崩溃,直接导航到安全页面
|
|
269
|
-
if hasattr(self, 'web_page'):
|
|
270
|
-
try:
|
|
271
|
-
current_url = self.web_page.url
|
|
272
|
-
if 'https://sso.geiwohuo.com//#/auth/SSLS' in current_url:
|
|
273
|
-
self.safe_goto('https://sso.geiwohuo.com/#/home?q=3')
|
|
274
|
-
return
|
|
275
|
-
except:
|
|
276
|
-
pass
|
|
277
|
-
|
|
278
|
-
# 重新创建页面
|
|
279
|
-
self.recreate_page()
|
|
280
|
-
|
|
281
|
-
except Exception as e:
|
|
282
|
-
log(f"处理页面崩溃失败: {e}")
|
|
283
|
-
raise
|
|
284
167
|
log('鉴权处理结束')
|
|
285
168
|
# web_page.wait_for_load_state("load")
|
|
286
169
|
# web_page.wait_for_load_state("networkidle")
|
|
287
|
-
|
|
170
|
+
web_page.wait_for_timeout(3000)
|
|
288
171
|
|
|
289
172
|
# 获取质检报告pdf地址
|
|
290
173
|
def get_qc_report_url(self, deliverCode, purchaseCode):
|
|
@@ -11,7 +11,7 @@ qrpa/fun_web.py,sha256=Ep2ddMwJix_KNpCiHEjSo7tWu-g55Nlu1QtOXJf6iZw,6531
|
|
|
11
11
|
qrpa/fun_win.py,sha256=-LnTeocdTt72NVH6VgLdpAT9_C5oV9okeudXG6CftMA,8034
|
|
12
12
|
qrpa/shein_daily_report_model.py,sha256=H8oZmIN5Pyqe306W1_xuz87lOqLQ_LI5RjXbaxDkIzE,12589
|
|
13
13
|
qrpa/shein_excel.py,sha256=1F9QMMsaihDfwr0ajSSQdXksBCjuKSPwMynfP7Jlkso,124825
|
|
14
|
-
qrpa/shein_lib.py,sha256=
|
|
14
|
+
qrpa/shein_lib.py,sha256=PxgiyvApZ9KWNqppsFwXEQDov1nyZqJ7bkTgcX9aePo,128927
|
|
15
15
|
qrpa/shein_mysql.py,sha256=Sgz6U0_3f4cT5zPf1Ht1OjvSFhrVPLkMxt91NV-ZPCM,3005
|
|
16
16
|
qrpa/shein_sqlite.py,sha256=ZQwD0Gz81q9WY7tY2HMEYvSF9r3N_G_Aur3bYfST9WY,5707
|
|
17
17
|
qrpa/shein_ziniao.py,sha256=3PvoRK-J81q5vhNXdhJ_OODExXPrPfJzTgYBH1S4rxM,18703
|
|
@@ -24,7 +24,7 @@ qrpa/wxwork.py,sha256=gIytG19DZ5g7Tsl0-W3EbjfSnpIqZw-ua24gcB78YEg,11264
|
|
|
24
24
|
qrpa/mysql_module/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
qrpa/mysql_module/shein_product_model.py,sha256=qViI_Ik3SkXXxqJ1nXjimvfB_a5uiwW9RXL0fOreBao,18880
|
|
26
26
|
qrpa/mysql_module/shein_return_order_model.py,sha256=Zt-bGOH_kCDbakW7uaTmqqo_qTT8v424yidcYSfWvWM,26562
|
|
27
|
-
qrpa-1.0.
|
|
28
|
-
qrpa-1.0.
|
|
29
|
-
qrpa-1.0.
|
|
30
|
-
qrpa-1.0.
|
|
27
|
+
qrpa-1.0.85.dist-info/METADATA,sha256=8sOzDXztR9sIfTkuNHMzufR79HTXiukIHc6RuLrOpqw,231
|
|
28
|
+
qrpa-1.0.85.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
qrpa-1.0.85.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
|
|
30
|
+
qrpa-1.0.85.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|