qrpa 1.0.50__py3-none-any.whl → 1.0.52__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.
- qrpa/fun_base.py +6 -9
- qrpa/shein_lib.py +35 -202
- qrpa/shein_ziniao.py +10 -4
- {qrpa-1.0.50.dist-info → qrpa-1.0.52.dist-info}/METADATA +1 -1
- {qrpa-1.0.50.dist-info → qrpa-1.0.52.dist-info}/RECORD +7 -7
- {qrpa-1.0.50.dist-info → qrpa-1.0.52.dist-info}/WHEEL +0 -0
- {qrpa-1.0.50.dist-info → qrpa-1.0.52.dist-info}/top_level.txt +0 -0
qrpa/fun_base.py
CHANGED
|
@@ -13,6 +13,11 @@ from .RateLimitedSender import RateLimitedSender
|
|
|
13
13
|
|
|
14
14
|
from typing import TypedDict
|
|
15
15
|
|
|
16
|
+
# 自定义错误类型,继承自 Exception
|
|
17
|
+
class NetWorkIdleTimeout(Exception):
|
|
18
|
+
"""这是一个自定义错误类型"""
|
|
19
|
+
pass
|
|
20
|
+
|
|
16
21
|
# 定义一个 TypedDict 来提供配置结构的类型提示
|
|
17
22
|
|
|
18
23
|
class ZiNiao(TypedDict):
|
|
@@ -161,7 +166,6 @@ def remove_columns(matrix, indices):
|
|
|
161
166
|
# 遍历每行,只保留不在indices中的列
|
|
162
167
|
return [[row[i] for i in indices_to_keep] for row in matrix]
|
|
163
168
|
|
|
164
|
-
|
|
165
169
|
def filter_columns(matrix, indices):
|
|
166
170
|
"""
|
|
167
171
|
过滤二维列表,只保留指定索引的列
|
|
@@ -182,7 +186,6 @@ def filter_columns(matrix, indices):
|
|
|
182
186
|
# 将过滤后的列转回二维列表
|
|
183
187
|
return [list(row) for row in zip(*filtered_columns)]
|
|
184
188
|
|
|
185
|
-
|
|
186
189
|
# # 示例使用
|
|
187
190
|
# matrix = [
|
|
188
191
|
# [1, 2, 3, 4],
|
|
@@ -216,7 +219,6 @@ def add_column_to_2d_list(data, new_col, index=None):
|
|
|
216
219
|
new_data.append(row)
|
|
217
220
|
return new_data
|
|
218
221
|
|
|
219
|
-
|
|
220
222
|
def add_prefixed_column(data, header, value):
|
|
221
223
|
"""
|
|
222
224
|
给二维列表增加第一列,第一行为 header,后面为 value。
|
|
@@ -232,7 +234,6 @@ def add_prefixed_column(data, header, value):
|
|
|
232
234
|
new_col = [header] + [value] * (len(data) - 1)
|
|
233
235
|
return [[new_col[i]] + row for i, row in enumerate(data)]
|
|
234
236
|
|
|
235
|
-
|
|
236
237
|
def add_suffixed_column(data, header, value):
|
|
237
238
|
"""
|
|
238
239
|
给二维列表增加第一列,第一行为 header,后面为 value。
|
|
@@ -248,7 +249,6 @@ def add_suffixed_column(data, header, value):
|
|
|
248
249
|
new_col = [header] + [value] * (len(data) - 1)
|
|
249
250
|
return [row + [new_col[i]] for i, row in enumerate(data)]
|
|
250
251
|
|
|
251
|
-
|
|
252
252
|
def merge_2d_lists_keep_first_header(data1, data2):
|
|
253
253
|
"""
|
|
254
254
|
合并两个二维列表,只保留第一个列表的标题(即第一行)。
|
|
@@ -268,7 +268,6 @@ def merge_2d_lists_keep_first_header(data1, data2):
|
|
|
268
268
|
|
|
269
269
|
return [header] + rows1 + rows2
|
|
270
270
|
|
|
271
|
-
|
|
272
271
|
def insert_total_row(data, row_index=1, label="合计"):
|
|
273
272
|
"""
|
|
274
273
|
在指定行插入一行,第一列为 label,其余为空字符串。
|
|
@@ -286,7 +285,6 @@ def insert_total_row(data, row_index=1, label="合计"):
|
|
|
286
285
|
|
|
287
286
|
return data[:row_index] + [new_row] + data[row_index:]
|
|
288
287
|
|
|
289
|
-
|
|
290
288
|
def insert_empty_column_after(data, col_index, new_header="单价成本"):
|
|
291
289
|
"""
|
|
292
290
|
在二维列表中指定列的后面插入一个新列,标题为 new_header,其余内容为空字符串。
|
|
@@ -308,7 +306,6 @@ def insert_empty_column_after(data, col_index, new_header="单价成本"):
|
|
|
308
306
|
|
|
309
307
|
return new_data
|
|
310
308
|
|
|
311
|
-
|
|
312
309
|
def insert_empty_column_after_column_name(data, target_col_name, new_header="单价成本"):
|
|
313
310
|
"""
|
|
314
311
|
在指定列名对应的列后面插入一个新列,标题为 new_header,其余行为空字符串。
|
|
@@ -334,4 +331,4 @@ def insert_empty_column_after_column_name(data, target_col_name, new_header="单
|
|
|
334
331
|
row.insert(col_index + 1, insert_value)
|
|
335
332
|
new_data.append(row)
|
|
336
333
|
|
|
337
|
-
return new_data
|
|
334
|
+
return new_data
|
qrpa/shein_lib.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .fun_file import read_dict_from_file, write_dict_to_file, read_dict_from_file_ex, write_dict_to_file_ex
|
|
2
|
-
from .fun_base import log, send_exception, md5_string, get_safe_value
|
|
2
|
+
from .fun_base import log, send_exception, md5_string, get_safe_value, NetWorkIdleTimeout
|
|
3
3
|
from .fun_web import fetch, full_screen_shot
|
|
4
4
|
from .time_utils import TimeUtils
|
|
5
5
|
from .wxwork import WxWorkBot
|
|
@@ -8,7 +8,7 @@ from .shein_sqlite import insert_sales, get_last_week_sales, get_near_week_sales
|
|
|
8
8
|
|
|
9
9
|
import math
|
|
10
10
|
import time
|
|
11
|
-
import json
|
|
11
|
+
import json, traceback
|
|
12
12
|
from datetime import datetime
|
|
13
13
|
from playwright.sync_api import Page
|
|
14
14
|
|
|
@@ -27,179 +27,8 @@ class SheinLib:
|
|
|
27
27
|
|
|
28
28
|
self.deal_auth()
|
|
29
29
|
|
|
30
|
-
def deal_auth(self):
|
|
31
|
-
"""处理登录鉴权流程"""
|
|
32
|
-
web_page = self.web_page
|
|
33
|
-
|
|
34
|
-
# 配置常量
|
|
35
|
-
MAX_RETRIES = 5
|
|
36
|
-
CAPTCHA_WAIT_INTERVAL = 5
|
|
37
|
-
PAGE_LOAD_TIMEOUT = 5000
|
|
38
|
-
SHORT_TIMEOUT = 1000
|
|
39
|
-
|
|
40
|
-
# 页面元素选择器 - 集中管理
|
|
41
|
-
selectors = {
|
|
42
|
-
'merchant_backend' : '//div[contains(text(),"商家后台")]',
|
|
43
|
-
'auth_confirm_btn' : '//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]',
|
|
44
|
-
'captcha_text' : '//div[text()="验证码"]',
|
|
45
|
-
'username_input' : '//input[@name="username"]',
|
|
46
|
-
'login_btn' : '//button[contains(@class,"login_btn")]',
|
|
47
|
-
'product_management': '//span[contains(text(),"商品管理")]',
|
|
48
|
-
'auth_title' : '//h1[contains(text(),"鉴权")]'
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
# URL常量
|
|
52
|
-
home_url = 'https://sso.geiwohuo.com/#/home'
|
|
53
|
-
base_url = 'https://sso.geiwohuo.com'
|
|
54
|
-
|
|
55
|
-
retries = 0
|
|
56
|
-
wait_count = 0
|
|
57
|
-
is_captcha_notification_sent = False
|
|
58
|
-
|
|
59
|
-
log("开始鉴权处理", self.store_username, self.store_name)
|
|
60
|
-
|
|
61
|
-
while retries < MAX_RETRIES:
|
|
62
|
-
try:
|
|
63
|
-
retries += 1
|
|
64
|
-
log(f"鉴权处理第{retries}次尝试", self.store_username, self.store_name)
|
|
65
|
-
|
|
66
|
-
# 主循环:等待商家后台页面加载
|
|
67
|
-
while True:
|
|
68
|
-
try:
|
|
69
|
-
# 检查商家后台是否已经可见
|
|
70
|
-
if web_page.locator(selectors['merchant_backend']).nth(1).is_visible(timeout=SHORT_TIMEOUT):
|
|
71
|
-
log('商家后台已可见,鉴权处理完成', self.store_username, self.store_name)
|
|
72
|
-
return
|
|
73
|
-
except:
|
|
74
|
-
pass
|
|
75
|
-
|
|
76
|
-
# 1. 处理鉴权确认弹窗
|
|
77
|
-
try:
|
|
78
|
-
auth_btn = web_page.locator(selectors['auth_confirm_btn']).nth(0)
|
|
79
|
-
if auth_btn.is_visible(timeout=SHORT_TIMEOUT):
|
|
80
|
-
log("检测到鉴权确认按钮,点击确定", self.store_username, self.store_name)
|
|
81
|
-
auth_btn.click()
|
|
82
|
-
web_page.wait_for_load_state("load")
|
|
83
|
-
web_page.wait_for_timeout(SHORT_TIMEOUT)
|
|
84
|
-
continue
|
|
85
|
-
except:
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
# 2. 处理验证码等待
|
|
89
|
-
try:
|
|
90
|
-
if web_page.locator(selectors['captcha_text']).is_visible(timeout=SHORT_TIMEOUT):
|
|
91
|
-
wait_count += 1
|
|
92
|
-
log(f'等待验证码输入: 第{wait_count}次', self.store_username, self.store_name)
|
|
93
|
-
|
|
94
|
-
# 只发送一次验证码通知
|
|
95
|
-
if not is_captcha_notification_sent:
|
|
96
|
-
try:
|
|
97
|
-
img_path = full_screen_shot(web_page, self.config)
|
|
98
|
-
wx_bot = WxWorkBot(self.config.wxwork_bot_exception)
|
|
99
|
-
wx_bot.send_img(img_path)
|
|
100
|
-
wx_bot.send_text(f'{self.store_username},{self.store_name} 需要登录验证码')
|
|
101
|
-
is_captcha_notification_sent = True
|
|
102
|
-
log("验证码通知已发送", self.store_username, self.store_name)
|
|
103
|
-
except Exception as notify_error:
|
|
104
|
-
log(f"发送验证码通知失败: {notify_error}", self.store_username, self.store_name)
|
|
105
|
-
|
|
106
|
-
time.sleep(CAPTCHA_WAIT_INTERVAL)
|
|
107
|
-
continue
|
|
108
|
-
except:
|
|
109
|
-
pass
|
|
110
|
-
|
|
111
|
-
# 3. 处理登录按钮点击
|
|
112
|
-
try:
|
|
113
|
-
if web_page.locator(selectors['username_input']).is_visible(timeout=SHORT_TIMEOUT):
|
|
114
|
-
log("检测到用户名输入框,准备点击登录按钮", self.store_username, self.store_name)
|
|
115
|
-
web_page.wait_for_timeout(PAGE_LOAD_TIMEOUT)
|
|
116
|
-
web_page.locator(selectors['login_btn']).click()
|
|
117
|
-
web_page.wait_for_load_state("load")
|
|
118
|
-
web_page.wait_for_timeout(PAGE_LOAD_TIMEOUT)
|
|
119
|
-
continue
|
|
120
|
-
except:
|
|
121
|
-
pass
|
|
122
|
-
|
|
123
|
-
# 4. 检查商品管理菜单(成功标识)
|
|
124
|
-
try:
|
|
125
|
-
if web_page.locator(selectors['product_management']).nth(1).is_visible(timeout=SHORT_TIMEOUT):
|
|
126
|
-
log('检测到商品管理菜单,鉴权处理成功', self.store_username, self.store_name)
|
|
127
|
-
return
|
|
128
|
-
except:
|
|
129
|
-
pass
|
|
130
|
-
|
|
131
|
-
# 5. 获取当前页面信息用于状态判断
|
|
132
|
-
current_title = web_page.title()
|
|
133
|
-
current_url = web_page.url
|
|
134
|
-
|
|
135
|
-
log(f'当前页面状态: {current_title} | {current_url}', self.store_username, self.store_name)
|
|
136
|
-
|
|
137
|
-
# 6. 处理已知的成功状态页面
|
|
138
|
-
success_titles = ['SHEIN全球商家中心', '后台首页', '商家后台']
|
|
139
|
-
if any(title in current_title for title in success_titles) and home_url in current_url:
|
|
140
|
-
log(f'检测到目标页面: {current_title},跳出循环', self.store_username, self.store_name)
|
|
141
|
-
break
|
|
142
|
-
|
|
143
|
-
# 7. 处理需要重定向的页面
|
|
144
|
-
if 'mrs.biz.sheincorp.cn' in current_url and '商家后台' in current_title:
|
|
145
|
-
log('检测到旧后台地址,重定向到新地址', self.store_username, self.store_name)
|
|
146
|
-
web_page.goto(home_url)
|
|
147
|
-
web_page.wait_for_load_state("load")
|
|
148
|
-
web_page.wait_for_timeout(3000)
|
|
149
|
-
continue
|
|
150
|
-
|
|
151
|
-
# 8. 处理鉴权页面
|
|
152
|
-
try:
|
|
153
|
-
if web_page.locator(selectors['auth_title']).is_visible(timeout=SHORT_TIMEOUT):
|
|
154
|
-
log('检测到鉴权页面,刷新重试', self.store_username, self.store_name)
|
|
155
|
-
web_page.reload()
|
|
156
|
-
web_page.wait_for_load_state('load')
|
|
157
|
-
web_page.wait_for_timeout(3000)
|
|
158
|
-
continue
|
|
159
|
-
except:
|
|
160
|
-
pass
|
|
161
|
-
|
|
162
|
-
# 9. 处理SHEIN主页
|
|
163
|
-
if current_title == 'SHEIN':
|
|
164
|
-
log('当前在SHEIN主页,跳转到商家后台', self.store_username, self.store_name)
|
|
165
|
-
web_page.goto(home_url)
|
|
166
|
-
web_page.wait_for_load_state("load")
|
|
167
|
-
web_page.wait_for_timeout(3000)
|
|
168
|
-
continue
|
|
169
|
-
|
|
170
|
-
# 默认等待,然后继续下一轮检查
|
|
171
|
-
web_page.wait_for_load_state("load")
|
|
172
|
-
web_page.wait_for_timeout(SHORT_TIMEOUT)
|
|
173
|
-
|
|
174
|
-
# 如果跳出了内层while循环,说明达到了某种成功状态
|
|
175
|
-
log('内层循环结束,鉴权处理完成', self.store_username, self.store_name)
|
|
176
|
-
return
|
|
177
|
-
|
|
178
|
-
except Exception as e:
|
|
179
|
-
error_msg = str(e)
|
|
180
|
-
log(f"鉴权处理异常: {error_msg}, 第{retries}次重试", self.store_username, self.store_name)
|
|
181
|
-
|
|
182
|
-
# 处理页面崩溃或特定认证错误
|
|
183
|
-
if 'crashed' in error_msg.lower() or 'https://sso.geiwohuo.com//#/auth/SSLS' in web_page.url:
|
|
184
|
-
log('检测到页面崩溃或认证错误,重新导航到基础URL', self.store_username, self.store_name)
|
|
185
|
-
try:
|
|
186
|
-
web_page.goto(base_url)
|
|
187
|
-
web_page.wait_for_load_state('load')
|
|
188
|
-
web_page.wait_for_timeout(3000)
|
|
189
|
-
except Exception as nav_error:
|
|
190
|
-
log(f'重新导航失败: {nav_error}', self.store_username, self.store_name)
|
|
191
|
-
|
|
192
|
-
# 达到最大重试次数
|
|
193
|
-
if retries >= MAX_RETRIES:
|
|
194
|
-
log(f"达到最大重试次数{MAX_RETRIES},鉴权处理失败", self.store_username, self.store_name)
|
|
195
|
-
break
|
|
196
|
-
|
|
197
|
-
time.sleep(2) # 异常后等待2秒再重试
|
|
198
|
-
|
|
199
|
-
log('鉴权处理结束', self.store_username, self.store_name)
|
|
200
|
-
|
|
201
30
|
# 处理鉴权
|
|
202
|
-
def
|
|
31
|
+
def deal_auth(self):
|
|
203
32
|
web_page = self.web_page
|
|
204
33
|
|
|
205
34
|
# 定义最大重试次数
|
|
@@ -218,10 +47,11 @@ class SheinLib:
|
|
|
218
47
|
while not web_page.locator('//div[contains(text(),"商家后台")]').nth(1).is_visible():
|
|
219
48
|
|
|
220
49
|
if web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).is_visible():
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
50
|
+
if 'https://sso.geiwohuo.com/#/home' not in web_page.url:
|
|
51
|
+
log("鉴权确定按钮可见 点击'确定'按钮", self.store_username, self.store_name)
|
|
52
|
+
web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).click()
|
|
53
|
+
web_page.wait_for_load_state("load")
|
|
54
|
+
web_page.wait_for_timeout(1000)
|
|
225
55
|
|
|
226
56
|
while web_page.locator('//div[text()="验证码"]').is_visible():
|
|
227
57
|
log(f'等待输入验证码: {wait_count}', self.store_username, self.store_name)
|
|
@@ -238,7 +68,7 @@ class SheinLib:
|
|
|
238
68
|
web_page.wait_for_timeout(5000)
|
|
239
69
|
log('点击"登录"', self.store_username, self.store_name)
|
|
240
70
|
web_page.locator('//button[contains(@class,"login_btn")]').click()
|
|
241
|
-
|
|
71
|
+
|
|
242
72
|
log('再延时5秒', self.store_username, self.store_name)
|
|
243
73
|
web_page.wait_for_timeout(5000)
|
|
244
74
|
|
|
@@ -250,17 +80,13 @@ class SheinLib:
|
|
|
250
80
|
web_page.wait_for_load_state("load")
|
|
251
81
|
web_page.wait_for_timeout(1000)
|
|
252
82
|
|
|
253
|
-
if '
|
|
254
|
-
log('SHEIN全球商家中心 中断循环', self.store_username, self.store_name)
|
|
255
|
-
break
|
|
83
|
+
if 'https://sso.geiwohuo.com/#/home' in web_page.url:
|
|
256
84
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
log('后台首页 中断循环', self.store_username, self.store_name)
|
|
263
|
-
break
|
|
85
|
+
if 'SHEIN全球商家中心' in web_page.title() or '后台首页' in web_page.title() or '商家后台' in web_page.title():
|
|
86
|
+
log(web_page.title(), '中断循环', self.store_username, self.store_name)
|
|
87
|
+
web_page.wait_for_load_state("load")
|
|
88
|
+
web_page.wait_for_timeout(2000)
|
|
89
|
+
break
|
|
264
90
|
|
|
265
91
|
if 'mrs.biz.sheincorp.cn' in web_page.url and '商家后台' in web_page.title():
|
|
266
92
|
web_page.goto('https://sso.geiwohuo.com/#/home')
|
|
@@ -280,12 +106,14 @@ class SheinLib:
|
|
|
280
106
|
web_page.wait_for_load_state("load")
|
|
281
107
|
web_page.wait_for_timeout(3000)
|
|
282
108
|
|
|
109
|
+
break
|
|
283
110
|
except Exception as e:
|
|
284
111
|
log(f"错误发生: {e}, 重试中...({self.store_username}, {self.store_name})")
|
|
112
|
+
log(traceback.format_exc())
|
|
285
113
|
if 'crashed' in str(e) or 'https://sso.geiwohuo.com//#/auth/SSLS' in web_page.url:
|
|
286
114
|
web_page.goto('https://sso.geiwohuo.com')
|
|
287
115
|
web_page.wait_for_load_state('load')
|
|
288
|
-
web_page.wait_for_timeout(
|
|
116
|
+
web_page.wait_for_timeout(10000)
|
|
289
117
|
retries += 1
|
|
290
118
|
if retries >= MAX_RETRIES:
|
|
291
119
|
log(f"达到最大重试次数,停止尝试({self.store_username}, {self.store_name})")
|
|
@@ -293,6 +121,9 @@ class SheinLib:
|
|
|
293
121
|
time.sleep(2) # 错误时等待2秒后重试
|
|
294
122
|
|
|
295
123
|
log('鉴权处理结束')
|
|
124
|
+
# web_page.wait_for_load_state("load")
|
|
125
|
+
# web_page.wait_for_load_state("networkidle")
|
|
126
|
+
web_page.wait_for_timeout(3000)
|
|
296
127
|
|
|
297
128
|
# 获取质检报告pdf地址
|
|
298
129
|
def get_qc_report_url(self, deliverCode, purchaseCode):
|
|
@@ -400,27 +231,29 @@ class SheinLib:
|
|
|
400
231
|
has_valid_package = item.get('hasPackage') == 1
|
|
401
232
|
is_valid_yesterday = TimeUtils.is_yesterday(item['completeTime'], None) if item.get('completeTime') else False
|
|
402
233
|
returnOrderId = item['id']
|
|
403
|
-
return_box_detail =
|
|
234
|
+
item['return_box_detail'] = []
|
|
404
235
|
item['qc_report_url'] = ''
|
|
405
236
|
item['report_url'] = ''
|
|
406
237
|
item['store_username'] = self.store_username
|
|
407
238
|
item['store_name'] = self.store_name
|
|
408
239
|
item['store_manager'] = self.config.shein_store_manager.get(str(self.store_username).lower())
|
|
409
|
-
if has_valid_package
|
|
240
|
+
if has_valid_package:
|
|
241
|
+
return_box_detail = self.get_return_order_box_detail(returnOrderId)
|
|
242
|
+
if len(return_box_detail) > 0:
|
|
410
243
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
244
|
+
if int(item['returnScrapType']) == 1:
|
|
245
|
+
purchaseCode = item['sellerOrderNo']
|
|
246
|
+
delivery_code = item['sellerDeliveryNo']
|
|
247
|
+
item['qc_report_url'] = self.get_qc_report_url(delivery_code, purchaseCode)
|
|
415
248
|
|
|
416
|
-
|
|
417
|
-
|
|
249
|
+
if int(item['returnScrapType']) == 2:
|
|
250
|
+
item['report_url'] = self.get_inspect_report_url(returnOrderId)
|
|
418
251
|
|
|
419
|
-
|
|
252
|
+
item['return_box_detail'] = return_box_detail
|
|
420
253
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
254
|
+
all_list_item.append(item)
|
|
255
|
+
if is_valid_yesterday:
|
|
256
|
+
today_list_item.append(item)
|
|
424
257
|
|
|
425
258
|
cache_file = f'{self.config.auto_dir}/shein/cache/shein_return_order_list_{TimeUtils.today_date()}.json'
|
|
426
259
|
write_dict_to_file_ex(cache_file, {self.store_username: today_list_item}, [self.store_username])
|
qrpa/shein_ziniao.py
CHANGED
|
@@ -21,7 +21,7 @@ from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
|
|
|
21
21
|
from functools import partial
|
|
22
22
|
|
|
23
23
|
from .fun_win import find_software_install_path
|
|
24
|
-
from .fun_base import log, hostname, send_exception
|
|
24
|
+
from .fun_base import log, hostname, send_exception, NetWorkIdleTimeout
|
|
25
25
|
from .fun_file import check_progress_json_ex, get_progress_json_ex, done_progress_json_ex, write_dict_to_file_ex
|
|
26
26
|
|
|
27
27
|
class ZiniaoClient:
|
|
@@ -260,7 +260,6 @@ class ZiniaoBrowser:
|
|
|
260
260
|
page.goto(launcher_page)
|
|
261
261
|
page.wait_for_load_state('load')
|
|
262
262
|
|
|
263
|
-
# 业务逻辑
|
|
264
263
|
run_func(page, store_username, store_name, task_key)
|
|
265
264
|
|
|
266
265
|
# 标记完成
|
|
@@ -332,7 +331,14 @@ class ZiniaoTaskManager:
|
|
|
332
331
|
ip_usable = self.browser.open_ip_check(browser_context, ip_check_url)
|
|
333
332
|
if ip_usable:
|
|
334
333
|
print("ip检测通过,打开店铺平台主页")
|
|
335
|
-
|
|
334
|
+
# 业务逻辑
|
|
335
|
+
try:
|
|
336
|
+
self.browser.open_launcher_page(browser_context, ret_json.get("launcherPage"), store_username, store_name, run_func, task_key)
|
|
337
|
+
except NetWorkIdleTimeout:
|
|
338
|
+
log('捕获到自定义错误: NetWorkIdleTimeout')
|
|
339
|
+
self.browser.close_store(store_id)
|
|
340
|
+
pass
|
|
341
|
+
|
|
336
342
|
else:
|
|
337
343
|
print("ip检测不通过,请检查")
|
|
338
344
|
except:
|
|
@@ -412,7 +418,7 @@ class ZiniaoRunner:
|
|
|
412
418
|
raise RuntimeError("店铺列表为空")
|
|
413
419
|
|
|
414
420
|
# 多线程并发执行任务
|
|
415
|
-
max_threads =
|
|
421
|
+
max_threads = 1 if (hostname().lower() == 'krrpa') else 3
|
|
416
422
|
log(f'当前启用线程数: {max_threads}')
|
|
417
423
|
self.task_manager.run_with_thread_pool(browser_list, max_threads, run, task_key, just_store_username, is_skip_store)
|
|
418
424
|
|
|
@@ -4,17 +4,17 @@ qrpa/db_migrator.py,sha256=2VmhzcMsU0MKpl-mNCwKyV8tLTqyEysSpP27-S_rQZ8,21862
|
|
|
4
4
|
qrpa/feishu_bot_app.py,sha256=6r2YqCAMUN7y3F7onoABRmHC7S-UPOLHwbhsQnQ3IRc,9452
|
|
5
5
|
qrpa/feishu_client.py,sha256=gXvyhf7r-IqeDhPjM01SfsGf17t8g1ZwUAkhymBkBeg,17544
|
|
6
6
|
qrpa/feishu_logic.py,sha256=yuwb-LeZiHKGlz-W8JobinorHonVa8L-5h12WxnU7_Q,67508
|
|
7
|
-
qrpa/fun_base.py,sha256=
|
|
7
|
+
qrpa/fun_base.py,sha256=lMzqPwsbVfe968CUR2MVNImzIskIUZqPCE2tWxYqb5o,10728
|
|
8
8
|
qrpa/fun_excel.py,sha256=iDngd15qBX_HHZh_owftRa5ZArquTneY2JegRdNvk4U,115820
|
|
9
9
|
qrpa/fun_file.py,sha256=yzjDV16WL5vRys7J4uQcNzIFkX4D5MAlSCwxcD-mwQo,11966
|
|
10
10
|
qrpa/fun_web.py,sha256=F6cxwwOxB8twg2XK73oAvKla0FqpwDYJiM37CWmFwXo,6322
|
|
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=7dWDKP5JlD_2sb3Uv3JK_VJvppGwidsP3UAyPA89Ga8,115472
|
|
14
|
-
qrpa/shein_lib.py,sha256=
|
|
14
|
+
qrpa/shein_lib.py,sha256=0NYJ5UnbMbg0dg2Tffd0y7JVcpxxlTqCuFuK_VfskE8,108774
|
|
15
15
|
qrpa/shein_mysql.py,sha256=MGPJsz13evsLygZWhmitpPzUswiTKZ91VFvr8KA0M40,750
|
|
16
16
|
qrpa/shein_sqlite.py,sha256=ZQwD0Gz81q9WY7tY2HMEYvSF9r3N_G_Aur3bYfST9WY,5707
|
|
17
|
-
qrpa/shein_ziniao.py,sha256=
|
|
17
|
+
qrpa/shein_ziniao.py,sha256=kAOirjawPf-VxBxHFNpdDHCN2zL-O1U-2xybpmt34Xs,18692
|
|
18
18
|
qrpa/temu_chrome.py,sha256=CbtFy1QPan9xJdJcNZj-EsVGhUvv3ZTEPVDEA4-im40,2803
|
|
19
19
|
qrpa/temu_excel.py,sha256=ssAQvhtRGaTOLAVM3gS-AnmHPkIiHCT6gTsK1hoi-_8,6990
|
|
20
20
|
qrpa/temu_lib.py,sha256=hYB59zsLS3m3NTic_duTwPMOTSxlHyQVa8OhHnHm-1g,7199
|
|
@@ -23,7 +23,7 @@ qrpa/time_utils_example.py,sha256=shHOXKKF3QSzb0SHsNc34M61wEkkLuM30U9X1THKNS8,80
|
|
|
23
23
|
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_return_order_model.py,sha256=oKWr5Q-8LxKO7gLih26MUjD3GqC-C9eH8menVNGoRgw,26010
|
|
26
|
-
qrpa-1.0.
|
|
27
|
-
qrpa-1.0.
|
|
28
|
-
qrpa-1.0.
|
|
29
|
-
qrpa-1.0.
|
|
26
|
+
qrpa-1.0.52.dist-info/METADATA,sha256=M9uB3HpzHb91Ps54AyTfgDDvL2rseFYAGfgtgNm8d0o,231
|
|
27
|
+
qrpa-1.0.52.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
28
|
+
qrpa-1.0.52.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
|
|
29
|
+
qrpa-1.0.52.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|