qrpa 1.1.79__py3-none-any.whl → 1.1.84__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/fun_excel.py CHANGED
@@ -19,6 +19,36 @@ from pathlib import Path
19
19
 
20
20
  from .fun_base import log, sanitize_filename, create_file_path, copy_file, add_https, send_exception
21
21
 
22
+
23
+ def is_valid_image(img_path):
24
+ """
25
+ 验证图片是否有效且可被 Excel 支持
26
+ :param img_path: 图片路径
27
+ :return: True 如果图片有效,否则 False
28
+ """
29
+ if not img_path or not os.path.exists(img_path):
30
+ return False
31
+
32
+ try:
33
+ with Image.open(img_path) as img:
34
+ img.verify() # 验证图片完整性
35
+
36
+ # verify() 后需要重新打开才能继续操作
37
+ with Image.open(img_path) as img:
38
+ img.load() # 尝试加载图片数据
39
+
40
+ # 检查是否是 Excel 支持的格式
41
+ supported_formats = {'JPEG', 'PNG', 'GIF', 'BMP', 'TIFF', 'EMF', 'WMF'}
42
+ if img.format and img.format.upper() not in supported_formats:
43
+ log(f'不支持的图片格式: {img.format}')
44
+ return False
45
+
46
+ return True
47
+ except Exception as e:
48
+ log(f'图片验证失败: {img_path}, 错误: {e}')
49
+ return False
50
+
51
+
22
52
  excel_color_index = {
23
53
  "无色(自动)" : 0, # 透明/默认
24
54
  "黑色" : 1, # #000000
@@ -867,6 +897,11 @@ def InsertImageV2(sheet, columns=None, platform='shein', img_width=150, img_save
867
897
 
868
898
  # 优化图片插入函数调用 (优化点3)
869
899
  try:
900
+ # 先验证图片有效性
901
+ if not is_valid_image(img_path):
902
+ log(f'图片无效或格式不支持,跳过: {img_path}')
903
+ continue
904
+
870
905
  # 使用预计算的位置直接插入图片
871
906
  sheet.pictures.add(img_path, top=top + 2, left=left + 2, width=width - 4, height=width - 4)
872
907
  cell_range.value = None
@@ -1099,6 +1134,11 @@ def InsertImageV3(sheet, columns=None, platform='shein', img_widths=None, img_sa
1099
1134
 
1100
1135
  # 插入图片
1101
1136
  try:
1137
+ # 先验证图片有效性
1138
+ if not is_valid_image(img_path):
1139
+ log(f'图片无效或格式不支持,跳过: {img_path}')
1140
+ continue
1141
+
1102
1142
  # 使用预计算的位置直接插入图片
1103
1143
  sheet.pictures.add(img_path, top=top + 2, left=left + 2, width=width - 4, height=width - 4)
1104
1144
  cell_range.value = None
@@ -264,6 +264,21 @@ class SheinStoreWalletManager:
264
264
  'supplier_id': supplier_id,
265
265
  'is_fp_account': 1 if api_response.get('isFpAccount') else 0,
266
266
  'deposit_flag': api_response.get('depositFlag', 1),
267
+ # 初始化所有字段,避免缺失导致 upsert 失败
268
+ 'currency': None,
269
+ 'withdrawable_amount': None,
270
+ 'no_withdrawable_amount': None,
271
+ 'withdrawing_amount': None,
272
+ 'balance_last_update_time': None,
273
+ 'auto_withdraw_state': 0,
274
+ 'can_withdraw': 1,
275
+ 'no_withdraw_reasons': '[]',
276
+ 'deposit_currency': None,
277
+ 'deposit_amount_paid': None,
278
+ 'deposit_amount_unpaid': None,
279
+ 'deposit_last_update_time': None,
280
+ 'raw_balance_json': None,
281
+ 'raw_deposit_json': None,
267
282
  }
268
283
 
269
284
  # 解析余额信息(取第一个)
@@ -280,6 +295,7 @@ class SheinStoreWalletManager:
280
295
  'can_withdraw': 1 if balance.get('canWithdraw') else 0,
281
296
  'no_withdraw_reasons': json.dumps(balance.get('noWithdrawReasons', []), ensure_ascii=False),
282
297
  })
298
+ record['raw_balance_json'] = json.dumps(balance_list, ensure_ascii=False)
283
299
 
284
300
  # 解析保证金信息(取第一个)
285
301
  deposit_list = api_response.get('depositList', [])
@@ -291,10 +307,7 @@ class SheinStoreWalletManager:
291
307
  'deposit_amount_unpaid': deposit.get('depositAmountUnPaid'),
292
308
  'deposit_last_update_time': deposit.get('lastUpdateTime'),
293
309
  })
294
-
295
- # 保存原始数据
296
- record['raw_balance_json'] = json.dumps(balance_list, ensure_ascii=False) if balance_list else None
297
- record['raw_deposit_json'] = json.dumps(deposit_list, ensure_ascii=False) if deposit_list else None
310
+ record['raw_deposit_json'] = json.dumps(deposit_list, ensure_ascii=False)
298
311
 
299
312
  return record
300
313
 
qrpa/shein_lib.py CHANGED
@@ -538,7 +538,11 @@ class SheinLib:
538
538
  result = {
539
539
  'list' : withdraw_list,
540
540
  'count' : total,
541
- 'depositFlag': deposit_flag
541
+ 'depositFlag': deposit_flag,
542
+ # 额外保存店铺信息,供后续导入数据库使用
543
+ 'store_username': self.store_username,
544
+ 'store_name': self.store_name,
545
+ 'supplier_id': supplier_id,
542
546
  }
543
547
 
544
548
  # 缓存结果
@@ -556,15 +560,11 @@ class SheinLib:
556
560
  self.web_page.goto('https://sso.geiwohuo.com/#/mws/seller/new-account-overview')
557
561
  self.web_page.wait_for_load_state('load')
558
562
 
559
- # 缓存文件路径:按店铺缓存文件
563
+ # 缓存文件路径:按店铺缓存文件(不使用缓存,每次都重新拉取)
560
564
  import os
561
565
  cache_dir = f'{self.config.auto_dir}/shein/wallet_balance'
562
566
  os.makedirs(cache_dir, exist_ok=True)
563
567
  cache_file = f'{cache_dir}/wallet_balance_detail_{self.store_username}_{TimeUtils.today_date()}.json'
564
- cached_data = read_dict_from_file(cache_file, 3600 * 12)
565
- if cached_data and len(cached_data) > 0:
566
- log(f'返回缓存的钱包余额详情: {self.store_name}')
567
- return cached_data
568
568
 
569
569
  log(f'正在获取 {self.store_name} 钱包余额详情')
570
570
  url = "https://sso.geiwohuo.com/mws/mwms/sso/balance/query"
@@ -611,6 +611,11 @@ class SheinLib:
611
611
  }
612
612
  result['depositList'].append(deposit_item)
613
613
 
614
+ # 额外保存店铺信息,供后续导入数据库使用
615
+ result['store_username'] = self.store_username
616
+ result['store_name'] = self.store_name
617
+ result['supplier_id'] = supplier_id
618
+
614
619
  # 缓存结果
615
620
  write_dict_to_file(cache_file, result)
616
621
 
qrpa/shein_ziniao.py CHANGED
@@ -9,6 +9,7 @@ import time, datetime
9
9
  import traceback
10
10
  import uuid
11
11
  import json
12
+ import ctypes
12
13
  from concurrent.futures import ThreadPoolExecutor
13
14
  from typing import Literal, Optional, Callable, List, Dict, Any
14
15
 
@@ -474,6 +475,33 @@ class ZiniaoRunner:
474
475
  threads_num: int = 3,
475
476
  ):
476
477
  """主执行入口"""
478
+ global mem_gb
479
+
480
+ def _get_total_memory_gb() -> int:
481
+ try:
482
+ import psutil
483
+ total_bytes = psutil.virtual_memory().total
484
+ except Exception:
485
+ if platform.system() == 'Windows':
486
+ class MemoryStatus(ctypes.Structure):
487
+ _fields_ = [
488
+ ('dwLength', ctypes.c_ulong),
489
+ ('dwMemoryLoad', ctypes.c_ulong),
490
+ ('ullTotalPhys', ctypes.c_ulonglong),
491
+ ('ullAvailPhys', ctypes.c_ulonglong),
492
+ ('ullTotalPageFile', ctypes.c_ulonglong),
493
+ ('ullAvailPageFile', ctypes.c_ulonglong),
494
+ ('ullTotalVirtual', ctypes.c_ulonglong),
495
+ ('ullAvailVirtual', ctypes.c_ulonglong),
496
+ ('sullAvailExtendedVirtual', ctypes.c_ulonglong),
497
+ ]
498
+ status = MemoryStatus()
499
+ status.dwLength = ctypes.sizeof(MemoryStatus)
500
+ ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(status))
501
+ total_bytes = status.ullTotalPhys
502
+ else:
503
+ total_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
504
+ return max(1, int(total_bytes // (1024 ** 3)))
477
505
  # 前置执行 if run_prepare:
478
506
  run_prepare()
479
507
 
@@ -494,10 +522,13 @@ class ZiniaoRunner:
494
522
  print(browser_list)
495
523
 
496
524
  # 多线程并发执行任务
497
- max_threads = 1 if (hostname().lower() == 'krrpa' or hostname().lower() == 'jyrpa') else threads_num
498
- if hostname().lower() == 'krrpa3':
499
- max_threads = 6
500
- log(f'当前启用线程数: {max_threads}')
525
+ host = hostname().lower()
526
+ mem_gb = _get_total_memory_gb()
527
+ if host in ('krrpa', 'jyrpa'):
528
+ max_threads = 1
529
+ else:
530
+ max_threads = min(10, max(1, mem_gb // 4))
531
+ log(f'当前启用线程数: {max_threads}, 内存: {mem_gb}GB {mem_gb // 4}')
501
532
  self.task_manager.run_with_thread_pool(browser_list, max_threads, run, task_key, just_store_username, is_skip_store)
502
533
 
503
534
  # 任务重试逻辑
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.1.79
3
+ Version: 1.1.84
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
@@ -5,16 +5,16 @@ qrpa/feishu_bot_app.py,sha256=h7UbtsLkjMIB2XTVYhWEIvdYzPHdXT1DMd39yXuX-x0,21705
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=HYxSinJciciwVSC9dE26nCc17qnbGhTddUdOacI8drQ,10607
8
- qrpa/fun_excel.py,sha256=n6_akVfefYvRqVb8CoS8HtQ4YFmi33XE4wezQPRQbcw,137803
8
+ qrpa/fun_excel.py,sha256=wCJRWowS8F0i0jfg1x_-G8nx0WB9zvR4ifYr2dbf14s,139307
9
9
  qrpa/fun_file.py,sha256=1PNYM71cVWWUjIgrutzw-5mKOGiBAeLrnkXcLMTIBhA,11648
10
10
  qrpa/fun_web.py,sha256=0qmnAulHNR72-BGruQ-RQEVwsR60CkgnQMJIV6obUmU,21501
11
11
  qrpa/fun_win.py,sha256=vMdVh00dsnVz8Wey4Bq7J3RPZAY8B_bI_IKphOX1cE8,7836
12
12
  qrpa/shein_daily_report_model.py,sha256=O8s9qM45WZRoAgxUFRngvmBrc29v7Uf2ye7K8_bcSRg,12214
13
13
  qrpa/shein_excel.py,sha256=VWJVqQ6yZ71zCKSBuJXrnEjtyydkDbtTl8SbfaeVXLs,194648
14
- qrpa/shein_lib.py,sha256=mzmyxk_PiIJZmIR93WwUdrj8iGV8gDeZH5oIvtKeHoE,259253
14
+ qrpa/shein_lib.py,sha256=SJrrn7Fu5Q-rebcWrSNImO-vte8wcA9VHHV48rTycx8,259507
15
15
  qrpa/shein_mysql.py,sha256=2LFNBuGSH0VzsuZ717WH0Grt4rT1BnGhpp_UwSA0lxQ,5140
16
16
  qrpa/shein_sqlite.py,sha256=i4xwNf60eoG6wbWM1R2i5pDdVW1ZMy6uy9nB-c2WKzk,5554
17
- qrpa/shein_ziniao.py,sha256=N9_67JXxPBBY3q1-YoUnpGW91Q_Ty9FgOPT-AnW6iiw,22017
17
+ qrpa/shein_ziniao.py,sha256=i6gHsg1VypR8UKoYTFd2Nk1US1VBW3iXMGUavM_9vCQ,23532
18
18
  qrpa/temu_chrome.py,sha256=jAYv59Z1uoRSVim81EF2R2tEgQYYForiYhWOCKmy_mo,2747
19
19
  qrpa/temu_excel.py,sha256=AqeMyJFjxf8slczbLzK4XKHdIiNZ8T-uDjB6DPj4DwU,6851
20
20
  qrpa/temu_lib.py,sha256=myvlEAE5yNtgt1TUrx8fBRpvw883jpyePTPLd0_7tf4,7131
@@ -29,8 +29,8 @@ qrpa/mysql_module/shein_product_model.py,sha256=jBxamujzYxrhxvZnH_kQW4O0QPzwTru_
29
29
  qrpa/mysql_module/shein_return_order_model.py,sha256=FoxKJPIg2JRCrK-bblfjWgiuBAklarWNU5_4zAE3SIs,37430
30
30
  qrpa/mysql_module/shein_store_model.py,sha256=iTO83PXZNnzaf3qqtIFMFmmQQL9C-pOazOJKXCatVUo,20537
31
31
  qrpa/mysql_module/shein_supplier_info_model.py,sha256=dpGCNOi0pu0-p5weuj9gGkBBe5r68-2P-Jv3FNvZQvQ,29860
32
- qrpa/mysql_module/shein_wallet_model.py,sha256=1v2OGl3n4IxcK1mhBQtb1xzQFlrby17pgob4LHtC5Ko,27662
33
- qrpa-1.1.79.dist-info/METADATA,sha256=xBPNDnVjoCoimiEhy4yVZbiVEaE8uf9g6h68_C66OkU,231
34
- qrpa-1.1.79.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- qrpa-1.1.79.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
36
- qrpa-1.1.79.dist-info/RECORD,,
32
+ qrpa/mysql_module/shein_wallet_model.py,sha256=-eg2Rto_WpepbgD72TjDVVoZcV-ZZ2_JbxW5dFAkE38,28219
33
+ qrpa-1.1.84.dist-info/METADATA,sha256=h3CPADwz2FQAOLrI2zLKikQm7u6kdEw4P0SLABTfEFY,231
34
+ qrpa-1.1.84.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ qrpa-1.1.84.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
36
+ qrpa-1.1.84.dist-info/RECORD,,
File without changes