qrpa 1.1.40__py3-none-any.whl → 1.1.42__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/shein_lib.py CHANGED
@@ -1066,6 +1066,126 @@ class SheinLib:
1066
1066
  write_dict_to_file(cache_file, info)
1067
1067
  return info
1068
1068
 
1069
+ def product_month_analysis(self, start_date, end_date):
1070
+ # 店铺信息包含 店铺名称 skc上架状态 skc商品层级 统计周期
1071
+ # 商品信息包含 SPU,SKC,商家SKC,质量等级,商品分类,上架日期,上架天数
1072
+ # SKU信息包含 商家SKU,属性集
1073
+ # 前9列均是skc维度,从SKU信息开始 后面是SKU维度
1074
+ excel_data = [
1075
+ ['店铺信息', '商品信息', 'SKC图片', '30天SKC曝光', '30天SKC点击率', '30天SKC转化率', '评论数', '差评率', '客单退货件数', 'SKU信息', 'SKU图片', 'SKU30天销量', '销售额', '核价', '成本', '30天利润', '30天利润率', 'skc']
1076
+ ]
1077
+ excel_data2 = [
1078
+ ['店铺信息', '商品信息', 'SKC图片', '日期', 'SKC销量', 'SKC曝光', 'SKC点击率', 'SKC转化率', 'skc']
1079
+ ]
1080
+ skc_list = self.get_bak_base_info()
1081
+ cache_file = f'{self.config.auto_dir}/shein/sku_price/sku_price_{self.store_username}.json'
1082
+ dict_sku = read_dict_from_file(cache_file)
1083
+ cache_file = f'{self.config.auto_dir}/shein/quality_label/quality_label_{self.store_username}.json'
1084
+ dict_quality_label = read_dict_from_file(cache_file)
1085
+
1086
+ cache_file_analysis = f'{self.config.auto_dir}/shein/product_analysis/skc_skc_analysis_{self.store_username}_{start_date}_{end_date}.json'
1087
+ dict_analysis = read_dict_from_file(cache_file_analysis)
1088
+
1089
+ for skc_item in skc_list:
1090
+ categoryName = skc_item['categoryName']
1091
+ spu = skc_item['spu'] # SPU
1092
+ skc = skc_item['skc'] # SKC
1093
+ supplierCode = skc_item['supplierCode'] # 商家SKC
1094
+ skc_img = skc_item['picUrl'] # SKC图片
1095
+ shelfDate = skc_item['shelfDate'] # 上架日期
1096
+ shelfDays = skc_item['shelfDays'] # 上架天数
1097
+ shelfStatusName = skc_item['shelfStatus']['name'] # 上架状态
1098
+ quality_label = dict_quality_label.get(skc, {}).get('name', '') # 质量等级
1099
+ if quality_label == '无判断':
1100
+ quality_label = ''
1101
+
1102
+ if shelfStatusName == '待上架':
1103
+ log('商品未上架跳过:', skc)
1104
+ continue
1105
+
1106
+ goods_level = skc_item.get('goodsLevel', {}).get('name', '-')
1107
+ if goods_level in ['自主停产', '退供款']:
1108
+ log(f'商品 {goods_level} 跳过:', skc)
1109
+ continue
1110
+
1111
+ dict_sku_sales = self.get_skc_actual_sales_dict(skc, start_date, end_date)
1112
+ dict_skc_trend = self.get_skc_trend(spu, skc, start_date, end_date)
1113
+
1114
+ # 只有当有趋势数据时才添加
1115
+ if dict_skc_trend:
1116
+ for stat_date, dict_item in dict_skc_trend.items():
1117
+
1118
+ store_info = f'{self.store_username}\n{self.store_name}\n({shelfStatusName})\n{goods_level}\n{start_date}\n{end_date}'
1119
+ product_info = f'SPU: {spu}\nSKC: {skc}\n商家SKC: {supplierCode}\n商品分类: {categoryName}\n上架日期: {shelfDate}\n上架天数: {shelfDays}\n质量等级: {quality_label}'
1120
+
1121
+ row_item2 = []
1122
+ row_item2.append(store_info)
1123
+ row_item2.append(product_info)
1124
+ row_item2.append(skc_img)
1125
+ row_item2.append(stat_date)
1126
+ row_item2.append(dict_item.get('saleCnt', 0))
1127
+ row_item2.append(dict_item.get('epsUvIdx', 0))
1128
+ row_item2.append(dict_item.get('epsGdsCtrIdx', 0))
1129
+ row_item2.append(dict_item.get('gdsPayCtrIdx', 0))
1130
+ row_item2.append(skc if skc else '') # 确保 skc 不为 None
1131
+ excel_data2.append(row_item2)
1132
+
1133
+ for sku_item in skc_item['skuList']:
1134
+ supplierSku = sku_item['supplierSku'] # 商家SKU
1135
+ attr = sku_item['attr'] # 属性集
1136
+ sku = sku_item['skuCode'] # SKU
1137
+
1138
+ c30dSaleCnt = sku_item['c30dSaleCnt'] # 近30天销量
1139
+ if attr == '合计' or int(c30dSaleCnt) == 0:
1140
+ log(f'跳过: {supplierSku},近30天销量: {c30dSaleCnt}')
1141
+ continue
1142
+
1143
+ price = dict_sku[sku]
1144
+
1145
+ store_info = f'{self.store_username}\n{self.store_name}\n({shelfStatusName})\n{goods_level}\n{start_date}\n{end_date}'
1146
+ product_info = f'SPU: {spu}\nSKC: {skc}\n商家SKC: {supplierCode}\n商品分类: {categoryName}\n上架日期: {shelfDate}\n上架天数: {shelfDays}\n质量等级: {quality_label}'
1147
+
1148
+ epsUvIdx = dict_analysis.get(skc, {}).get('epsUvIdx', 0)
1149
+ epsGdsCtrIdx = dict_analysis.get(skc, {}).get('epsGdsCtrIdx', 0)
1150
+ gdsPayCtrIdx = dict_analysis.get(skc, {}).get('gdsPayCtrIdx', 0)
1151
+ totalCommentCnt = dict_analysis.get(skc, {}).get('totalCommentCnt', 0)
1152
+ badCommentRate = dict_analysis.get(skc, {}).get('badCommentRate', 0)
1153
+ returnOrderCnt = dict_analysis.get(skc, {}).get('returnOrderCnt', 0)
1154
+
1155
+ sku_info = f'平台SKU: {sku}\n商家SKU: {supplierSku}\n属性集: {attr}'
1156
+ sku_img = self.bridge.get_sku_img(supplierSku, 'mb')
1157
+ # cost_price = self.bridge.get_sku_cost(sku_item['supplierSku'], self.config.erp_source)
1158
+ cost_price = self.bridge.get_sku_cost(sku_item['supplierSku'], 'mb')
1159
+
1160
+ row_item = []
1161
+ row_item.append(store_info)
1162
+ row_item.append(product_info)
1163
+ row_item.append(skc_img)
1164
+ row_item.append(epsUvIdx)
1165
+ row_item.append(epsGdsCtrIdx)
1166
+ row_item.append(gdsPayCtrIdx)
1167
+ row_item.append(totalCommentCnt)
1168
+ row_item.append(badCommentRate)
1169
+ row_item.append(returnOrderCnt)
1170
+ row_item.append(sku_info)
1171
+ row_item.append(sku_img)
1172
+ row_item.append(dict_sku_sales.get(sku, 0))
1173
+ row_item.append('') # 销售额(公式计算)
1174
+ row_item.append(price) # 核价
1175
+ row_item.append(cost_price) # 成本
1176
+ row_item.append('') # 30天利润(公式计算)
1177
+ row_item.append('') # 30天利润率(公式计算)
1178
+ row_item.append(skc)
1179
+ excel_data.append(row_item)
1180
+
1181
+
1182
+ cache_file = f'{self.config.auto_dir}/shein/product_analysis/product_analysis_{TimeUtils.today_date()}.json'
1183
+ write_dict_to_file_ex(cache_file, {self.store_username: excel_data}, [self.store_username])
1184
+
1185
+ cache_file = f'{self.config.auto_dir}/shein/product_analysis/product_analysis_2_{TimeUtils.today_date()}.json'
1186
+ write_dict_to_file_ex(cache_file, {self.store_username: excel_data2}, [self.store_username])
1187
+ return excel_data
1188
+
1069
1189
  def get_product(self):
