qrpa 1.1.32__py3-none-any.whl → 1.1.34__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/RateLimitedSender.py +45 -45
- qrpa/__init__.py +31 -31
- qrpa/db_migrator.py +600 -600
- qrpa/feishu_bot_app.py +267 -267
- qrpa/fun_base.py +339 -339
- qrpa/fun_excel.py +3059 -3059
- qrpa/fun_file.py +318 -318
- qrpa/fun_web.py +258 -258
- qrpa/fun_win.py +198 -198
- qrpa/mysql_module/new_product_analysis_model.py +429 -0
- qrpa/mysql_module/shein_ledger_model.py +468 -468
- qrpa/mysql_module/shein_product_model.py +484 -484
- qrpa/mysql_module/shein_return_order_model.py +569 -569
- qrpa/shein_daily_report_model.py +375 -375
- qrpa/shein_excel.py +3125 -3125
- qrpa/shein_lib.py +3932 -3609
- qrpa/shein_mysql.py +22 -0
- qrpa/shein_sqlite.py +153 -153
- qrpa/shein_ziniao.py +529 -529
- qrpa/temu_chrome.py +56 -56
- qrpa/temu_excel.py +139 -139
- qrpa/temu_lib.py +154 -154
- qrpa/time_utils.py +882 -882
- qrpa/time_utils_example.py +243 -243
- qrpa/wxwork.py +318 -318
- {qrpa-1.1.32.dist-info → qrpa-1.1.34.dist-info}/METADATA +1 -1
- qrpa-1.1.34.dist-info/RECORD +32 -0
- qrpa-1.1.32.dist-info/RECORD +0 -31
- {qrpa-1.1.32.dist-info → qrpa-1.1.34.dist-info}/WHEEL +0 -0
- {qrpa-1.1.32.dist-info → qrpa-1.1.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
新品分析数据模型
|
|
5
|
+
使用SQLAlchemy定义shein_new_product_analysis表结构
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import create_engine, Column, Integer, String, DECIMAL, Date, BigInteger, DateTime, Text, Index
|
|
9
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
10
|
+
from sqlalchemy.orm import sessionmaker
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
# 创建基类
|
|
15
|
+
Base = declarative_base()
|
|
16
|
+
|
|
17
|
+
class SheinNewProductAnalysis(Base):
|
|
18
|
+
"""
|
|
19
|
+
希音新品分析表
|
|
20
|
+
存储SKC新品分析相关数据
|
|
21
|
+
"""
|
|
22
|
+
__tablename__ = 'shein_new_product_analysis'
|
|
23
|
+
|
|
24
|
+
# 主键ID
|
|
25
|
+
id = Column(BigInteger, primary_key=True, autoincrement=True, comment='主键ID')
|
|
26
|
+
|
|
27
|
+
# 店铺信息
|
|
28
|
+
store_username = Column(String(100), nullable=False, comment='店铺账号')
|
|
29
|
+
store_name = Column(String(200), nullable=True, comment='店铺名称')
|
|
30
|
+
|
|
31
|
+
# 日期信息
|
|
32
|
+
stat_date = Column(Date, nullable=False, comment='统计日期')
|
|
33
|
+
shelf_date = Column(Date, nullable=True, comment='上架日期')
|
|
34
|
+
|
|
35
|
+
# SKC信息
|
|
36
|
+
skc = Column(String(100), nullable=False, comment='平台SKC')
|
|
37
|
+
sku_supplier_no = Column(String(100), nullable=True, comment='商家SKC')
|
|
38
|
+
layer_nm = Column(String(100), nullable=True, comment='商品层级')
|
|
39
|
+
goods_name = Column(String(500), nullable=True, comment='商品标题')
|
|
40
|
+
img_url = Column(String(500), nullable=True, comment='SKC图片URL')
|
|
41
|
+
|
|
42
|
+
# 状态标识
|
|
43
|
+
onsale_flag = Column(Integer, nullable=True, default=0, comment='在售标识(0-否,1-是)')
|
|
44
|
+
sale_flag = Column(Integer, nullable=True, default=0, comment='上架标识(0-否,1-是)')
|
|
45
|
+
|
|
46
|
+
# 销售数据
|
|
47
|
+
sale_cnt = Column(Integer, nullable=True, default=0, comment='销量')
|
|
48
|
+
pay_order_cnt = Column(Integer, nullable=True, default=0, comment='支付订单数')
|
|
49
|
+
goods_uv = Column(Integer, nullable=True, default=0, comment='商品访客数')
|
|
50
|
+
cart_uv_idx = Column(Integer, nullable=True, default=0, comment='加车访客')
|
|
51
|
+
eps_uv_idx = Column(Integer, nullable=True, default=0, comment='曝光人数')
|
|
52
|
+
|
|
53
|
+
# 转化率数据
|
|
54
|
+
eps_gds_ctr_idx = Column(DECIMAL(10, 4), nullable=True, comment='点击率')
|
|
55
|
+
gds_pay_ctr_idx = Column(DECIMAL(10, 4), nullable=True, comment='转化率')
|
|
56
|
+
bad_comment_rate = Column(DECIMAL(10, 4), nullable=True, comment='差评率')
|
|
57
|
+
|
|
58
|
+
# 促销活动信息(JSON格式)
|
|
59
|
+
prom_inf_ing = Column(Text, nullable=True, comment='活动中的促销活动(JSON)')
|
|
60
|
+
prom_inf_ready = Column(Text, nullable=True, comment='即将开始的促销活动(JSON)')
|
|
61
|
+
|
|
62
|
+
# AB测试信息(JSON格式)
|
|
63
|
+
ab_test = Column(Text, nullable=True, comment='AB测试数据(JSON)')
|
|
64
|
+
|
|
65
|
+
# 分析字段(不参与更新)
|
|
66
|
+
reason_analysis = Column(Text, nullable=True, comment='原因分析')
|
|
67
|
+
optimization_action = Column(Text, nullable=True, comment='优化动作')
|
|
68
|
+
|
|
69
|
+
# 备注
|
|
70
|
+
remark = Column(String(500), nullable=True, comment='备注')
|
|
71
|
+
|
|
72
|
+
# 时间戳
|
|
73
|
+
created_at = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
|
|
74
|
+
updated_at = Column(DateTime, nullable=True, default=datetime.now, onupdate=datetime.now, comment='更新时间')
|
|
75
|
+
|
|
76
|
+
# 创建联合唯一索引
|
|
77
|
+
__table_args__ = (
|
|
78
|
+
Index('idx_date_skc', 'stat_date', 'skc', unique=True),
|
|
79
|
+
Index('idx_stat_date', 'stat_date'),
|
|
80
|
+
Index('idx_skc', 'skc'),
|
|
81
|
+
Index('idx_store_username', 'store_username'),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def __repr__(self):
|
|
85
|
+
return f"<SheinNewProductAnalysis(id={self.id}, store_username='{self.store_username}', skc='{self.skc}', stat_date={self.stat_date})>"
|
|
86
|
+
|
|
87
|
+
class NewProductAnalysisManager:
|
|
88
|
+
"""
|
|
89
|
+
新品分析数据管理器
|
|
90
|
+
提供数据库操作相关方法
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# database_url = f"mysql+pymysql://{config.mysql_username}:{config.mysql_password}@{config.mysql_host}:{config.mysql_port}/{config.mysql_database}"
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def __init__(self, database_url=None):
|
|
97
|
+
"""
|
|
98
|
+
初始化数据库连接
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
database_url (str): 数据库连接URL
|
|
102
|
+
"""
|
|
103
|
+
# if database_url is None:
|
|
104
|
+
# database_url = self.database_url
|
|
105
|
+
print(f"{self.__name__} 连接数据库: {database_url}")
|
|
106
|
+
self.engine = create_engine(database_url, echo=False)
|
|
107
|
+
self.Session = sessionmaker(bind=self.engine)
|
|
108
|
+
|
|
109
|
+
def create_table(self):
|
|
110
|
+
"""
|
|
111
|
+
创建数据表
|
|
112
|
+
"""
|
|
113
|
+
Base.metadata.create_all(self.engine)
|
|
114
|
+
print("数据表创建成功")
|
|
115
|
+
|
|
116
|
+
def insert_data(self, data_list):
|
|
117
|
+
"""
|
|
118
|
+
批量插入数据
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
data_list (list): 数据字典列表
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
int: 成功插入的记录数
|
|
125
|
+
"""
|
|
126
|
+
session = self.Session()
|
|
127
|
+
try:
|
|
128
|
+
insert_count = 0
|
|
129
|
+
for data in data_list:
|
|
130
|
+
# 检查是否存在(根据唯一索引:stat_date + skc)
|
|
131
|
+
existing = session.query(SheinNewProductAnalysis).filter(
|
|
132
|
+
SheinNewProductAnalysis.stat_date == data.get('stat_date'),
|
|
133
|
+
SheinNewProductAnalysis.skc == data.get('skc')
|
|
134
|
+
).first()
|
|
135
|
+
|
|
136
|
+
# 先处理JSON字段转换(无论是新增还是更新都需要)
|
|
137
|
+
# 使用 'in' 判断而不是 'and',确保空列表[]和空字典{}也能被转换
|
|
138
|
+
if 'prom_inf_ing' in data and isinstance(data['prom_inf_ing'], (dict, list)):
|
|
139
|
+
data['prom_inf_ing'] = json.dumps(data['prom_inf_ing'], ensure_ascii=False)
|
|
140
|
+
if 'prom_inf_ready' in data and isinstance(data['prom_inf_ready'], (dict, list)):
|
|
141
|
+
data['prom_inf_ready'] = json.dumps(data['prom_inf_ready'], ensure_ascii=False)
|
|
142
|
+
if 'ab_test' in data and isinstance(data['ab_test'], (dict, list)):
|
|
143
|
+
data['ab_test'] = json.dumps(data['ab_test'], ensure_ascii=False)
|
|
144
|
+
|
|
145
|
+
if existing:
|
|
146
|
+
# 更新现有记录(排除不更新的分析字段)
|
|
147
|
+
exclude_fields = {'reason_analysis', 'optimization_action'}
|
|
148
|
+
for key, value in data.items():
|
|
149
|
+
if key not in exclude_fields:
|
|
150
|
+
setattr(existing, key, value)
|
|
151
|
+
setattr(existing, 'updated_at', datetime.now())
|
|
152
|
+
else:
|
|
153
|
+
# 插入新记录
|
|
154
|
+
new_record = SheinNewProductAnalysis(**data)
|
|
155
|
+
session.add(new_record)
|
|
156
|
+
insert_count += 1
|
|
157
|
+
|
|
158
|
+
session.commit()
|
|
159
|
+
print(f"成功插入/更新 {insert_count} 条记录")
|
|
160
|
+
return insert_count
|
|
161
|
+
except Exception as e:
|
|
162
|
+
session.rollback()
|
|
163
|
+
print(f"插入数据失败: {e}")
|
|
164
|
+
raise
|
|
165
|
+
finally:
|
|
166
|
+
session.close()
|
|
167
|
+
|
|
168
|
+
def get_records_by_date_range(self, store_username, start_date, end_date):
|
|
169
|
+
"""
|
|
170
|
+
根据日期范围查询记录
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
store_username (str): 店铺账号
|
|
174
|
+
start_date (str): 开始日期
|
|
175
|
+
end_date (str): 结束日期
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
list: 记录列表
|
|
179
|
+
"""
|
|
180
|
+
session = self.Session()
|
|
181
|
+
try:
|
|
182
|
+
records = session.query(SheinNewProductAnalysis).filter(
|
|
183
|
+
SheinNewProductAnalysis.store_username == store_username,
|
|
184
|
+
SheinNewProductAnalysis.stat_date >= start_date,
|
|
185
|
+
SheinNewProductAnalysis.stat_date <= end_date
|
|
186
|
+
).all()
|
|
187
|
+
return records
|
|
188
|
+
finally:
|
|
189
|
+
session.close()
|
|
190
|
+
|
|
191
|
+
def get_records_by_skc(self, store_username, skc):
|
|
192
|
+
"""
|
|
193
|
+
根据SKC查询记录
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
store_username (str): 店铺账号
|
|
197
|
+
skc (str): 平台SKC
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
list: 记录列表
|
|
201
|
+
"""
|
|
202
|
+
session = self.Session()
|
|
203
|
+
try:
|
|
204
|
+
records = session.query(SheinNewProductAnalysis).filter(
|
|
205
|
+
SheinNewProductAnalysis.store_username == store_username,
|
|
206
|
+
SheinNewProductAnalysis.skc == skc
|
|
207
|
+
).order_by(SheinNewProductAnalysis.stat_date.desc()).all()
|
|
208
|
+
return records
|
|
209
|
+
finally:
|
|
210
|
+
session.close()
|
|
211
|
+
|
|
212
|
+
def _extract_prom_info(self, prom_list):
|
|
213
|
+
"""
|
|
214
|
+
提取促销活动信息
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
prom_list (list): 促销活动列表
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
list: 提取后的促销活动信息列表
|
|
221
|
+
"""
|
|
222
|
+
if not prom_list:
|
|
223
|
+
return []
|
|
224
|
+
|
|
225
|
+
result = []
|
|
226
|
+
for prom in prom_list:
|
|
227
|
+
prom_info = {
|
|
228
|
+
'promNm' : prom.get('promNm'),
|
|
229
|
+
'promId' : prom.get('promId'),
|
|
230
|
+
'startDate': prom.get('startDate'),
|
|
231
|
+
'endDate' : prom.get('endDate')
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
prom_id = prom.get('promId', '')
|
|
235
|
+
prom_detail = prom.get('promDetail', [])
|
|
236
|
+
|
|
237
|
+
# 根据promId长度判断取哪些字段
|
|
238
|
+
if len(str(prom_id)) > 6 and prom_detail:
|
|
239
|
+
# 营销工具:取第一个detail的数据
|
|
240
|
+
detail = prom_detail[0] if prom_detail else {}
|
|
241
|
+
prom_info['attend_num_sum'] = detail.get('attend_num_sum')
|
|
242
|
+
prom_info['supply_price'] = detail.get('supply_price')
|
|
243
|
+
prom_info['product_act_price'] = detail.get('product_act_price')
|
|
244
|
+
elif prom_detail:
|
|
245
|
+
# 营销活动:取第一个detail的数据
|
|
246
|
+
detail = prom_detail[0] if prom_detail else {}
|
|
247
|
+
prom_info['attend_num'] = detail.get('attend_num')
|
|
248
|
+
prom_info['goods_cost'] = detail.get('goods_cost')
|
|
249
|
+
prom_info['attend_cost'] = detail.get('attend_cost')
|
|
250
|
+
|
|
251
|
+
result.append(prom_info)
|
|
252
|
+
|
|
253
|
+
return result
|
|
254
|
+
|
|
255
|
+
def import_from_json(self, json_data_list):
|
|
256
|
+
"""
|
|
257
|
+
从JSON数据导入到数据库
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
json_data_list (list): JSON数据列表
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
int: 成功导入的记录数
|
|
264
|
+
"""
|
|
265
|
+
print(f"开始处理 {len(json_data_list)} 条JSON数据")
|
|
266
|
+
data_list = []
|
|
267
|
+
skipped_count = 0
|
|
268
|
+
|
|
269
|
+
for idx, item in enumerate(json_data_list, 1):
|
|
270
|
+
# 验证必填字段
|
|
271
|
+
stat_date = item.get('stat_date')
|
|
272
|
+
skc = item.get('skc')
|
|
273
|
+
|
|
274
|
+
if not stat_date:
|
|
275
|
+
print(f"⚠️ 警告: 第 {idx} 条记录缺少必填字段 stat_date (统计日期),跳过该记录")
|
|
276
|
+
skipped_count += 1
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
if not skc:
|
|
280
|
+
print(f"⚠️ 警告: 第 {idx} 条记录缺少必填字段 skc,跳过该记录")
|
|
281
|
+
skipped_count += 1
|
|
282
|
+
continue
|
|
283
|
+
|
|
284
|
+
# 提取促销活动信息
|
|
285
|
+
prom_campaign = item.get('promCampaign', {})
|
|
286
|
+
prom_inf_ing = self._extract_prom_info(prom_campaign.get('promInfIng'))
|
|
287
|
+
prom_inf_ready = self._extract_prom_info(prom_campaign.get('promInfReady'))
|
|
288
|
+
|
|
289
|
+
# 提取AB测试信息(去掉product_name字段)
|
|
290
|
+
ab_test = item.get('ab_test', {})
|
|
291
|
+
if ab_test and isinstance(ab_test, dict):
|
|
292
|
+
ab_test_copy = ab_test.copy()
|
|
293
|
+
ab_test_copy.pop('product_name', None)
|
|
294
|
+
ab_test = ab_test_copy
|
|
295
|
+
|
|
296
|
+
# 构建数据库记录
|
|
297
|
+
record = {
|
|
298
|
+
'store_username' : item.get('store_username'),
|
|
299
|
+
'store_name' : item.get('store_name'),
|
|
300
|
+
'stat_date' : stat_date,
|
|
301
|
+
'shelf_date' : item.get('shelf_date'),
|
|
302
|
+
'skc' : skc,
|
|
303
|
+
'sku_supplier_no' : item.get('skuSupplierNo'),
|
|
304
|
+
'layer_nm' : item.get('layerNm'),
|
|
305
|
+
'goods_name' : item.get('goodsName'),
|
|
306
|
+
'img_url' : item.get('imgUrl'),
|
|
307
|
+
'onsale_flag' : int(item.get('onsaleFlag', 0)),
|
|
308
|
+
'sale_flag' : int(item.get('saleFlag', 0)),
|
|
309
|
+
'sale_cnt' : item.get('saleCnt', 0),
|
|
310
|
+
'pay_order_cnt' : item.get('payOrderCnt', 0),
|
|
311
|
+
'goods_uv' : item.get('goodsUv', 0),
|
|
312
|
+
'cart_uv_idx' : item.get('cartUvIdx', 0),
|
|
313
|
+
'eps_uv_idx' : item.get('epsUvIdx', 0),
|
|
314
|
+
'eps_gds_ctr_idx' : item.get('epsGdsCtrIdx', 0),
|
|
315
|
+
'gds_pay_ctr_idx' : item.get('gdsPayCtrIdx', 0),
|
|
316
|
+
'bad_comment_rate': item.get('badCommentRate', 0),
|
|
317
|
+
'prom_inf_ing' : prom_inf_ing,
|
|
318
|
+
'prom_inf_ready' : prom_inf_ready,
|
|
319
|
+
'ab_test' : ab_test
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
print(f"✓ 处理第 {idx} 条: SKC={record['skc']}, stat_date={stat_date}")
|
|
323
|
+
data_list.append(record)
|
|
324
|
+
|
|
325
|
+
if skipped_count > 0:
|
|
326
|
+
print(f"⚠️ 共跳过 {skipped_count} 条记录(缺少必填字段)")
|
|
327
|
+
|
|
328
|
+
# 调用insert_data方法插入数据
|
|
329
|
+
return self.insert_data(data_list)
|
|
330
|
+
|
|
331
|
+
def delete_records_by_date(self, store_username, stat_date):
|
|
332
|
+
"""
|
|
333
|
+
删除指定日期的记录
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
store_username (str): 店铺账号
|
|
337
|
+
stat_date (str): 统计日期
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
int: 删除的记录数
|
|
341
|
+
"""
|
|
342
|
+
session = self.Session()
|
|
343
|
+
try:
|
|
344
|
+
delete_count = session.query(SheinNewProductAnalysis).filter(
|
|
345
|
+
SheinNewProductAnalysis.store_username == store_username,
|
|
346
|
+
SheinNewProductAnalysis.stat_date == stat_date
|
|
347
|
+
).delete()
|
|
348
|
+
session.commit()
|
|
349
|
+
print(f"成功删除 {delete_count} 条记录")
|
|
350
|
+
return delete_count
|
|
351
|
+
except Exception as e:
|
|
352
|
+
session.rollback()
|
|
353
|
+
print(f"删除数据失败: {e}")
|
|
354
|
+
raise
|
|
355
|
+
finally:
|
|
356
|
+
session.close()
|
|
357
|
+
|
|
358
|
+
# 创建全局实例,用于快速访问
|
|
359
|
+
_new_product_analysis_manager = None
|
|
360
|
+
|
|
361
|
+
def get_new_product_analysis_manager():
|
|
362
|
+
"""
|
|
363
|
+
获取新品分析管理器实例
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
NewProductAnalysisManager: 新品分析管理器实例
|
|
367
|
+
"""
|
|
368
|
+
global _new_product_analysis_manager
|
|
369
|
+
if _new_product_analysis_manager is None:
|
|
370
|
+
_new_product_analysis_manager = NewProductAnalysisManager()
|
|
371
|
+
return _new_product_analysis_manager
|
|
372
|
+
|
|
373
|
+
def insert_analysis_data(data_list):
|
|
374
|
+
"""
|
|
375
|
+
插入分析数据的便捷函数
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
data_list (list): 数据字典列表
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
int: 成功插入的记录数
|
|
382
|
+
"""
|
|
383
|
+
manager = get_new_product_analysis_manager()
|
|
384
|
+
return manager.insert_data(data_list)
|
|
385
|
+
|
|
386
|
+
def import_from_json(json_data_list):
|
|
387
|
+
"""
|
|
388
|
+
从JSON数据导入的便捷函数
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
json_data_list (list): JSON数据列表
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
int: 成功导入的记录数
|
|
395
|
+
"""
|
|
396
|
+
manager = get_new_product_analysis_manager()
|
|
397
|
+
return manager.import_from_json(json_data_list)
|
|
398
|
+
|
|
399
|
+
def get_records_by_skc(store_username, skc):
|
|
400
|
+
"""
|
|
401
|
+
根据SKC查询记录的便捷函数
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
store_username (str): 店铺账号
|
|
405
|
+
skc (str): 平台SKC
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
list: 记录列表
|
|
409
|
+
"""
|
|
410
|
+
manager = get_new_product_analysis_manager()
|
|
411
|
+
return manager.get_records_by_skc(store_username, skc)
|
|
412
|
+
|
|
413
|
+
if __name__ == '__main__':
|
|
414
|
+
# 测试代码
|
|
415
|
+
manager = NewProductAnalysisManager()
|
|
416
|
+
|
|
417
|
+
# 创建表
|
|
418
|
+
manager.create_table()
|
|
419
|
+
|
|
420
|
+
# 读取JSON文件
|
|
421
|
+
with open('../../docs/skc_model_GS9740414_2025-10-15.json', 'r', encoding='utf-8') as f:
|
|
422
|
+
json_data = json.load(f)
|
|
423
|
+
count = manager.import_from_json(json_data)
|
|
424
|
+
print(f"成功导入 {count} 条记录")
|
|
425
|
+
|
|
426
|
+
with open('../../docs/skc_model_S19118100_2025-10-15.json', 'r', encoding='utf-8') as f:
|
|
427
|
+
json_data = json.load(f)
|
|
428
|
+
count = manager.import_from_json(json_data)
|
|
429
|
+
print(f"成功导入 {count} 条记录")
|