qrpa 1.0.22__tar.gz → 1.0.24__tar.gz

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.

Files changed (31) hide show
  1. {qrpa-1.0.22 → qrpa-1.0.24}/PKG-INFO +1 -1
  2. {qrpa-1.0.22 → qrpa-1.0.24}/pyproject.toml +1 -1
  3. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/__init__.py +5 -1
  4. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/fun_base.py +38 -0
  5. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/fun_excel.py +50 -10
  6. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/shein_daily_report_model.py +1 -1
  7. qrpa-1.0.24/qrpa/shein_excel.py +776 -0
  8. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/shein_lib.py +155 -0
  9. qrpa-1.0.24/qrpa/temu_chrome.py +56 -0
  10. qrpa-1.0.24/qrpa/temu_excel.py +109 -0
  11. qrpa-1.0.24/qrpa/temu_lib.py +154 -0
  12. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/wxwork.py +6 -0
  13. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa.egg-info/PKG-INFO +1 -1
  14. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa.egg-info/SOURCES.txt +3 -0
  15. qrpa-1.0.22/qrpa/shein_excel.py +0 -575
  16. {qrpa-1.0.22 → qrpa-1.0.24}/README.md +0 -0
  17. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/RateLimitedSender.py +0 -0
  18. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/db_migrator.py +0 -0
  19. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/fun_file.py +0 -0
  20. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/fun_web.py +0 -0
  21. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/fun_win.py +0 -0
  22. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/shein_sqlite.py +0 -0
  23. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/shein_ziniao.py +0 -0
  24. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/time_utils.py +0 -0
  25. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa/time_utils_example.py +0 -0
  26. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa.egg-info/dependency_links.txt +0 -0
  27. {qrpa-1.0.22 → qrpa-1.0.24}/qrpa.egg-info/top_level.txt +0 -0
  28. {qrpa-1.0.22 → qrpa-1.0.24}/setup.cfg +0 -0
  29. {qrpa-1.0.22 → qrpa-1.0.24}/setup.py +0 -0
  30. {qrpa-1.0.22 → qrpa-1.0.24}/tests/test_db_migrator.py +0 -0
  31. {qrpa-1.0.22 → qrpa-1.0.24}/tests/test_wxwork.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.0.22
3
+ Version: 1.0.24
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qrpa"
7
- version = "1.0.22"
7
+ version = "1.0.24"
8
8
  description = "qsir's rpa library"
9
9
  authors = [{ name = "QSir", email = "1171725650@qq.com" }]
10
10
  readme = "README.md"
@@ -3,7 +3,7 @@ from .db_migrator import DatabaseMigrator, DatabaseConfig, RemoteConfig, create_
3
3
 
4
4
  from .shein_ziniao import ZiniaoRunner
5
5
 
6
- from .fun_base import log, send_exception, md5_string, hostname, get_safe_value, sanitize_filename
6
+ from .fun_base import log, send_exception, md5_string, hostname, get_safe_value, sanitize_filename, get_file_size, calculate_star_symbols
7
7
 
8
8
  from .time_utils import TimeUtils
9
9
 
@@ -18,3 +18,7 @@ from .shein_excel import SheinExcel
18
18
  from .shein_lib import SheinLib
19
19
 
20
20
  from .fun_excel import InsertImageV2
21
+
22
+ from .temu_lib import TemuLib
23
+ from .temu_excel import TemuExcel
24
+ from .temu_chrome import temu_chrome_excute
@@ -105,3 +105,41 @@ def copy_file(source, destination):
105
105
  print(f"错误:没有权限复制到 '{destination}'")
106
106
  except Exception as e:
107
107
  print(f"错误:发生未知错误 - {e}")