1070
1190
  excel_data = [
1071
1191
  ['店铺信息', '产品信息', 'SKC', '商家SKC', 'SKC图片', '商家SKU', '属性集', '近7天销量', '近30天销量', '核价', 'ERP成本价', '近7天利润', '近30天利润', '导出时间', 'SPU', 'SKC_FOR_STAT']
@@ -1231,6 +1351,63 @@ class SheinLib:
1231
1351
  detail_file = f'{self.config.auto_dir}/shein/product/product_detail_file.json'
1232
1352
  write_dict_to_file_ex(detail_file, {self.store_username: dict_product_detail}, [self.store_username])
1233
1353
 
1354
+ def get_skc_diagnose_dict(self, start_date="", end_date=""):
1355
+ log(f'获取商品分析某个月的字典 {start_date} {end_date} {self.store_name} {self.store_username}')
1356
+
1357
+ cache_file_analysis = f'{self.config.auto_dir}/shein/product_analysis/skc_skc_analysis_{self.store_username}_{start_date}_{end_date}.json'
1358
+
1359
+ dict_analysis = read_dict_from_file(cache_file_analysis)
1360
+ if len(dict_analysis) > 0:
1361
+ return dict_analysis
1362
+
1363
+ dt_goods = self.get_dt_time_goods()
1364
+ if not TimeUtils.is_yesterday_date(dt_goods, "%Y%m%d"):
1365
+ log("数据尚未更新: dt_goods:", dt_goods)
1366
+ return []
1367
+
1368
+ url = "https://sso.geiwohuo.com/sbn/new_goods/get_skc_diagnose_list"
1369
+ page_num = 1
1370
+ page_size = 100
1371
+ payload = {
1372
+ "areaCd" : "cn",
1373
+ "dt" : dt_goods,
1374
+ "countrySite": [
1375
+ "shein-all"
1376
+ ],
1377
+ "startDate" : start_date.replace('-', ""),
1378
+ "endDate" : end_date.replace('-', ""),
1379
+ "pageNum" : page_num,
1380
+ "pageSize" : page_size,
1381
+ }
1382
+ response_text = fetch(self.web_page, url, payload)
1383
+ error_code = response_text.get('code')
1384
+ if str(error_code) != '0':
1385
+ raise send_exception(json.dumps(response_text, ensure_ascii=False))
1386
+ spu_list = response_text['info']['data']
1387
+ total = response_text['info']['meta']['count']
1388
+ totalPage = math.ceil(total / page_size)
1389
+
1390
+ for page in range(2, totalPage + 1):
1391
+ log(f'获取商品分析列表(最近上架的) 第{page}/{totalPage}页')
1392
+ payload.update({"pageNum": page})
1393
+ response_text = fetch(self.web_page, url, payload)
1394
+ spu_list_new = response_text['info']['data']
1395
+ spu_list += spu_list_new
1396
+ time.sleep(0.3)
1397
+
1398
+ cache_file = f'{self.config.auto_dir}/shein/product_analysis/skc_dict_{self.store_username}_{start_date}_{end_date}.json'
1399
+ write_dict_to_file(cache_file, spu_list)
1400
+
1401
+ for skc_item in spu_list:
1402
+ skc = skc_item['skc']
1403
+ skc_item['store_username'] = self.store_username
1404
+ skc_item['store_name'] = self.store_name
1405
+ dict_analysis[skc] = skc_item
1406
+
1407
+ write_dict_to_file(cache_file_analysis, dict_analysis)
1408
+
1409
+ return dict_analysis
1410
+
1234
1411
  def get_skc_diagnose_list(self, shelf_date_begin="", shelf_date_end=""):
1235
1412
  log(f'获取商品分析列表(最近上架的或在售的) {shelf_date_begin} {shelf_date_end} {self.store_name} {self.store_username}')
1236
1413
 
@@ -1466,6 +1643,7 @@ class SheinLib:
1466
1643
 
1467
1644
  skc_list = [item['skc'] for item in spu_list]
1468
1645
  self.get_activity_label(skc_list)
1646
+ self.get_quality_label(skc_list)
1469
1647
  self.get_preemption_list(skc_list)
1470
1648
  self.get_sku_price_v2(skc_list)
1471
1649
  self.get_stock_advice(skc_list)
@@ -1482,6 +1660,7 @@ class SheinLib:
1482
1660
 
1483
1661
  skc_list = [item['skc'] for item in new_spu_list]
1484
1662
  self.get_activity_label(skc_list)
1663
+ self.get_quality_label(skc_list)
1485
1664
  self.get_preemption_list(skc_list)
1486
1665
  self.get_sku_price_v2(skc_list)
1487
1666
  self.get_stock_advice(skc_list)
@@ -2549,6 +2728,36 @@ class SheinLib:
2549
2728
 
2550
2729
  write_dict_to_file(cache_file, dict_activity_price)
2551
2730
 
2731
+ def get_skc_actual_sales_dict(self, skc, first_day, last_day):
2732
+ cache_file = f'{self.config.auto_dir}/shein/cache/actual_sales_{skc}_{first_day}_{last_day}.json'
2733
+ if datetime.now().hour >= 9:
2734
+ DictSkuSales = read_dict_from_file(cache_file)
2735
+ else:
2736
+ DictSkuSales = read_dict_from_file(cache_file, 1800)
2737
+ if len(DictSkuSales) > 0:
2738
+ return DictSkuSales
2739
+
2740
+ url = f"https://sso.geiwohuo.com/idms/sale-trend/detail"
2741
+ payload = {
2742
+ "skc" : skc,
2743
+ "startDate": first_day,
2744
+ "endDate" : last_day,
2745
+ "daysToAdd": 0
2746
+ }
2747
+ response_text = fetch(self.web_page, url, payload)
2748
+ error_code = response_text.get('code')
2749
+ if str(error_code) != '0':
2750
+ log(response_text)
2751
+ return {}
2752
+ info = response_text['info']
2753
+ for sale_item in info['actualSalesVolumeMap']:
2754
+ sku = sale_item['skuCode']
2755
+ if sku is not None:
2756
+ DictSkuSales[sku] = sale_item['actualSalesVolume']
2757
+
2758
+ write_dict_to_file(cache_file, DictSkuSales)
2759
+ return DictSkuSales
2760
+
2552
2761
  def get_skc_week_actual_sales(self, skc):
2553
2762
  first_day, last_day = TimeUtils.get_past_7_days_range()
2554
2763
  cache_file = f'{self.config.auto_dir}/shein/cache/{skc}_{first_day}_{last_day}.json'
@@ -2601,6 +2810,22 @@ class SheinLib:
2601
2810
 
2602
2811
  return dict
2603
2812
 
2813
+ def get_quality_label(self, skc_list):
2814
+ url = f"https://sso.geiwohuo.com/idms/goods-skc/quality-label"
2815
+ payload = skc_list
2816
+ response_text = fetch(self.web_page, url, payload)
2817
+ error_code = response_text.get('code')
2818
+ if str(error_code) != '0':
2819
+ raise send_exception(json.dumps(response_text, ensure_ascii=False))
2820
+ dict = response_text['info']
2821
+
2822
+ cache_file = f'{self.config.auto_dir}/shein/quality_label/quality_label_{self.store_username}.json'
2823
+ dict_label = read_dict_from_file(cache_file)
2824
+ dict_label.update(dict)
2825
+ write_dict_to_file(cache_file, dict_label)
2826
+
2827
+ return dict
2828
+
2604
2829
  def get_activity_label(self, skc_list):
2605
2830
  url = f"https://sso.geiwohuo.com/idms/goods-skc/activity-label"
2606
2831
  payload = skc_list
@@ -3037,6 +3262,51 @@ class SheinLib:
3037
3262
 
3038
3263
  return product_sku_list
3039
3264
 
3265
+ # 获取一个skc一段时间内的销售趋势(商品明细中的)
3266
+ def get_skc_trend(self, spu, skc, start_date, end_date):
3267
+ dt = self.get_dt_time_goods()
3268
+
3269
+ # 将字符串转换为日期对象
3270
+ date1 = datetime.strptime(end_date, "%Y-%m-%d").date()
3271
+ date2 = datetime.strptime(dt, "%Y%m%d").date()
3272
+ if date1 > date2:
3273
+ log(f'get_skc_trend: dt:{dt} < end_date: {end_date}')
3274
+
3275
+ cache_file = f'{self.config.auto_dir}/shein/dict/skc_trend_{skc}_{start_date}_{end_date}.json'
3276
+ DictSkc = read_dict_from_file(cache_file)
3277
+ if len(DictSkc) > 0:
3278
+ return DictSkc
3279
+
3280
+ url = f"https://sso.geiwohuo.com/sbn/new_goods/get_skc_diagnose_trend"
3281
+ payload = {
3282
+ "areaCd" : "cn",
3283
+ "countrySite": [
3284
+ "shein-all"
3285
+ ],
3286
+ "dt" : dt,
3287
+ "endDate" : end_date.replace('-', ''),
3288
+ "spu" : [spu],
3289
+ "skc" : [skc],
3290
+ "startDate" : start_date.replace('-', ''),
3291
+ }
3292
+ response_text = fetch(self.web_page, url, payload)
3293
+ log(response_text)
3294
+ error_code = response_text.get('code')
3295
+ if str(error_code) != '0':
3296
+ raise send_exception(json.dumps(response_text, ensure_ascii=False))
3297
+
3298
+ data_list = response_text['info']
3299
+ DictSkc = {}
3300
+ for date_item in data_list:
3301
+ dataDate = date_item['dataDate']
3302
+ # epsUvIdx = date_item['epsUvIdx']
3303
+ # saleCnt = date_item['saleCnt']
3304
+ DictSkc[dataDate] = date_item
3305
+
3306
+ log('len(DictSkc)', len(DictSkc))
3307
+ write_dict_to_file(cache_file, DictSkc)
3308
+ return DictSkc
3309
+
3040
3310
  # 获取一个skc一周内的销售趋势(商品明细中的)
3041
3311
  def get_dict_skc_week_trend_v2(self, spu, skc, start_from=None):
3042
3312
  dt = self.get_dt_time()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.1.40
3
+ Version: 1.1.42
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
@@ -5,13 +5,13 @@ qrpa/feishu_bot_app.py,sha256=Gjvv7D-OS-55mirP9xKYkIDNrIEWgWub7YwZkXDv4yo,9185
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=bs-dvhTPE1laKQVZQOlJ48PTfDaHMCYDmr1HPgvTY9w,116829
8
+ qrpa/fun_excel.py,sha256=xic9CWZVNEK9EckZdhhGn02e-n3ddmocU4VdO9LnXiE,134992
9
9
  qrpa/fun_file.py,sha256=1PNYM71cVWWUjIgrutzw-5mKOGiBAeLrnkXcLMTIBhA,11648
10
10
  qrpa/fun_web.py,sha256=9YuVy_wps9Ty_FBZ91W2R0iKgC2IViaJjHbyuUgngGs,11599
11
11
  qrpa/fun_win.py,sha256=vMdVh00dsnVz8Wey4Bq7J3RPZAY8B_bI_IKphOX1cE8,7836
12
12
  qrpa/shein_daily_report_model.py,sha256=O8s9qM45WZRoAgxUFRngvmBrc29v7Uf2ye7K8_bcSRg,12214
13
- qrpa/shein_excel.py,sha256=jQrAILYr1US4RlM0BfMKBpS-mu0vUs89EMshJ8dL7Dg,165740
14
- qrpa/shein_lib.py,sha256=usWog94MmDmXpmc0ZFjrQY1yIbPp-6VYYNG7kFxqNVc,193261
13
+ qrpa/shein_excel.py,sha256=HHFWgEhMlKo3BnOrG9f27qwWCgv6MrwJaVZen4fJQk4,173948
14
+ qrpa/shein_lib.py,sha256=W9puz2gjzi5bkv87L6iT7HdIUcM54D2ZfuzclAL7_6E,206361
15
15
  qrpa/shein_mysql.py,sha256=MxbiRSH0gaTtW4ET7lVWRNY4NLOrMLGXO_4STptE1pU,4562
16
16
  qrpa/shein_sqlite.py,sha256=i4xwNf60eoG6wbWM1R2i5pDdVW1ZMy6uy9nB-c2WKzk,5554
17
17
  qrpa/shein_ziniao.py,sha256=YN7g6m84-vyDyePssfR41lqwaROz-km0-rJ8qY-jhy0,21416
@@ -24,10 +24,10 @@ qrpa/wxwork.py,sha256=Vy8PGEtlTWt4-1laVhuqpJUGCFH2JymgbjvH00aaBog,10946
24
24
  qrpa/mysql_module/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  qrpa/mysql_module/new_product_analysis_model.py,sha256=j_9WpGK21XBr_bProhUV6IWaDXWlKg1_jQsImsqK4L8,20272
26
26
  qrpa/mysql_module/shein_ledger_model.py,sha256=KGKfGyzS00rbBZhiZhAzypwYPGs7OdfRLnH2ea36Vm8,18161
27
- qrpa/mysql_module/shein_product_model.py,sha256=KiXMjPT93XkANCM53cCFaISja0sTmAWsionFrRy8DQ4,18773
27
+ qrpa/mysql_module/shein_product_model.py,sha256=FGbcjsz-MHdAkonMAyE7om7N1a2_OttgHsm35oSBDNM,19171
28
28
  qrpa/mysql_module/shein_return_order_model.py,sha256=8xvKhOzpcJS5FHfyA33UednaqRNCyXo3qeXBzwTXeN8,25993
29
29
  qrpa/mysql_module/shein_store_model.py,sha256=RTj9cqexewHglHm1JNTe8iU0vJueHBLltdap-gvGxaY,20536
30
- qrpa-1.1.40.dist-info/METADATA,sha256=gGYtDe06Kp4dig395bxKmeJJAvrtsH1moq9wCPM4NoU,231
31
- qrpa-1.1.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- qrpa-1.1.40.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
33
- qrpa-1.1.40.dist-info/RECORD,,
30
+ qrpa-1.1.42.dist-info/METADATA,sha256=0-NfISNPsLB-dmC16zPTqMFSz5E4262xMXqt6pvVDYc,231
31
+ qrpa-1.1.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ qrpa-1.1.42.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
33
+ qrpa-1.1.42.dist-info/RECORD,,
File without changes