qrpa 1.0.90__tar.gz → 1.0.91__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 (37) hide show
  1. {qrpa-1.0.90 → qrpa-1.0.91}/PKG-INFO +1 -1
  2. {qrpa-1.0.90 → qrpa-1.0.91}/pyproject.toml +1 -1
  3. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/fun_excel.py +35 -8
  4. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/mysql_module/shein_product_model.py +11 -3
  5. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_excel.py +1 -1
  6. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_lib.py +4 -1
  7. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa.egg-info/PKG-INFO +1 -1
  8. {qrpa-1.0.90 → qrpa-1.0.91}/README.md +0 -0
  9. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/RateLimitedSender.py +0 -0
  10. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/__init__.py +0 -0
  11. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/db_migrator.py +0 -0
  12. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/feishu_bot_app.py +0 -0
  13. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/feishu_client.py +0 -0
  14. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/feishu_logic.py +0 -0
  15. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/fun_base.py +0 -0
  16. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/fun_file.py +0 -0
  17. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/fun_web.py +0 -0
  18. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/fun_win.py +0 -0
  19. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/mysql_module/__init__.py +0 -0
  20. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/mysql_module/shein_return_order_model.py +0 -0
  21. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_daily_report_model.py +0 -0
  22. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_mysql.py +0 -0
  23. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_sqlite.py +0 -0
  24. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/shein_ziniao.py +0 -0
  25. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/temu_chrome.py +0 -0
  26. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/temu_excel.py +0 -0
  27. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/temu_lib.py +0 -0
  28. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/time_utils.py +0 -0
  29. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/time_utils_example.py +0 -0
  30. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa/wxwork.py +0 -0
  31. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa.egg-info/SOURCES.txt +0 -0
  32. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa.egg-info/dependency_links.txt +0 -0
  33. {qrpa-1.0.90 → qrpa-1.0.91}/qrpa.egg-info/top_level.txt +0 -0
  34. {qrpa-1.0.90 → qrpa-1.0.91}/setup.cfg +0 -0
  35. {qrpa-1.0.90 → qrpa-1.0.91}/setup.py +0 -0
  36. {qrpa-1.0.90 → qrpa-1.0.91}/tests/test_db_migrator.py +0 -0
  37. {qrpa-1.0.90 → qrpa-1.0.91}/tests/test_wxwork.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.0.90
3
+ Version: 1.0.91
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.90"
7
+ version = "1.0.91"
8
8
  description = "qsir's rpa library"
9
9
  authors = [{ name = "QSir", email = "1171725650@qq.com" }]
10
10
  readme = "README.md"
@@ -14,6 +14,9 @@ import threading
14
14
  from playwright.sync_api import sync_playwright
15
15
  import psutil
16
16
 
17
+ import os, sys
18
+ from pathlib import Path
19
+
17
20
  from .fun_base import log, sanitize_filename, create_file_path, copy_file, add_https, send_exception
18
21
 