108
+
109
+ def get_file_size(file_path, human_readable=False):
110
+ """
111
+ 获取文件大小
112
+
113
+ :param file_path: 文件路径
114
+ :param human_readable: 是否返回可读格式(KB, MB, GB)
115
+ :return: 文件大小(字节数或可读格式)
116
+ """
117
+ if not os.path.isfile(file_path):
118
+ raise FileNotFoundError(f"文件不存在: {file_path}")
119
+
120
+ size_bytes = os.path.getsize(file_path)
121
+
122
+ if not human_readable:
123
+ return size_bytes
124
+
125
+ # 转换为可读单位
126
+ units = ["B", "KB", "MB", "GB", "TB"]
127
+ size = float(size_bytes)
128
+ for unit in units:
129
+ if size < 1024:
130
+ return f"{size:.2f} {unit}"
131
+ size /= 1024
132
+
133
+ def calculate_star_symbols(rating):
134
+ """
135
+ 计算星级对应的符号组合(独立评分逻辑函数)
136
+ 参数:
137
+ rating (int): 标准化评分(0-5)
138
+ 返回:
139
+ str: 星级符号字符串(如★★★⭐☆)
140
+ """
141
+ full_stars = int(rating)
142
+ empty_stars = 5 - full_stars
143
+ star_string = '★' * full_stars
144
+ star_string += '☆' * empty_stars
145
+ return star_string
@@ -12,6 +12,7 @@ import concurrent.futures
12
12
  from collections import defaultdict
13
13
  import threading
14
14
  from playwright.sync_api import sync_playwright
15
+ import psutil
15
16
 
16
17
  from .fun_base import log, sanitize_filename, create_file_path, copy_file, add_https, send_exception
17
18
 
@@ -89,13 +90,13 @@ def set_cell_prefix_red(cell, n, color_name):
89
90
  except Exception as e:
90
91
  print(f"设置字体颜色失败: {e}")
91
92
 
92
- def sort_by_column(data, col_index, start_row=2, reverse=True):
93
- if not data or start_row >= len(data):
93
+ def sort_by_column(data, col_index, header_rows=2, reverse=True):
94
+ if not data or header_rows >= len(data):
94
95
  return data
95
96
 
96
97
  try:
97
- header = data[:start_row]
98
- new_data_sorted = data[start_row:]
98
+ header = data[:header_rows]
99
+ new_data_sorted = data[header_rows:]
99
100
 
100
101
  def get_key(row):
101
102
  value = row[col_index]
@@ -541,11 +542,11 @@ def insert_fixed_scale_image(sheet, cell, image_path, scale=1.0):
541
542
 
542
543
  return None
543
544
 
544
- def InsertImageV2(app, wb, sheet, columns=None, platform='shein', img_width=150, img_save_key=None, dir_name=None, cell_height_with_img=False):
545
+ def InsertImageV2(sheet, columns=None, platform='shein', img_width=150, img_save_key=None, dir_name=None, cell_height_with_img=False):
545
546
  if not columns:
546
547
  return
547
548
 
548
- minimize(app)
549
+ minimize(sheet.book.app)
549
550
 
550
551
  # 清空所有图片
551
552
  clear_all_pictures(sheet)
@@ -1162,6 +1163,9 @@ def check_data(data):
1162
1163
  log(len(row), row)
1163
1164
 
1164
1165
  def write_data(excel_path, sheet_name, data, format_to_text_colunm=None):
1166
+ log('write_data入参:', excel_path, sheet_name, 'data', format_to_text_colunm)
1167
+ close_excel_file(excel_path)
1168
+
1165
1169
  app, wb, sheet = open_excel(excel_path, sheet_name)
1166
1170
  # 清空工作表中的所有数据
1167
1171
  sheet.clear()
@@ -1174,8 +1178,8 @@ def write_data(excel_path, sheet_name, data, format_to_text_colunm=None):
1174
1178
  wb.save()
1175
1179
  close_excel(app, wb)
1176
1180
 
1177
- def colorize_by_field(app, wb, sheet, field):
1178
- minimize(app)
1181
+ def colorize_by_field(sheet, field):
1182
+ minimize(sheet.book.app)
1179
1183
  # 读取数据
1180
1184
  field_column = find_column_by_data(sheet, 1, field) # 假设 SPU 在 C 列
1181
1185
  if field_column is None:
@@ -2405,6 +2409,7 @@ def format_excel_with_lock(excel_path, sheet_name, format_func, *args, **kwargs)
2405
2409
  log(f"格式化失败: {e}")
2406
2410
  return False
2407
2411
 
2412
+ # 经过观察 fortmat时 传入函数需要为类函数且第二个参数必须是 sheet
2408
2413
  def batch_excel_operations(excel_path, operations):
2409
2414
  """
2410
2415
  批量 Excel 操作函数,一次性打开 Excel 执行多个操作
@@ -2439,21 +2444,36 @@ def batch_excel_operations(excel_path, operations):
2439
2444
  sheet.activate()
2440
2445
 
2441
2446
  if operation_type == 'write':
2442
- data, format_to_text_colunm = args[:2]
2447
+ data, format_to_text_colunm = args[0], args[1:] if len(args) > 1 else None
2443
2448
  # 清空工作表
2444
2449
  sheet.clear()
2445
2450
  # 格式化文本列
2446
- format_to_text_v2(sheet, format_to_text_colunm)
2451
+ if format_to_text_colunm:
2452
+ format_to_text_v2(sheet, format_to_text_colunm)
2447
2453
  # 写入数据
2448
2454
  sheet.range('A1').value = data
2449
2455
  log(f"批量操作:写入数据到 {sheet_name}")
2450
2456
 
2451
2457
  elif operation_type == 'format':
2452
2458
  format_func, format_args = args[0], args[1:] if len(args) > 1 else ()
2459
+ log('格式化入参', *format_args)
2453
2460
  # 执行格式化
2454
2461
  format_func(sheet, *format_args)
2455
2462
  log(f"批量操作:格式化工作表 {sheet_name}")
2456
2463
 
2464
+ elif operation_type == 'delete':
2465
+ pass
2466
+ delete_sheet_if_exists(wb, sheet_name)
2467
+
2468
+ elif operation_type == 'move':
2469
+ pass
2470
+ position = args[0]
2471
+ move_sheet_to_position(wb, sheet_name, position)
2472
+
2473
+ elif operation_type == 'active':
2474
+ pass
2475
+ sheet.activate()
2476
+
2457
2477
  # 保存所有更改
2458
2478
  wb.save()
2459
2479
  log(f"批量操作完成: {excel_path}")
@@ -2465,6 +2485,26 @@ def batch_excel_operations(excel_path, operations):
2465
2485
  finally:
2466
2486
  # 释放锁但不关闭 Excel(保持复用)
2467
2487
  excel_lock_manager.release_excel_lock(excel_path)
2488
+ close_excel_with_lock(excel_path, app, wb, True)
2489
+
2490
+ def close_excel_file(file_path):
2491
+ file_path = os.path.abspath(file_path).lower()
2492
+
2493
+ for proc in psutil.process_iter(['pid', 'name']):
2494
+ if proc.info['name'] and proc.info['name'].lower() in ['excel.exe', 'wps.exe']: # 只找 Excel
2495
+ try:
2496
+ for f in proc.open_files():
2497
+ if os.path.abspath(f.path).lower() == file_path:
2498
+ print(f"文件被 Excel 占用 (PID: {proc.pid}),正在关闭进程...")
2499
+ proc.terminate()
2500
+ proc.wait(timeout=3)
2501
+ print("已关闭。")
2502
+ return True
2503
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
2504
+ continue
2505
+
2506
+ print("文件没有被 Excel 占用。")
2507
+ return False
2468
2508
 
2469
2509
  def force_close_excel_file(excel_path):
2470
2510
  """
@@ -365,7 +365,7 @@ class SheinStoreSalesDetailManager:
365
365
  # 如果发生错误,回滚事务
366
366
  session.rollback()
367
367
  print(f"插入数据时发生错误: {e}")
368
- raise
368
+ #raise
369
369
  finally:
370
370
  # 关闭会话
371
371
  session.close()