qrpa 1.0.28__py3-none-any.whl → 1.0.30__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/__init__.py +1 -0
- qrpa/feishu_bot_app.py +2 -2
- qrpa/fun_excel.py +105 -37
- qrpa/shein_excel.py +52 -14
- qrpa/shein_lib.py +7 -0
- {qrpa-1.0.28.dist-info → qrpa-1.0.30.dist-info}/METADATA +1 -1
- {qrpa-1.0.28.dist-info → qrpa-1.0.30.dist-info}/RECORD +9 -9
- {qrpa-1.0.28.dist-info → qrpa-1.0.30.dist-info}/WHEEL +0 -0
- {qrpa-1.0.28.dist-info → qrpa-1.0.30.dist-info}/top_level.txt +0 -0
qrpa/__init__.py
CHANGED
qrpa/feishu_bot_app.py
CHANGED
|
@@ -26,8 +26,8 @@ class FeishuBot:
|
|
|
26
26
|
"""获取飞书客户端,使用懒加载模式"""
|
|
27
27
|
if self._client is None:
|
|
28
28
|
self._client = lark.Client.builder() \
|
|
29
|
-
.app_id(self.config.
|
|
30
|
-
.app_secret(self.config.
|
|
29
|
+
.app_id(self.config.feishu_bot.app_id) \
|
|
30
|
+
.app_secret(self.config.feishu_bot.app_secret) \
|
|
31
31
|
.log_level(lark.LogLevel.INFO) \
|
|
32
32
|
.build()
|
|
33
33
|
return self._client
|
qrpa/fun_excel.py
CHANGED
|
@@ -282,6 +282,7 @@ def delete_sheet_if_exists(wb, sheet_name):
|
|
|
282
282
|
sheet_names = [s.name for s in wb.sheets]
|
|
283
283
|
if sheet_name in sheet_names:
|
|
284
284
|
wb.sheets[sheet_name].delete()
|
|
285
|
+
wb.save()
|
|
285
286
|
print(f"已删除 Sheet: {sheet_name}")
|
|
286
287
|
else:
|
|
287
288
|
print(f"Sheet 不存在: {sheet_name}")
|
|
@@ -1871,18 +1872,18 @@ def format_to_text_v2_safe(sheet, columns=None, data_rows=None):
|
|
|
1871
1872
|
"""
|
|
1872
1873
|
if columns is None or len(columns) == 0:
|
|
1873
1874
|
return
|
|
1874
|
-
|
|
1875
|
+
|
|
1875
1876
|
# 确保columns是列表
|
|
1876
1877
|
if not isinstance(columns, list):
|
|
1877
1878
|
columns = [columns]
|
|
1878
|
-
|
|
1879
|
+
|
|
1879
1880
|
for col_name in columns:
|
|
1880
1881
|
try:
|
|
1881
1882
|
if isinstance(col_name, int):
|
|
1882
1883
|
col_name = xw.utils.col_name(col_name)
|
|
1883
|
-
|
|
1884
|
+
|
|
1884
1885
|
log(f'安全设置[{col_name}] 文本格式')
|
|
1885
|
-
|
|
1886
|
+
|
|
1886
1887
|
# 如果指定了数据行数,只格式化有数据的范围
|
|
1887
1888
|
if data_rows and data_rows > 0:
|
|
1888
1889
|
# 格式化从第1行到数据行数的范围
|
|
@@ -1899,7 +1900,7 @@ def format_to_text_v2_safe(sheet, columns=None, data_rows=None):
|
|
|
1899
1900
|
log(f'列 {col_name} 没有数据,跳过格式化')
|
|
1900
1901
|
except:
|
|
1901
1902
|
log(f'列 {col_name} 格式化失败,跳过')
|
|
1902
|
-
|
|
1903
|
+
|
|
1903
1904
|
except Exception as e:
|
|
1904
1905
|
log(f'设置列 {col_name} 文本格式失败: {e},继续处理其他列')
|
|
1905
1906
|
|
|
@@ -1914,14 +1915,14 @@ def pre_format_columns_safe(sheet, columns, data_rows):
|
|
|
1914
1915
|
"""
|
|
1915
1916
|
if not columns or not isinstance(columns, list):
|
|
1916
1917
|
return
|
|
1917
|
-
|
|
1918
|
+
|
|
1918
1919
|
for col_name in columns:
|
|
1919
1920
|
try:
|
|
1920
1921
|
if isinstance(col_name, int):
|
|
1921
1922
|
col_name = xw.utils.col_name(col_name)
|
|
1922
|
-
|
|
1923
|
+
|
|
1923
1924
|
log(f'预格式化列 [{col_name}] 为文本格式')
|
|
1924
|
-
|
|
1925
|
+
|
|
1925
1926
|
# 方法1:先创建最小范围,避免整列操作
|
|
1926
1927
|
try:
|
|
1927
1928
|
# 创建足够大的范围来覆盖预期数据
|
|
@@ -1930,7 +1931,7 @@ def pre_format_columns_safe(sheet, columns, data_rows):
|
|
|
1930
1931
|
log(f'预格式化成功: {range_str}')
|
|
1931
1932
|
except Exception as e1:
|
|
1932
1933
|
log(f'预格式化方法1失败: {e1}')
|
|
1933
|
-
|
|
1934
|
+
|
|
1934
1935
|
# 方法2:逐行设置格式,更安全但稍慢
|
|
1935
1936
|
try:
|
|
1936
1937
|
for row in range(1, data_rows + 1):
|
|
@@ -1939,7 +1940,7 @@ def pre_format_columns_safe(sheet, columns, data_rows):
|
|
|
1939
1940
|
log(f'逐行预格式化成功: {col_name}')
|
|
1940
1941
|
except Exception as e2:
|
|
1941
1942
|
log(f'逐行预格式化也失败: {e2}')
|
|
1942
|
-
|
|
1943
|
+
|
|
1943
1944
|
except Exception as e:
|
|
1944
1945
|
log(f'预格式化列 {col_name} 失败: {e},继续处理其他列')
|
|
1945
1946
|
|
|
@@ -1954,20 +1955,20 @@ def post_format_columns_safe(sheet, columns, data_rows):
|
|
|
1954
1955
|
"""
|
|
1955
1956
|
if not columns or not isinstance(columns, list):
|
|
1956
1957
|
return
|
|
1957
|
-
|
|
1958
|
+
|
|
1958
1959
|
for col_name in columns:
|
|
1959
1960
|
try:
|
|
1960
1961
|
if isinstance(col_name, int):
|
|
1961
1962
|
col_name = xw.utils.col_name(col_name)
|
|
1962
|
-
|
|
1963
|
+
|
|
1963
1964
|
log(f'后格式化列 [{col_name}] 为文本格式')
|
|
1964
|
-
|
|
1965
|
+
|
|
1965
1966
|
# 只对实际有数据的行进行格式化
|
|
1966
1967
|
if data_rows > 0:
|
|
1967
1968
|
range_str = f'{col_name}1:{col_name}{data_rows}'
|
|
1968
1969
|
sheet.range(range_str).number_format = '@'
|
|
1969
1970
|
log(f'后格式化成功: {range_str}')
|
|
1970
|
-
|
|
1971
|
+
|
|
1971
1972
|
except Exception as e:
|
|
1972
1973
|
log(f'后格式化列 {col_name} 失败: {e},继续处理其他列')
|
|
1973
1974
|
|
|
@@ -2545,18 +2546,77 @@ def format_excel_with_lock(excel_path, sheet_name, format_func, *args, **kwargs)
|
|
|
2545
2546
|
# 经过观察 fortmat时 传入函数需要为类函数且第二个参数必须是 sheet
|
|
2546
2547
|
def batch_excel_operations(excel_path, operations):
|
|
2547
2548
|
"""
|
|
2548
|
-
批量 Excel
|
|
2549
|
-
|
|
2549
|
+
批量 Excel 操作函数,自动分批处理,避免一次操作过多sheet导致Excel COM错误
|
|
2550
|
+
保持操作的原始顺序执行
|
|
2551
|
+
|
|
2550
2552
|
Args:
|
|
2551
2553
|
excel_path: Excel 文件路径
|
|
2552
2554
|
operations: 操作列表,每个操作是 (sheet_name, operation_type, data, format_func) 的元组
|
|
2553
|
-
operation_type: 'write'
|
|
2554
|
-
|
|
2555
|
-
format_func: 格式化函数(仅 format 操作需要)
|
|
2556
|
-
|
|
2555
|
+
operation_type: 'write', 'format', 'delete', 'move', 'active'
|
|
2556
|
+
|
|
2557
2557
|
Returns:
|
|
2558
2558
|
bool: 是否全部操作成功
|
|
2559
2559
|
"""
|
|
2560
|
+
if not operations:
|
|
2561
|
+
return True
|
|
2562
|
+
|
|
2563
|
+
# 批处理大小设置:每批最多处理8个操作
|
|
2564
|
+
MAX_OPERATIONS_PER_BATCH = 8
|
|
2565
|
+
|
|
2566
|
+
try:
|
|
2567
|
+
# 计算需要分几批
|
|
2568
|
+
total_batches = (len(operations) + MAX_OPERATIONS_PER_BATCH - 1) // MAX_OPERATIONS_PER_BATCH
|
|
2569
|
+
log(f"分{total_batches}批执行{len(operations)}个操作,每批最多{MAX_OPERATIONS_PER_BATCH}个,保持原始顺序")
|
|
2570
|
+
|
|
2571
|
+
# 按顺序分批执行
|
|
2572
|
+
for batch_idx in range(total_batches):
|
|
2573
|
+
start_idx = batch_idx * MAX_OPERATIONS_PER_BATCH
|
|
2574
|
+
end_idx = min(start_idx + MAX_OPERATIONS_PER_BATCH, len(operations))
|
|
2575
|
+
batch_operations = operations[start_idx:end_idx]
|
|
2576
|
+
|
|
2577
|
+
log(f"执行第{batch_idx + 1}/{total_batches}批操作({start_idx + 1}-{end_idx}),共{len(batch_operations)}个操作")
|
|
2578
|
+
|
|
2579
|
+
# 重试机制
|
|
2580
|
+
max_retries = 3
|
|
2581
|
+
for retry in range(max_retries):
|
|
2582
|
+
try:
|
|
2583
|
+
# 强制垃圾回收
|
|
2584
|
+
import gc
|
|
2585
|
+
gc.collect()
|
|
2586
|
+
|
|
2587
|
+
if _execute_operations_batch(excel_path, batch_operations):
|
|
2588
|
+
log(f"第{batch_idx + 1}批操作成功")
|
|
2589
|
+
break
|
|
2590
|
+
else:
|
|
2591
|
+
log(f"第{batch_idx + 1}批操作失败,重试 {retry + 1}/{max_retries}")
|
|
2592
|
+
if retry == max_retries - 1:
|
|
2593
|
+
log(f"第{batch_idx + 1}批操作最终失败")
|
|
2594
|
+
return False
|
|
2595
|
+
import time
|
|
2596
|
+
time.sleep(3)
|
|
2597
|
+
except Exception as e:
|
|
2598
|
+
log(f"第{batch_idx + 1}批操作异常: {e}")
|
|
2599
|
+
if retry == max_retries - 1:
|
|
2600
|
+
return False
|
|
2601
|
+
import time
|
|
2602
|
+
time.sleep(3)
|
|
2603
|
+
|
|
2604
|
+
# 批次间延迟
|
|
2605
|
+
if batch_idx < total_batches - 1:
|
|
2606
|
+
import time
|
|
2607
|
+
time.sleep(1)
|
|
2608
|
+
|
|
2609
|
+
log(f"所有批量操作完成: {excel_path}")
|
|
2610
|
+
return True
|
|
2611
|
+
|
|
2612
|
+
except Exception as e:
|
|
2613
|
+
log(f"批量操作过程异常: {e}")
|
|
2614
|
+
return False
|
|
2615
|
+
|
|
2616
|
+
def _execute_operations_batch(excel_path, operations):
|
|
2617
|
+
"""
|
|
2618
|
+
执行单个批次的操作
|
|
2619
|
+
"""
|
|
2560
2620
|
app, wb, sheet = open_excel_with_lock(excel_path)
|
|
2561
2621
|
if not app or not wb:
|
|
2562
2622
|
log(f"无法打开 Excel 文件: {excel_path}")
|
|
@@ -2564,23 +2624,38 @@ def batch_excel_operations(excel_path, operations):
|
|
|
2564
2624
|
|
|
2565
2625
|
try:
|
|
2566
2626
|
for sheet_name, operation_type, *args in operations:
|
|
2567
|
-
#
|
|
2627
|
+
# 根据操作类型决定是否需要获取或创建工作表
|
|
2628
|
+
sheet = None
|
|
2629
|
+
|
|
2630
|
+
# 删除操作不需要获取sheet对象
|
|
2631
|
+
if operation_type == 'delete':
|
|
2632
|
+
log(f'删除sheet: {sheet_name}')
|
|
2633
|
+
delete_sheet_if_exists(wb, sheet_name)
|
|
2634
|
+
continue
|
|
2635
|
+
|
|
2636
|
+
# 其他操作需要获取或创建工作表
|
|
2568
2637
|
if isinstance(sheet_name, str):
|
|
2569
2638
|
sheet_names = [s.name.strip().lower() for s in wb.sheets]
|
|
2570
2639
|
if sheet_name.strip().lower() in sheet_names:
|
|
2571
2640
|
sheet = wb.sheets[sheet_name]
|
|
2572
2641
|
else:
|
|
2573
|
-
sheet
|
|
2642
|
+
# 只有在需要操作sheet内容时才创建
|
|
2643
|
+
if operation_type in ['write', 'format']:
|
|
2644
|
+
sheet = wb.sheets.add(sheet_name, after=wb.sheets[-1])
|
|
2645
|
+
else:
|
|
2646
|
+
log(f"警告: 操作 {operation_type} 需要的sheet {sheet_name} 不存在,跳过此操作")
|
|
2647
|
+
continue
|
|
2574
2648
|
else:
|
|
2575
2649
|
sheet = wb.sheets[sheet_name]
|
|
2576
2650
|
|
|
2577
|
-
sheet
|
|
2651
|
+
if sheet:
|
|
2652
|
+
sheet.activate()
|
|
2578
2653
|
|
|
2579
2654
|
if operation_type == 'write':
|
|
2580
2655
|
data, format_to_text_colunm = args[0], args[1:] if len(args) > 1 else None
|
|
2581
2656
|
# 清空工作表
|
|
2582
2657
|
sheet.clear()
|
|
2583
|
-
|
|
2658
|
+
|
|
2584
2659
|
# 先设置文本格式,再写入数据(确保格式生效)
|
|
2585
2660
|
if format_to_text_colunm and format_to_text_colunm[0]:
|
|
2586
2661
|
try:
|
|
@@ -2588,11 +2663,11 @@ def batch_excel_operations(excel_path, operations):
|
|
|
2588
2663
|
pre_format_columns_safe(sheet, format_to_text_colunm[0], len(data))
|
|
2589
2664
|
except Exception as e:
|
|
2590
2665
|
log(f"预格式化失败: {e},继续执行")
|
|
2591
|
-
|
|
2666
|
+
|
|
2592
2667
|
# 写入数据
|
|
2668
|
+
log(f"批量操作,写入数据到: {sheet_name}")
|
|
2593
2669
|
sheet.range('A1').value = data
|
|
2594
|
-
|
|
2595
|
-
|
|
2670
|
+
|
|
2596
2671
|
# 写入后再次确认格式(双重保险)
|
|
2597
2672
|
if format_to_text_colunm and format_to_text_colunm[0]:
|
|
2598
2673
|
try:
|
|
@@ -2602,31 +2677,24 @@ def batch_excel_operations(excel_path, operations):
|
|
|
2602
2677
|
|
|
2603
2678
|
elif operation_type == 'format':
|
|
2604
2679
|
format_func, format_args = args[0], args[1:] if len(args) > 1 else ()
|
|
2605
|
-
log('格式化入参', *format_args)
|
|
2606
2680
|
# 执行格式化
|
|
2607
2681
|
format_func(sheet, *format_args)
|
|
2608
|
-
log(f"批量操作:格式化工作表 {sheet_name}")
|
|
2609
|
-
|
|
2610
|
-
elif operation_type == 'delete':
|
|
2611
|
-
pass
|
|
2612
|
-
delete_sheet_if_exists(wb, sheet_name)
|
|
2613
2682
|
|
|
2614
2683
|
elif operation_type == 'move':
|
|
2615
|
-
|
|
2684
|
+
log(f'移动sheet: {sheet_name}')
|
|
2616
2685
|
position = args[0]
|
|
2617
2686
|
move_sheet_to_position(wb, sheet_name, position)
|
|
2618
2687
|
|
|
2619
2688
|
elif operation_type == 'active':
|
|
2620
|
-
|
|
2689
|
+
log(f'激活sheet: {sheet_name}')
|
|
2621
2690
|
sheet.activate()
|
|
2622
2691
|
|
|
2623
2692
|
# 保存所有更改
|
|
2624
2693
|
wb.save()
|
|
2625
|
-
log(f"批量操作完成: {excel_path}")
|
|
2626
2694
|
return True
|
|
2627
2695
|
|
|
2628
2696
|
except Exception as e:
|
|
2629
|
-
log(f"
|
|
2697
|
+
log(f"单批次操作失败: {e}")
|
|
2630
2698
|
return False
|
|
2631
2699
|
finally:
|
|
2632
2700
|
# 释放锁但不关闭 Excel(保持复用)
|
qrpa/shein_excel.py
CHANGED
|
@@ -1426,6 +1426,13 @@ class SheinExcel:
|
|
|
1426
1426
|
))
|
|
1427
1427
|
batch_excel_operations(excel_path, operations)
|
|
1428
1428
|
|
|
1429
|
+
# 添加月度sheet操作 - 自定义操作函数
|
|
1430
|
+
def write_monthly_data(self, sheet, data, name):
|
|
1431
|
+
# 写入数据到A5位置(月度数据从A列开始)
|
|
1432
|
+
sheet.range('A5').value = data
|
|
1433
|
+
# 设置标题
|
|
1434
|
+
sheet.range('A1').value = f'{name}SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
1435
|
+
|
|
1429
1436
|
def write_sales_data(self):
|
|
1430
1437
|
yesterday = TimeUtils.get_yesterday()
|
|
1431
1438
|
model = SheinStoreSalesDetailManager(self.config.database_url)
|
|
@@ -1464,7 +1471,7 @@ class SheinExcel:
|
|
|
1464
1471
|
sheet_name_first = 'SHEIN销售部每日店铺情况'
|
|
1465
1472
|
|
|
1466
1473
|
# 准备批量操作列表
|
|
1467
|
-
|
|
1474
|
+
base_operations = []
|
|
1468
1475
|
|
|
1469
1476
|
# 添加每日汇总sheet的操作 - 自定义操作函数
|
|
1470
1477
|
def write_daily_data(sheet):
|
|
@@ -1475,13 +1482,16 @@ class SheinExcel:
|
|
|
1475
1482
|
# 设置日期和合并
|
|
1476
1483
|
sheet.range('A4').value = f'{TimeUtils.format_date_cross_platform(yesterday)}\n({TimeUtils.get_chinese_weekday(yesterday)})'
|
|
1477
1484
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1485
|
+
base_operations.append((sheet_name_first, 'format', write_daily_data))
|
|
1486
|
+
base_operations.append((sheet_name_first, 'format', self._format_daily_summary_sheet, yesterday, len(data_day)))
|
|
1487
|
+
base_operations.append((sheet_name_first, 'move', 1))
|
|
1488
|
+
base_operations.append(('Sheet1', 'delete'))
|
|
1482
1489
|
|
|
1483
1490
|
# 获取店铺列表并准备月度数据
|
|
1484
1491
|
store_list = model.get_distinct_store_sales_list()
|
|
1492
|
+
|
|
1493
|
+
# 准备所有店铺的数据
|
|
1494
|
+
store_operations_data = []
|
|
1485
1495
|
for store in store_list:
|
|
1486
1496
|
store_username = store[0]
|
|
1487
1497
|
store_name = dict_store_name.get(store_username)
|
|
@@ -1512,18 +1522,22 @@ class SheinExcel:
|
|
|
1512
1522
|
# store_data.append(record.remark) # 月度数据不包含备注列,保持19列
|
|
1513
1523
|
data_month.append(store_data)
|
|
1514
1524
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
# 设置标题
|
|
1520
|
-
sheet.range('A1').value = f'{name}SHEIN{TimeUtils.get_current_month()}月店铺数据'
|
|
1525
|
+
store_operations_data.append((store_name, data_month))
|
|
1526
|
+
|
|
1527
|
+
# 构建所有操作列表
|
|
1528
|
+
operations = base_operations.copy()
|
|
1521
1529
|
|
|
1522
|
-
|
|
1523
|
-
|
|
1530
|
+
# 添加店铺操作
|
|
1531
|
+
for store_name, data_month in store_operations_data:
|
|
1532
|
+
# 清理店铺名称
|
|
1533
|
+
clean_store_name = self._clean_sheet_name(store_name)
|
|
1534
|
+
operations.append((clean_store_name, 'format', self.write_monthly_data, data_month, clean_store_name))
|
|
1535
|
+
operations.append((clean_store_name, 'format', self._format_store_monthly_sheet, clean_store_name, len(data_month)))
|
|
1524
1536
|
|
|
1525
|
-
#
|
|
1537
|
+
# 添加最后激活操作
|
|
1526
1538
|
operations.append((sheet_name_first, 'active'))
|
|
1539
|
+
|
|
1540
|
+
# 执行批量操作(内部会自动分批处理)
|
|
1527
1541
|
success = batch_excel_operations(excel_path, operations)
|
|
1528
1542
|
|
|
1529
1543
|
if success:
|
|
@@ -1533,6 +1547,30 @@ class SheinExcel:
|
|
|
1533
1547
|
else:
|
|
1534
1548
|
log(f"销售数据写入失败: {excel_path}")
|
|
1535
1549
|
|
|
1550
|
+
def _clean_sheet_name(self, name):
|
|
1551
|
+
"""
|
|
1552
|
+
清理工作表名称,移除Excel不支持的字符
|
|
1553
|
+
"""
|
|
1554
|
+
if not name:
|
|
1555
|
+
return "DefaultSheet"
|
|
1556
|
+
|
|
1557
|
+
# Excel工作表名称限制:不能包含 [ ] : * ? / \ 字符,且长度不超过31字符
|
|
1558
|
+
invalid_chars = ['[', ']', ':', '*', '?', '/', '\\']
|
|
1559
|
+
clean_name = name
|
|
1560
|
+
|
|
1561
|
+
for char in invalid_chars:
|
|
1562
|
+
clean_name = clean_name.replace(char, '_')
|
|
1563
|
+
|
|
1564
|
+
# 限制长度为31字符
|
|
1565
|
+
if len(clean_name) > 31:
|
|
1566
|
+
clean_name = clean_name[:28] + "..."
|
|
1567
|
+
|
|
1568
|
+
# 确保不为空
|
|
1569
|
+
if not clean_name.strip():
|
|
1570
|
+
clean_name = "Sheet"
|
|
1571
|
+
|
|
1572
|
+
return clean_name
|
|
1573
|
+
|
|
1536
1574
|
def _format_daily_summary_sheet(self, sheet, yesterday, data_length):
|
|
1537
1575
|
"""格式化每日汇总sheet"""
|
|
1538
1576
|
las_row = data_length + 4 # 数据从第5行开始,4行header
|
qrpa/shein_lib.py
CHANGED
|
@@ -1611,6 +1611,9 @@ class SheinLib:
|
|
|
1611
1611
|
|
|
1612
1612
|
spu_list = response_text['info']['list']
|
|
1613
1613
|
|
|
1614
|
+
skc_list = [item['skc'] for item in spu_list]
|
|
1615
|
+
self.get_sku_price_v2(skc_list)
|
|
1616
|
+
|
|
1614
1617
|
total = response_text['info']['count']
|
|
1615
1618
|
totalPage = math.ceil(total / pageSize)
|
|
1616
1619
|
for page in range(2, totalPage + 1):
|
|
@@ -1619,6 +1622,10 @@ class SheinLib:
|
|
|
1619
1622
|
payload = dictPayload
|
|
1620
1623
|
response_text = fetch(self.web_page, url, payload)
|
|
1621
1624
|
spu_list_new = response_text['info']['list']
|
|
1625
|
+
|
|
1626
|
+
skc_list = [item['skc'] for item in spu_list_new]
|
|
1627
|
+
self.get_sku_price_v2(skc_list)
|
|
1628
|
+
|
|
1622
1629
|
spu_list += spu_list_new
|
|
1623
1630
|
time.sleep(0.3)
|
|
1624
1631
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
qrpa/RateLimitedSender.py,sha256=hqvb1qspDFaW4RsLuVufylOrefkMgixANKeBaGEqYb4,1421
|
|
2
|
-
qrpa/__init__.py,sha256=
|
|
2
|
+
qrpa/__init__.py,sha256=p4n9kXm1j9G-GWKDPWQa1WIyrDUeC33zeM27xky9otg,1019
|
|
3
3
|
qrpa/db_migrator.py,sha256=2VmhzcMsU0MKpl-mNCwKyV8tLTqyEysSpP27-S_rQZ8,21862
|
|
4
|
-
qrpa/feishu_bot_app.py,sha256=
|
|
4
|
+
qrpa/feishu_bot_app.py,sha256=2oUEdfvROzFazKrNoZ0pRbww9YWSU9cTzTdwcCYS7Ug,9482
|
|
5
5
|
qrpa/fun_base.py,sha256=qg6SvR-GEj2TclB1OL9eLu711jV-bysXJ5Eh2gW9pE8,10600
|
|
6
|
-
qrpa/fun_excel.py,sha256=
|
|
6
|
+
qrpa/fun_excel.py,sha256=gWRNZ44dVSfPkIV6baObI84Bk-CV35Eb4EtYVqre8xI,114220
|
|
7
7
|
qrpa/fun_file.py,sha256=yzjDV16WL5vRys7J4uQcNzIFkX4D5MAlSCwxcD-mwQo,11966
|
|
8
8
|
qrpa/fun_web.py,sha256=5QLQorAhRzMOGMRh4eCJ2UH8ZhVHvxkHwobWhmgU5qM,6286
|
|
9
9
|
qrpa/fun_win.py,sha256=-LnTeocdTt72NVH6VgLdpAT9_C5oV9okeudXG6CftMA,8034
|
|
10
10
|
qrpa/shein_daily_report_model.py,sha256=H8oZmIN5Pyqe306W1_xuz87lOqLQ_LI5RjXbaxDkIzE,12589
|
|
11
|
-
qrpa/shein_excel.py,sha256=
|
|
12
|
-
qrpa/shein_lib.py,sha256=
|
|
11
|
+
qrpa/shein_excel.py,sha256=mDqnamzNi8e_T1RnTYZAJAeVhT3CDl9shBqZ1IetbSk,102632
|
|
12
|
+
qrpa/shein_lib.py,sha256=A9sKidNf1NVFomXA3-UzckYjcpQx4QDIYvLVbQfHl3o,101218
|
|
13
13
|
qrpa/shein_sqlite.py,sha256=ZQwD0Gz81q9WY7tY2HMEYvSF9r3N_G_Aur3bYfST9WY,5707
|
|
14
14
|
qrpa/shein_ziniao.py,sha256=nSqqcEPh4nVQtUxUnIRzeZfTLyXywGPjPZn5pP-w57U,18309
|
|
15
15
|
qrpa/temu_chrome.py,sha256=CbtFy1QPan9xJdJcNZj-EsVGhUvv3ZTEPVDEA4-im40,2803
|
|
@@ -18,7 +18,7 @@ qrpa/temu_lib.py,sha256=hYB59zsLS3m3NTic_duTwPMOTSxlHyQVa8OhHnHm-1g,7199
|
|
|
18
18
|
qrpa/time_utils.py,sha256=ef0hhbN_6b-gcnz5ETIVOoxemIMvcxGVGGIRnHnGaBo,29564
|
|
19
19
|
qrpa/time_utils_example.py,sha256=shHOXKKF3QSzb0SHsNc34M61wEkkLuM30U9X1THKNS8,8053
|
|
20
20
|
qrpa/wxwork.py,sha256=Vy8PGEtlTWt4-1laVhuqpJUGCFH2JymgbjvH00aaBog,10946
|
|
21
|
-
qrpa-1.0.
|
|
22
|
-
qrpa-1.0.
|
|
23
|
-
qrpa-1.0.
|
|
24
|
-
qrpa-1.0.
|
|
21
|
+
qrpa-1.0.30.dist-info/METADATA,sha256=dvFOSHAXQhbMg8Kd3C8lXFgC17aPTxto1BZ10maRYTU,231
|
|
22
|
+
qrpa-1.0.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
23
|
+
qrpa-1.0.30.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
|
|
24
|
+
qrpa-1.0.30.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|