19
22
  excel_color_index = {
@@ -195,13 +198,13 @@ def merge_by_column_v2(sheet, column_name, other_columns):
195
198
  # 更安全的数据获取方式,确保获取完整的数据范围
196
199
  last_row = get_last_row(sheet, col_letter)
197
200
  data = sheet.range(f'{col_letter}1:{col_letter}{last_row}').value
198
-
201
+
199
202
  # 确保data是列表格式
200
203
  if not isinstance(data, list):
201
204
  data = [data]
202
-
205
+
203
206
  log(f'数据范围: {col_letter}1:{col_letter}{last_row}, 数据长度: {len(data)}')
204
-
207
+
205
208
  start_row = 2 # 从第2行开始,跳过表头
206
209
  merge_row_ranges = [] # 用来存储需要合并的行范围 (start_row, end_row)
207
210
 
@@ -211,13 +214,13 @@ def merge_by_column_v2(sheet, column_name, other_columns):
211
214
  col_name = find_column_by_data(sheet, 1, col)
212
215
  if col_name:
213
216
  all_columns.append(col_name)
214
-
217
+
215
218
  log(f'需要合并的列: {all_columns}')
216
219
 
217
220
  # 遍历数据行,从第3行开始比较(因为第1行是表头,第2行是第一个数据行)
218
221
  for row in range(3, len(data) + 1):
219
- log(f'查找 {row}/{len(data)}, 当前值: {data[row-1] if row-1 < len(data) else "超出范围"}, 前一个值: {data[row-2] if row-2 < len(data) else "超出范围"}')
220
-
222
+ log(f'查找 {row}/{len(data)}, 当前值: {data[row - 1] if row - 1 < len(data) else "超出范围"}, 前一个值: {data[row - 2] if row - 2 < len(data) else "超出范围"}')
223
+
221
224
  # 检查值是否发生变化
222
225
  if row <= len(data) and data[row - 1] != data[row - 2]:
223
226
  # 值发生变化,处理前一组
@@ -233,7 +236,7 @@ def merge_by_column_v2(sheet, column_name, other_columns):
233
236
  merge_row_ranges.append((start_row, end_row))
234
237
 
235
238
  log(f'行合并范围: {merge_row_ranges}')
236
-
239
+
237
240
  # 对每个行范围,在所有指定列中执行合并
238
241
  for start_row, end_row in merge_row_ranges:
239
242
  if start_row < end_row: # 只有当开始行小于结束行时才合并(多行)
@@ -756,9 +759,33 @@ def download_images_concurrently(image_urls, platform='shein', img_save_dir=None
756
759
  results = list(executor.map(lambda url: download_img_v2(url, platform, img_save_path=img_save_dir), image_urls))
757
760
  return results
758
761
 
762
+ def get_chromium_executable():
763
+ """
764
+ 返回 Chromium 可执行文件路径,兼容 PyInstaller 打包后的 exe
765
+ """
766
+ # PyInstaller 临时目录
767
+ if getattr(sys, 'frozen', False):
768
+ base_path = Path(sys._MEIPASS)
769
+ else:
770
+ base_path = Path(__file__).parent
771
+
772
+ # 尝试查找打包后的浏览器文件
773
+ possible_path = base_path / "playwright" / "driver" / "package" / "chromium_headless_shell-1169" / "chrome-win" / "headless_shell.exe"
774
+ if possible_path.exists():
775
+ return str(possible_path)
776
+
777
+ # fallback: 系统 Playwright 安装目录
778
+ local_appdata = Path(os.environ.get("LOCALAPPDATA", ""))
779
+ fallback_path = local_appdata / "ms-playwright" / "chromium" / "chrome-win" / "chrome.exe"
780
+ if fallback_path.exists():
781
+ return str(fallback_path)
782
+
783
+ raise FileNotFoundError("Chromium 可执行文件未找到,请先执行 'playwright install' 下载浏览器。")
784
+
759
785
  def download_img_by_chrome(image_url, save_name):
786
+ chromium_path = get_chromium_executable()
760
787
  with sync_playwright() as p:
761
- browser = p.chromium.launch(headless=True) # 运行时可以看到浏览器
788
+ browser = p.chromium.launch(headless=True, executable_path=chromium_path) # 运行时可以看到浏览器
762
789
  context = browser.new_context()
763
790
  page = context.new_page()
764
791
  # 直接通过Playwright下载图片
@@ -64,6 +64,9 @@ class SheinProductSkc(Base):
64
64
  created_at = Column(DateTime, default=datetime.now, comment='创建时间')
65
65
  updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间')
66
66
 
67
+ # 用户备注字段(供后续web界面使用)
68
+ user_notes = Column(Text, nullable=True, comment='用户备注')
69
+
67
70
  # 定义索引
68
71
  __table_args__ = (
69
72
  Index('ix_skc_id', 'skc_id'),
@@ -108,6 +111,7 @@ class SheinProductSku(Base):
108
111
  price = Column(DECIMAL(10, 2), nullable=True, comment='价格')
109
112
  erp_cost_price = Column(DECIMAL(10, 2), nullable=True, comment='ERP成本价')
110
113
  erp_supplier_name = Column(String(100), nullable=True, comment='ERP默认供货商')
114
+ erp_stock = Column(Integer, nullable=True, comment='ERP库存')
111
115
 
112
116
  # 时间戳
113
117
  created_at = Column(DateTime, default=datetime.now, comment='创建时间')
@@ -218,10 +222,10 @@ class SheinProductManager:
218
222
  session = self.Session()
219
223
  try:
220
224
  for data in data_list:
221
-
225
+
222
226
  # 处理SKC数据
223
227
  skc_record = self._upsert_skc_data(session, data)
224
-
228
+
225
229
  # 处理SKU数据
226
230
  for sku_data in data.get('skuList', []):
227
231
  sku_data['local_skc_id'] = skc_record.id
@@ -319,6 +323,7 @@ class SheinProductManager:
319
323
  existing_sku.price = sku_data.get('price')
320
324
  existing_sku.erp_cost_price = sku_data.get('erp_cost_price')
321
325
  existing_sku.erp_supplier_name = sku_data.get('erp_supplier_name')
326
+ existing_sku.erp_stock = sku_data.get('erp_stock')
322
327
  existing_sku.updated_at = datetime.now()
323
328
  else:
324
329
  # 插入新记录
@@ -473,4 +478,7 @@ def example_usage2():
473
478
 
474
479
  if __name__ == "__main__":
475
480
  pass
476
- # example_usage()
481
+ database_url = "mysql+pymysql://root:123wyk@localhost:3306/lz"
482
+ manager = SheinProductManager(database_url)
483
+ manager.create_tables()
484
+ # example_usage()
@@ -2341,7 +2341,7 @@ class SheinExcel:
2341
2341
  self.dealFormula(sheet) # 有空再封装优化
2342
2342
  colorize_by_field(sheet, 'SPU')
2343
2343
  autofit_column(sheet, ['商品信息', '店铺名称', 'SKC点击率/SKC转化率', '自主参与活动'])
2344
- column_to_left(sheet, ['店铺名称', 'SKC点击率/SKC转化率', '自主参与活动'])
2344
+ column_to_left(sheet, ['店铺名称', 'SKC点击率/SKC转化率', '自主参与活动','近7天SKU销量/SKC销量/SKC曝光'])
2345
2345
  specify_column_width(sheet, ['商品标题'], 150 / 6)
2346
2346
  add_borders(sheet)
2347
2347
  InsertImageV2(sheet, ['SKC图片', 'SKU图片'], 'shein', 120, None, None, True)
@@ -887,6 +887,8 @@ class SheinLib:
887
887
  cost_price = self.bridge.get_sku_cost(sku_item['supplierSku'], self.config.erp_source)
888
888
  sku_item['erp_cost_price'] = cost_price if isinstance(cost_price, (int, float)) else None
889
889
  sku_item['erp_supplier_name'] = self.bridge.get_sku_supplier(sku_item['supplierSku'], self.config.erp_source)
890
+ stock = self.bridge.get_sku_stock(sku_item['supplierSku'], self.config.erp_source)
891
+ sku_item['erp_stock'] = stock if isinstance(stock, (int, float)) else None
890
892
 
891
893
  cache_file = f'{self.config.auto_dir}/shein/product/skc_list_{self.store_username}.json'
892
894
  write_dict_to_file_ex(cache_file, {self.store_username: skc_list}, [self.store_username])
@@ -2314,6 +2316,7 @@ class SheinLib:
2314
2316
  skc = str(spu_info['skc'])
2315
2317
  # if not shein_db.exists_sales_1_days_ago(skc):
2316
2318
  # log(f'未查到昨天销量: {skc}')
2319
+ self.get_skc_week_actual_sales(skc)
2317
2320
  self.get_skc_sales(skc, date_60_days_ago, date_1_days_ago)
2318
2321
  skcCode = spu_info['supplierCode']
2319
2322
  product_name = DictSpuInfo[spu]['product_name_en']
@@ -2434,7 +2437,7 @@ class SheinLib:
2434
2437
  # SKC趋势数据
2435
2438
  sku_item.append(skc_trend.get('saleCnt', 0)) # SKC近7天销量
2436
2439
  sku_item.append(skc_trend.get('epsUvIdx', 0)) # SKC近7天曝光人数
2437
- sku_item.append(skc_trend.get('goodsUvIdx', 0)) # SKC近7天商详访客
2440
+ sku_item.append(skc_trend.get('goodsUv', 0)) # SKC近7天商详访客
2438
2441
  sku_item.append(skc_trend.get('epsGdsCtrIdx', 0)) # SKC近7天点击率
2439
2442
  sku_item.append(skc_trend.get('payUvIdx', 0)) # SKC近7天支付人数
2440
2443
  sku_item.append(skc_trend.get('gdsPayCtrIdx', 0)) # SKC近7天支付率
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.0.90
3
+ Version: 1.0.91
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes