qrpa 1.0.89__py3-none-any.whl → 1.0.90__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/db_migrator.py +1 -1
- qrpa/fun_web.py +48 -0
- qrpa/shein_lib.py +54 -16
- qrpa/shein_ziniao.py +73 -2
- qrpa/time_utils.py +17 -6
- {qrpa-1.0.89.dist-info → qrpa-1.0.90.dist-info}/METADATA +1 -1
- {qrpa-1.0.89.dist-info → qrpa-1.0.90.dist-info}/RECORD +9 -9
- {qrpa-1.0.89.dist-info → qrpa-1.0.90.dist-info}/WHEEL +0 -0
- {qrpa-1.0.89.dist-info → qrpa-1.0.90.dist-info}/top_level.txt +0 -0
qrpa/db_migrator.py
CHANGED
qrpa/fun_web.py
CHANGED
|
@@ -146,6 +146,54 @@ def full_screen_shot(web_page: Page, config):
|
|
|
146
146
|
web_page.screenshot(path=full_screenshot_image_path, full_page=True)
|
|
147
147
|
return full_screenshot_image_path
|
|
148
148
|
|
|
149
|
+
def fetch_get(page: Page, url: str, headers: Optional[dict] = None, config: Optional[dict] = None) -> dict:
|
|
150
|
+
"""
|
|
151
|
+
发送 HTTP GET 请求,支持自定义 headers 和配置。
|
|
152
|
+
|
|
153
|
+
:param page: Playwright 的 Page 对象
|
|
154
|
+
:param url: 请求地址
|
|
155
|
+
:param headers: 自定义 headers 字典
|
|
156
|
+
:param config: 请求配置字典,可包含 credentials, mode, referrer, referrerPolicy 等
|
|
157
|
+
:return: 服务器返回的 JSON 响应(dict)
|
|
158
|
+
"""
|
|
159
|
+
if headers is not None and not isinstance(headers, dict):
|
|
160
|
+
raise ValueError("headers 参数必须是 dict 或 None")
|
|
161
|
+
if config is not None and not isinstance(config, dict):
|
|
162
|
+
raise ValueError("config 参数必须是 dict 或 None")
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
page.wait_for_load_state('load')
|
|
166
|
+
response = page.evaluate("""
|
|
167
|
+
async ({ url, extraHeaders, config }) => {
|
|
168
|
+
try {
|
|
169
|
+
const defaultHeaders = {
|
|
170
|
+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const defaultConfig = {
|
|
174
|
+
method: 'GET',
|
|
175
|
+
credentials: 'include',
|
|
176
|
+
mode: 'cors'
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const headers = Object.assign({}, defaultHeaders, extraHeaders || {});
|
|
180
|
+
const options = Object.assign({}, defaultConfig, config || {}, { headers: headers });
|
|
181
|
+
|
|
182
|
+
const response = await fetch(url, options);
|
|
183
|
+
if (!response.ok) {
|
|
184
|
+
throw new Error(`HTTP ${response.status} - ${response.statusText}`);
|
|
185
|
+
}
|
|
186
|
+
return await response.json();
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return { "error": "fetch_failed", "message": error.message };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
""", {"url": url, "extraHeaders": headers, "config": config})
|
|
192
|
+
|
|
193
|
+
return response
|
|
194
|
+
except Exception as e:
|
|
195
|
+
raise send_exception()
|
|
196
|
+
|
|
149
197
|
def safe_goto(page, url, **kwargs):
|
|
150
198
|
caller = inspect.stack()[1]
|
|
151
199
|
log(f"[DEBUG] goto called from {caller.filename}:{caller.lineno} url={url}")
|
qrpa/shein_lib.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
2
|
from .fun_base import log, send_exception, md5_string, get_safe_value, NetWorkIdleTimeout
|
|
3
|
-
from .fun_web import fetch, full_screen_shot, safe_goto
|
|
3
|
+
from .fun_web import fetch, fetch_get, full_screen_shot, safe_goto
|
|
4
4
|
from .time_utils import TimeUtils
|
|
5
5
|
from .wxwork import WxWorkBot
|
|
6
6
|
|
|
@@ -36,7 +36,7 @@ class SheinLib:
|
|
|
36
36
|
try:
|
|
37
37
|
current_url = web_page.url
|
|
38
38
|
log(f"尝试获取页面信息 - URL: {current_url}", self.store_username, self.store_name)
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
# 检查是否在认证页面,如果是则直接跳转到目标页面
|
|
41
41
|
if '/auth/SSLS' in current_url:
|
|
42
42
|
log("检测到SSLS认证页面,直接跳转到首页", self.store_username, self.store_name)
|
|
@@ -44,17 +44,17 @@ class SheinLib:
|
|
|
44
44
|
web_page.wait_for_timeout(3000)
|
|
45
45
|
current_url = web_page.url
|
|
46
46
|
log(f"跳转后URL: {current_url}", self.store_username, self.store_name)
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
# 等待导航完成
|
|
49
49
|
web_page.wait_for_load_state("domcontentloaded", timeout=6000)
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
final_url = web_page.url
|
|
52
52
|
final_title = web_page.title()
|
|
53
53
|
log(f"页面稳定 - URL: {final_url}, 标题: {final_title}", self.store_username, self.store_name)
|
|
54
54
|
break
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
except Exception as e:
|
|
57
|
-
log(f"第{attempt+1}次等待页面稳定失败: {e}", self.store_username, self.store_name)
|
|
57
|
+
log(f"第{attempt + 1}次等待页面稳定失败: {e}", self.store_username, self.store_name)
|
|
58
58
|
if "crashed" in str(e) or "Target" in str(e):
|
|
59
59
|
log("页面稳定检查时崩溃,直接继续", self.store_username, self.store_name)
|
|
60
60
|
break
|
|
@@ -66,7 +66,7 @@ class SheinLib:
|
|
|
66
66
|
log("页面稳定等待最终失败,继续执行", self.store_username, self.store_name)
|
|
67
67
|
break
|
|
68
68
|
web_page.wait_for_timeout(2000)
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
web_page.wait_for_timeout(2000)
|
|
71
71
|
|
|
72
72
|
# 定义最大重试次数
|
|
@@ -83,19 +83,19 @@ class SheinLib:
|
|
|
83
83
|
retries += 1
|
|
84
84
|
|
|
85
85
|
while not web_page.locator('//div[contains(text(),"商家后台")]').nth(1).is_visible():
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
try:
|
|
88
88
|
current_url = web_page.url
|
|
89
89
|
current_title = web_page.title()
|
|
90
90
|
log(f"循环检查 - URL: {current_url}, 标题: {current_title}", self.store_username, self.store_name)
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
# 如果在认证页面且出现问题,直接跳转
|
|
93
93
|
if '/auth/SSLS' in current_url:
|
|
94
94
|
log("在主循环中检测到SSLS认证页面,跳转到首页", self.store_username, self.store_name)
|
|
95
95
|
web_page.goto('https://sso.geiwohuo.com/#/home', wait_until='domcontentloaded', timeout=15000)
|
|
96
96
|
web_page.wait_for_timeout(3000)
|
|
97
97
|
continue
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
except Exception as status_error:
|
|
100
100
|
log(f"获取页面状态失败: {status_error}", self.store_username, self.store_name)
|
|
101
101
|
if "crashed" in str(status_error):
|
|
@@ -200,13 +200,13 @@ class SheinLib:
|
|
|
200
200
|
except Exception as e:
|
|
201
201
|
log(f"错误发生: {e}, 重试中...({self.store_username}, {self.store_name})")
|
|
202
202
|
log(traceback.format_exc())
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
# 收集崩溃时的详细信息
|
|
205
205
|
try:
|
|
206
206
|
crash_url = web_page.url
|
|
207
207
|
crash_title = web_page.title()
|
|
208
208
|
log(f"崩溃时页面信息 - URL: {crash_url}, 标题: {crash_title}", self.store_username, self.store_name)
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
# 尝试截图保存崩溃现场
|
|
211
211
|
try:
|
|
212
212
|
screenshot_path = f"crash_screenshot_{self.store_username}_{int(time.time())}.png"
|
|
@@ -214,19 +214,19 @@ class SheinLib:
|
|
|
214
214
|
log(f"已保存崩溃截图: {screenshot_path}", self.store_username, self.store_name)
|
|
215
215
|
except:
|
|
216
216
|
log("无法截取崩溃时的页面截图", self.store_username, self.store_name)
|
|
217
|
-
|
|
217
|
+
|
|
218
218
|
except:
|
|
219
219
|
log("无法获取崩溃时的页面信息", self.store_username, self.store_name)
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
# 检查特定类型的错误
|
|
222
222
|
if any(keyword in str(e).lower() for keyword in ['memory', 'out of memory', 'oom']):
|
|
223
223
|
log("检测到内存相关崩溃", self.store_username, self.store_name)
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
if "destroyed" in str(e) or "navigation" in str(e):
|
|
226
226
|
log("检测到导航中断,等待页面稳定后重试", self.store_username, self.store_name)
|
|
227
227
|
web_page.wait_for_timeout(5000)
|
|
228
228
|
continue
|
|
229
|
-
|
|
229
|
+
|
|
230
230
|
if 'crashed' in str(e) or 'Target' in str(e):
|
|
231
231
|
log("检测到页面或目标崩溃,直接退出当前循环", self.store_username, self.store_name)
|
|
232
232
|
raise e
|
|
@@ -241,6 +241,44 @@ class SheinLib:
|
|
|
241
241
|
# web_page.wait_for_load_state("networkidle")
|
|
242
242
|
web_page.wait_for_timeout(3000)
|
|
243
243
|
|
|
244
|
+
# 获取用户信息
|
|
245
|
+
def get_user(self, uuid=None):
|
|
246
|
+
log(f'获取用户信息:{self.store_username} {self.store_name}')
|
|
247
|
+
|
|
248
|
+
# 生成 uuid 参数,如果没有提供则使用时间戳
|
|
249
|
+
if uuid is None:
|
|
250
|
+
import time
|
|
251
|
+
uuid = str(int(time.time() * 1000))
|
|
252
|
+
|
|
253
|
+
url = f"https://sso.geiwohuo.com/sso-prefix/auth/getUser?uuid={uuid}"
|
|
254
|
+
|
|
255
|
+
# 设置请求头,根据 Chrome 请求
|
|
256
|
+
headers = {
|
|
257
|
+
"gmpsso-language": "CN",
|
|
258
|
+
"origin-url" : "https://sso.geiwohuo.com/#/home/",
|
|
259
|
+
"x-sso-scene" : "gmpsso"
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
# 特定于此请求的配置
|
|
263
|
+
fetch_config = {
|
|
264
|
+
"credentials" : "omit",
|
|
265
|
+
"referrer" : "https://sso.geiwohuo.com/",
|
|
266
|
+
"referrerPolicy": "strict-origin-when-cross-origin"
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
response_text = fetch_get(self.web_page, url, headers, fetch_config)
|
|
270
|
+
error_code = response_text.get('code')
|
|
271
|
+
if str(error_code) != '0':
|
|
272
|
+
raise send_exception(json.dumps(response_text, ensure_ascii=False))
|
|
273
|
+
info = response_text.get('info', {})
|
|
274
|
+
log(info)
|
|
275
|
+
cache_file = f'{self.config.auto_dir}/shein_user.json'
|
|
276
|
+
info['store_username'] = self.store_username
|
|
277
|
+
info['store_name'] = self.store_name
|
|
278
|
+
write_dict_to_file_ex(cache_file, {self.store_username: info}, [self.store_username])
|
|
279
|
+
|
|
280
|
+
return info
|
|
281
|
+
|
|
244
282
|
# 获取质检报告pdf地址
|
|
245
283
|
def get_qc_report_url(self, deliverCode, purchaseCode):
|
|
246
284
|
log(f'获取质检报告:{deliverCode} {purchaseCode}')
|
qrpa/shein_ziniao.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import os
|
|
6
6
|
import platform
|
|
7
7
|
import shutil
|
|
8
|
-
import time
|
|
8
|
+
import time, datetime
|
|
9
9
|
import traceback
|
|
10
10
|
import uuid
|
|
11
11
|
import json
|
|
@@ -74,7 +74,7 @@ class ZiniaoClient:
|
|
|
74
74
|
"""启动客户端"""
|
|
75
75
|
try:
|
|
76
76
|
if self.is_windows:
|
|
77
|
-
cmd = [self.client_path, '--run_type=web_driver', '--ipc_type=http', '--port=' + str(self.socket_port)]
|
|
77
|
+
cmd = [self.client_path, '--run_type=web_driver', '--show_sidb=true', '--ipc_type=http', '--port=' + str(self.socket_port)]
|
|
78
78
|
elif self.is_mac:
|
|
79
79
|
cmd = ['open', '-a', self.client_path, '--args', '--run_type=web_driver', '--ipc_type=http',
|
|
80
80
|
'--port=' + str(self.socket_port)]
|
|
@@ -272,6 +272,73 @@ class ZiniaoTaskManager:
|
|
|
272
272
|
self.browser = browser
|
|
273
273
|
self.config = config
|
|
274
274
|
|
|
275
|
+
def daily_cleanup_superbrowser(self, browser_id):
|
|
276
|
+
"""
|
|
277
|
+
每天删除一次SuperBrowser缓存文件夹
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
browser_id (str): 浏览器ID,如 '26986387919128'
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
# 获取本地AppData路径
|
|
284
|
+
local_appdata = os.getenv('LOCALAPPDATA')
|
|
285
|
+
if not local_appdata:
|
|
286
|
+
log("错误: 无法获取LOCALAPPDATA路径")
|
|
287
|
+
return False
|
|
288
|
+
|
|
289
|
+
# 构建路径
|
|
290
|
+
cache_path = os.path.join(local_appdata, 'SuperBrowser')
|
|
291
|
+
target_folder = os.path.join(cache_path, f'User Data\\Chromium_{browser_id}')
|
|
292
|
+
flag_file = os.path.join(cache_path, f'User Data\\cleanup_flag_{browser_id}.txt')
|
|
293
|
+
|
|
294
|
+
# 检查目标文件夹是否存在
|
|
295
|
+
if not os.path.exists(target_folder):
|
|
296
|
+
log(f"目标文件夹不存在: {target_folder}")
|
|
297
|
+
return False
|
|
298
|
+
|
|
299
|
+
# 获取当前日期
|
|
300
|
+
today = datetime.date.today()
|
|
301
|
+
today_str = today.strftime('%Y-%m-%d')
|
|
302
|
+
|
|
303
|
+
# 检查标志文件
|
|
304
|
+
need_cleanup = True
|
|
305
|
+
|
|
306
|
+
if os.path.exists(flag_file):
|
|
307
|
+
try:
|
|
308
|
+
# 读取标志文件中的日期
|
|
309
|
+
with open(flag_file, 'r', encoding='utf-8') as f:
|
|
310
|
+
last_cleanup_date = f.read().strip()
|
|
311
|
+
|
|
312
|
+
# 如果是今天已经清理过,则跳过
|
|
313
|
+
if last_cleanup_date == today_str:
|
|
314
|
+
log(f"今天({today_str})已经清理过,跳过删除操作")
|
|
315
|
+
need_cleanup = False
|
|
316
|
+
|
|
317
|
+
except Exception as e:
|
|
318
|
+
log(f"读取标志文件时出错: {e}")
|
|
319
|
+
# 如果读取出错,继续执行清理
|
|
320
|
+
|
|
321
|
+
if need_cleanup:
|
|
322
|
+
try:
|
|
323
|
+
# 删除目标文件夹
|
|
324
|
+
log(f"正在删除文件夹: {target_folder}")
|
|
325
|
+
shutil.rmtree(target_folder)
|
|
326
|
+
log("删除成功!")
|
|
327
|
+
|
|
328
|
+
# 创建/更新标志文件
|
|
329
|
+
os.makedirs(os.path.dirname(flag_file), exist_ok=True)
|
|
330
|
+
with open(flag_file, 'w', encoding='utf-8') as f:
|
|
331
|
+
f.write(today_str)
|
|
332
|
+
|
|
333
|
+
log(f"已创建标志文件: {flag_file}")
|
|
334
|
+
return True
|
|
335
|
+
|
|
336
|
+
except Exception as e:
|
|
337
|
+
log(f"删除文件夹时出错: {e}")
|
|
338
|
+
return False
|
|
339
|
+
|
|
340
|
+
return True
|
|
341
|
+
|
|
275
342
|
def run_single_store_task(self, browser_info: Dict[str, Any],
|
|
276
343
|
run_func: Callable, task_key: str,
|
|
277
344
|
just_store_username: Optional[List[str]] = None,
|
|
@@ -282,6 +349,10 @@ class ZiniaoTaskManager:
|
|
|
282
349
|
store_name = browser_info.get("browserName")
|
|
283
350
|
store_username = browser_info.get("store_username")
|
|
284
351
|
|
|
352
|
+
# 删除浏览器缓存,一天一删
|
|
353
|
+
browser_id = browser_info.get("browserId")
|
|
354
|
+
self.daily_cleanup_superbrowser(browser_id)
|
|
355
|
+
|
|
285
356
|
retry_count = 0
|
|
286
357
|
while True:
|
|
287
358
|
try:
|
qrpa/time_utils.py
CHANGED
|
@@ -260,20 +260,31 @@ class TimeUtils:
|
|
|
260
260
|
|
|
261
261
|
@staticmethod
|
|
262
262
|
def get_dates_from_first_of_month_to_yesterday() -> List[str]:
|
|
263
|
-
"""获取从本月第一天到昨天的日期列表
|
|
263
|
+
"""获取从本月第一天到昨天的日期列表
|
|
264
|
+
如果今天是本月第一天,则返回上个月的日期列表
|
|
265
|
+
"""
|
|
264
266
|
today = datetime.today()
|
|
265
|
-
first_day_of_month = today.replace(day=1)
|
|
266
267
|
yesterday = today - timedelta(days=1)
|
|
267
268
|
|
|
268
|
-
|
|
269
|
-
|
|
269
|
+
# 如果今天是本月第一天,取上个月
|
|
270
|
+
if today.day == 1:
|
|
271
|
+
# 找到上个月最后一天
|
|
272
|
+
last_month_last_day = today - timedelta(days=1)
|
|
273
|
+
# 上个月第一天
|
|
274
|
+
first_day_of_last_month = last_month_last_day.replace(day=1)
|
|
275
|
+
start_date = first_day_of_last_month
|
|
276
|
+
end_date = last_month_last_day
|
|
277
|
+
else:
|
|
278
|
+
start_date = today.replace(day=1)
|
|
279
|
+
end_date = yesterday
|
|
270
280
|
|
|
271
|
-
|
|
281
|
+
date_list = []
|
|
282
|
+
current_date = start_date
|
|
283
|
+
while current_date <= end_date:
|
|
272
284
|
date_list.append(current_date.strftime('%Y-%m-%d'))
|
|
273
285
|
current_date += timedelta(days=1)
|
|
274
286
|
|
|
275
287
|
return date_list
|
|
276
|
-
|
|
277
288
|
# ==================== 月份相关 ====================
|
|
278
289
|
|
|
279
290
|
@staticmethod
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
qrpa/RateLimitedSender.py,sha256=hqvb1qspDFaW4RsLuVufylOrefkMgixANKeBaGEqYb4,1421
|
|
2
2
|
qrpa/__init__.py,sha256=FjyNLjEnR4Y9_0scrWy7foJmDI4oiqSNyeAohPQTQvE,1148
|
|
3
|
-
qrpa/db_migrator.py,sha256=
|
|
3
|
+
qrpa/db_migrator.py,sha256=6lz1MdSQzN3Co00uwy0EwIXjWrblgL39hHJUw18sf5I,21865
|
|
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
7
|
qrpa/fun_base.py,sha256=lMzqPwsbVfe968CUR2MVNImzIskIUZqPCE2tWxYqb5o,10728
|
|
8
8
|
qrpa/fun_excel.py,sha256=-GFtjg0LeiiXrpTU5RtMlBUHl05mqzdHCzIxlssT59U,117385
|
|
9
9
|
qrpa/fun_file.py,sha256=yzjDV16WL5vRys7J4uQcNzIFkX4D5MAlSCwxcD-mwQo,11966
|
|
10
|
-
qrpa/fun_web.py,sha256=
|
|
10
|
+
qrpa/fun_web.py,sha256=Mv0m2P5fh2-U4DzRoVivqRcXD56BJ_Svj6TZznx49YU,8645
|
|
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=5rsxoS8rI8xKprjEVmEzaNRrTcCm4FU2eGcpfhf-TzE,134142
|
|
15
15
|
qrpa/shein_mysql.py,sha256=Sgz6U0_3f4cT5zPf1Ht1OjvSFhrVPLkMxt91NV-ZPCM,3005
|
|
16
16
|
qrpa/shein_sqlite.py,sha256=ZQwD0Gz81q9WY7tY2HMEYvSF9r3N_G_Aur3bYfST9WY,5707
|
|
17
|
-
qrpa/shein_ziniao.py,sha256=
|
|
17
|
+
qrpa/shein_ziniao.py,sha256=4CsOPZXRDEqHJvCGyb8imCPqSH5Ln5fGqPUFqLuFgCg,21276
|
|
18
18
|
qrpa/temu_chrome.py,sha256=CbtFy1QPan9xJdJcNZj-EsVGhUvv3ZTEPVDEA4-im40,2803
|
|
19
19
|
qrpa/temu_excel.py,sha256=2hGw76YWzkTZGyFCuuUAab4oHptYX9a6U6yjpNsL7FE,6990
|
|
20
20
|
qrpa/temu_lib.py,sha256=hYB59zsLS3m3NTic_duTwPMOTSxlHyQVa8OhHnHm-1g,7199
|
|
21
|
-
qrpa/time_utils.py,sha256=
|
|
21
|
+
qrpa/time_utils.py,sha256=KFXnF1pMWACAKOSy483riPqvTsMjhQtFJAIhQsZKaMk,30075
|
|
22
22
|
qrpa/time_utils_example.py,sha256=shHOXKKF3QSzb0SHsNc34M61wEkkLuM30U9X1THKNS8,8053
|
|
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_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.90.dist-info/METADATA,sha256=5_HyMIZcanl7560yxaMsi9O4YjuP2nlvjtMIzsSEJXM,231
|
|
28
|
+
qrpa-1.0.90.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
qrpa-1.0.90.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
|
|
30
|
+
qrpa-1.0.90.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|