qrpa 1.0.15__py3-none-any.whl → 1.0.17__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/__init__.py +3 -0
- qrpa/fun_file.py +147 -1
- qrpa/shein_excel.py +197 -0
- qrpa/shein_lib.py +586 -25
- qrpa/shein_sqlite.py +154 -0
- qrpa/wxwork.py +37 -0
- {qrpa-1.0.15.dist-info → qrpa-1.0.17.dist-info}/METADATA +1 -1
- {qrpa-1.0.15.dist-info → qrpa-1.0.17.dist-info}/RECORD +10 -9
- {qrpa-1.0.15.dist-info → qrpa-1.0.17.dist-info}/WHEEL +0 -0
- {qrpa-1.0.15.dist-info → qrpa-1.0.17.dist-info}/top_level.txt +0 -0
qrpa/shein_sqlite.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from .fun_base import log
|
|
2
|
+
|
|
3
|
+
import sqlite3
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
auto_dir = 'D:/auto'
|
|
10
|
+
db_file = f'{auto_dir}/shein/db/shein_sku_sales.db'
|
|
11
|
+
|
|
12
|
+
# log(db_file)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(args):
|
|
16
|
+
init_db()
|
|
17
|
+
# exists_sales_1_days_ago('653231597')
|
|
18
|
+
# log(get_last_week_sales('6960380466'))
|
|
19
|
+
# log(get_sales('6960380466', '2025-02-25', '2025-03-04'))
|
|
20
|
+
# log(get_near_week_sales('I46mraado10r'))
|
|
21
|
+
# log(get_last_week_sales('I46mraado10r','2025-03-08','2025-03-14'))
|
|
22
|
+
# create_indexes()
|
|
23
|
+
|
|
24
|
+
def init_db():
|
|
25
|
+
# 获取文件夹路径
|
|
26
|
+
folder_path = os.path.dirname(db_file)
|
|
27
|
+
# 如果文件夹不存在,则创建
|
|
28
|
+
if not os.path.exists(folder_path):
|
|
29
|
+
os.makedirs(folder_path)
|
|
30
|
+
log(f"文件夹已创建: {folder_path}")
|
|
31
|
+
conn = sqlite3.connect(db_file)
|
|
32
|
+
cursor = conn.cursor()
|
|
33
|
+
cursor.execute('''
|
|
34
|
+
CREATE TABLE IF NOT EXISTS sales (
|
|
35
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
+
skc TEXT,
|
|
37
|
+
date TEXT,
|
|
38
|
+
skc_sale INTEGER,
|
|
39
|
+
skc_order INTEGER,
|
|
40
|
+
sku TEXT,
|
|
41
|
+
attr_name TEXT,
|
|
42
|
+
sku_sale INTEGER,
|
|
43
|
+
sku_order INTEGER
|
|
44
|
+
)
|
|
45
|
+
''')
|
|
46
|
+
conn.commit()
|
|
47
|
+
conn.close()
|
|
48
|
+
log('新建数据库成功', db_file)
|
|
49
|
+
|
|
50
|
+
init_db()
|
|
51
|
+
|
|
52
|
+
def insert_sales(skc, date, skc_sale, skc_order, sku, attr_name, sku_sale, sku_order):
|
|
53
|
+
conn = sqlite3.connect(db_file)
|
|
54
|
+
cursor = conn.cursor()
|
|
55
|
+
cursor.execute('''
|
|
56
|
+
SELECT 1 FROM sales WHERE sku = ? AND date = ?
|
|
57
|
+
''', (sku, date))
|
|
58
|
+
|
|
59
|
+
if cursor.fetchone() is None:
|
|
60
|
+
cursor.execute('''
|
|
61
|
+
INSERT INTO sales (skc, date, skc_sale, skc_order, sku, attr_name, sku_sale, sku_order)
|
|
62
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
63
|
+
''', (skc, date, skc_sale, skc_order, sku, attr_name, sku_sale, sku_order))
|
|
64
|
+
conn.commit()
|
|
65
|
+
|
|
66
|
+
conn.close()
|
|
67
|
+
|
|
68
|
+
def get_sales(sku, start_date, end_date):
|
|
69
|
+
conn = sqlite3.connect(db_file)
|
|
70
|
+
cursor = conn.cursor()
|
|
71
|
+
cursor.execute('''
|
|
72
|
+
SELECT SUM(sku_sale), SUM(sku_order) FROM sales WHERE sku = ? AND date BETWEEN ? AND ?
|
|
73
|
+
''', (sku, start_date, end_date))
|
|
74
|
+
|
|
75
|
+
result = cursor.fetchone() # 获取查询结果
|
|
76
|
+
sales_num = result[0] if result[0] is not None else 0
|
|
77
|
+
orders_num = result[1] if result[1] is not None else 0
|
|
78
|
+
|
|
79
|
+
conn.close()
|
|
80
|
+
|
|
81
|
+
log('get_sales:', sku, start_date, end_date, sales_num, orders_num)
|
|
82
|
+
return sales_num, orders_num # 返回销售量和订单量的元组
|
|
83
|
+
|
|
84
|
+
def get_last_week_sales(sku):
|
|
85
|
+
today = datetime.today().date()
|
|
86
|
+
# last_week_start = today - timedelta(days=today.weekday() + 14)
|
|
87
|
+
last_week_start = (datetime.now() - timedelta(days=14)).strftime("%Y-%m-%d")
|
|
88
|
+
last_week_end = (datetime.now() - timedelta(days=8)).strftime("%Y-%m-%d")
|
|
89
|
+
# log('远7天',last_week_start,last_week_end,sku)
|
|
90
|
+
return get_sales(sku, str(last_week_start), str(last_week_end))
|
|
91
|
+
|
|
92
|
+
def get_near_week_sales(sku):
|
|
93
|
+
today = datetime.today().date()
|
|
94
|
+
# last_week_start = today - timedelta(days=today.weekday() + 14)
|
|
95
|
+
last_week_start = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
|
|
96
|
+
last_week_end = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
|
|
97
|
+
# log('远7天',last_week_start,last_week_end,sku)
|
|
98
|
+
return get_sales(sku, str(last_week_start), str(last_week_end))
|
|
99
|
+
|
|
100
|
+
def get_last_month_sales(sku):
|
|
101
|
+
today = datetime.today().date()
|
|
102
|
+
# first_day_of_this_month = today.replace(day=1)
|
|
103
|
+
# last_month_end = first_day_of_this_month - timedelta(days=1)
|
|
104
|
+
# last_month_start = last_month_end.replace(day=1)
|
|
105
|
+
last_month_start = (datetime.now() - timedelta(days=60)).strftime("%Y-%m-%d")
|
|
106
|
+
last_month_end = (datetime.now() - timedelta(days=31)).strftime("%Y-%m-%d")
|
|
107
|
+
# log('远30天',last_month_start,last_month_end,sku)
|
|
108
|
+
return get_sales(sku, str(last_month_start), str(last_month_end))
|
|
109
|
+
|
|
110
|
+
def get_near_month_sales(sku):
|
|
111
|
+
today = datetime.today().date()
|
|
112
|
+
# first_day_of_this_month = today.replace(day=1)
|
|
113
|
+
# last_month_end = first_day_of_this_month - timedelta(days=1)
|
|
114
|
+
# last_month_start = last_month_end.replace(day=1)
|
|
115
|
+
last_month_start = (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d")
|
|
116
|
+
last_month_end = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
|
|
117
|
+
# log('远30天',last_month_start,last_month_end,sku)
|
|
118
|
+
return get_sales(sku, str(last_month_start), str(last_month_end))
|
|
119
|
+
|
|
120
|
+
def exists_sales_1_days_ago(skc):
|
|
121
|
+
conn = sqlite3.connect(db_file) # 替换成你的数据库文件
|
|
122
|
+
cursor = conn.cursor()
|
|
123
|
+
date_threshold = (datetime.today().date() - timedelta(days=1)).isoformat()
|
|
124
|
+
# 使用 str.format() 格式化 SQL
|
|
125
|
+
sql = '''
|
|
126
|
+
SELECT 1 FROM sales WHERE skc = '{skc}' AND date = '{date}' LIMIT 1
|
|
127
|
+
'''.format(skc=skc, date=date_threshold)
|
|
128
|
+
log("exists_sales_1_days_ago:", sql.strip()) # 打印 SQL 语句
|
|
129
|
+
cursor.execute('''
|
|
130
|
+
SELECT 1 FROM sales WHERE skc = ? AND date <= ? LIMIT 1
|
|
131
|
+
''', (skc, date_threshold))
|
|
132
|
+
result = cursor.fetchone()
|
|
133
|
+
conn.close()
|
|
134
|
+
return result is not None
|
|
135
|
+
|
|
136
|
+
def create_indexes():
|
|
137
|
+
conn = sqlite3.connect(db_file)
|
|
138
|
+
cursor = conn.cursor()
|
|
139
|
+
# 创建 spu + date 联合索引
|
|
140
|
+
cursor.execute('''
|
|
141
|
+
CREATE INDEX IF NOT EXISTS idx_sales_skc_date ON sales (skc, date);
|
|
142
|
+
''')
|
|
143
|
+
# 创建 sku + date 唯一索引
|
|
144
|
+
cursor.execute('''
|
|
145
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_sales_sku_date_unique ON sales (sku, date);
|
|
146
|
+
''')
|
|
147
|
+
conn.commit() # 提交更改
|
|
148
|
+
conn.close() # 关闭连接
|
|
149
|
+
log("索引创建成功!")
|
|
150
|
+
|
|
151
|
+
init_db()
|
|
152
|
+
|
|
153
|
+
if __name__ == '__main__':
|
|
154
|
+
main(sys.argv)
|
qrpa/wxwork.py
CHANGED
|
@@ -17,6 +17,7 @@ import hashlib
|
|
|
17
17
|
import base64
|
|
18
18
|
import requests
|
|
19
19
|
from requests_toolbelt import MultipartEncoder
|
|
20
|
+
from datetime import datetime
|
|
20
21
|
|
|
21
22
|
# 通过企微群机器人发送消息
|
|
22
23
|
class WxWorkBot:
|
|
@@ -99,6 +100,42 @@ class WxWorkBot:
|
|
|
99
100
|
}
|
|
100
101
|
self.send_msg(data)
|
|
101
102
|
|
|
103
|
+
def send_notify(self, title, sub_title_list, data_list):
|
|
104
|
+
"""
|
|
105
|
+
发送Markdown消息
|
|
106
|
+
:param content:
|
|
107
|
+
:return:
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
current_date = datetime.now().strftime("%Y-%m-%d")
|
|
111
|
+
header = f"{current_date} {title}\n\n"
|
|
112
|
+
|
|
113
|
+
arr_color = ['warning', 'info', 'warning']
|
|
114
|
+
arr_sub_header = [f"<font color='{arr_color[index]}'>{title}</font>" for index, title in enumerate(sub_title_list)]
|
|
115
|
+
sub_header = "\t".join(arr_sub_header) + "\n\n"
|
|
116
|
+
|
|
117
|
+
# 获取每个元素的行索引和列索引
|
|
118
|
+
arr_content = [
|
|
119
|
+
[
|
|
120
|
+
f'{value}' if col_idx == 0 else f"<font color='{arr_color[col_idx - 1]}'>{value}</font>"
|
|
121
|
+
for col_idx, value in enumerate(row)
|
|
122
|
+
] # 每行的元素组成一个子列表
|
|
123
|
+
for row_idx, row in enumerate(data_list) # 外层循环控制行
|
|
124
|
+
]
|
|
125
|
+
# 将二维数组转换为字符串
|
|
126
|
+
content = "\n".join(
|
|
127
|
+
# 对每行的元素列表使用 join(),用 \t 连接
|
|
128
|
+
"\t".join(row) for row in arr_content
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
data = {
|
|
132
|
+
"msgtype" : "markdown",
|
|
133
|
+
"markdown": {
|
|
134
|
+
"content": header + sub_header + content
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
self.send_msg(data)
|
|
138
|
+
|
|
102
139
|
def send_img(self, img_path):
|
|
103
140
|
"""
|
|
104
141
|
发送图片消息
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
qrpa/RateLimitedSender.py,sha256=hqvb1qspDFaW4RsLuVufylOrefkMgixANKeBaGEqYb4,1421
|
|
2
|
-
qrpa/__init__.py,sha256=
|
|
2
|
+
qrpa/__init__.py,sha256=EysO3QHdHWPWuVmtbekAZBSKSlCIAHnLzg2O6e26nNs,801
|
|
3
3
|
qrpa/db_migrator.py,sha256=2VmhzcMsU0MKpl-mNCwKyV8tLTqyEysSpP27-S_rQZ8,21862
|
|
4
4
|
qrpa/fun_base.py,sha256=W_owEa8-yuGG18n9kX3remm9YTzym69ztQjtYCNMTw4,3308
|
|
5
5
|
qrpa/fun_excel.py,sha256=S-A-kTZ2e3dJ8NqdhiOFqTlcr0d6XLMP6imagztRel0,103605
|
|
6
|
-
qrpa/fun_file.py,sha256=
|
|
6
|
+
qrpa/fun_file.py,sha256=yzjDV16WL5vRys7J4uQcNzIFkX4D5MAlSCwxcD-mwQo,11966
|
|
7
7
|
qrpa/fun_web.py,sha256=5QLQorAhRzMOGMRh4eCJ2UH8ZhVHvxkHwobWhmgU5qM,6286
|
|
8
8
|
qrpa/fun_win.py,sha256=-LnTeocdTt72NVH6VgLdpAT9_C5oV9okeudXG6CftMA,8034
|
|
9
|
-
qrpa/shein_excel.py,sha256=
|
|
10
|
-
qrpa/shein_lib.py,sha256=
|
|
9
|
+
qrpa/shein_excel.py,sha256=4dYhyvfphhcaje7rJUJR7GMZDWwm8VMw49BWf8T8f8E,13455
|
|
10
|
+
qrpa/shein_lib.py,sha256=VOKtgUK-2stWLwASjQRfiYHkVG7M2Tzk0VV-XNyXkes,65915
|
|
11
|
+
qrpa/shein_sqlite.py,sha256=ZQwD0Gz81q9WY7tY2HMEYvSF9r3N_G_Aur3bYfST9WY,5707
|
|
11
12
|
qrpa/shein_ziniao.py,sha256=nSqqcEPh4nVQtUxUnIRzeZfTLyXywGPjPZn5pP-w57U,18309
|
|
12
13
|
qrpa/time_utils.py,sha256=ef0hhbN_6b-gcnz5ETIVOoxemIMvcxGVGGIRnHnGaBo,29564
|
|
13
14
|
qrpa/time_utils_example.py,sha256=shHOXKKF3QSzb0SHsNc34M61wEkkLuM30U9X1THKNS8,8053
|
|
14
|
-
qrpa/wxwork.py,sha256=
|
|
15
|
-
qrpa-1.0.
|
|
16
|
-
qrpa-1.0.
|
|
17
|
-
qrpa-1.0.
|
|
18
|
-
qrpa-1.0.
|
|
15
|
+
qrpa/wxwork.py,sha256=8LzRmoHYo0KBfZ1cmkWPj824Zp52NAUYm3RXYzmIIi0,10507
|
|
16
|
+
qrpa-1.0.17.dist-info/METADATA,sha256=KltOu2nc9ZIPMTGxfUoAzr5p14zr_eY-OoyyagV2tXM,231
|
|
17
|
+
qrpa-1.0.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
18
|
+
qrpa-1.0.17.dist-info/top_level.txt,sha256=F6T5igi0fhXDucPPUbmmSC0qFCDEsH5eVijfVF48OFU,5
|
|
19
|
+
qrpa-1.0.17.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|