@pn-data/pn-data-analysis 0.0.2 → 0.0.4
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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/pn-data-analysis/SKILL.md +50 -11
- package/pn-data-analysis/pn_query.py +60 -5
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -3,6 +3,18 @@ name: pn-data-analysis
|
|
|
3
3
|
description: Analyzes project data on the middle platform (pn_mid_v2). Use when querying 收入, 流水, 商店流水, 活跃, 留存, 来源, project revenue, activity, retention, or source data by project and month.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
> Skill 版本:v0.0.4
|
|
7
|
+
|
|
8
|
+
# Skill 更新
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm view @pn-data/pn-data-analysis version --registry https://registry.npmjs.org/
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
与本文件顶部 `Skill 版本` 对比,不同则更新本 Skill
|
|
15
|
+
|
|
16
|
+
更新后**重新读取** `<SKILL_DIR>/SKILL.md`,以新版本为准。告知用户"中台数据分析 Skill 已更新到 vX.X.X"。
|
|
17
|
+
|
|
6
18
|
# 中台项目数据分析
|
|
7
19
|
|
|
8
20
|
通过 `pn_query.py` 远程查询 pn_mid_v2 中台各项目数据,支持**流水、活跃、留存、来源**四类查询。
|
|
@@ -13,10 +25,21 @@ description: Analyzes project data on the middle platform (pn_mid_v2). Use when
|
|
|
13
25
|
- **关键词**:用pn、用中台
|
|
14
26
|
- **数据类型词**:收入、流水、商店流水、活跃、留存、来源
|
|
15
27
|
|
|
16
|
-
##
|
|
28
|
+
## 执行顺序:先取 listProject 学习 id 与名称
|
|
29
|
+
|
|
30
|
+
**在跑任何按项目查询(pay/activity/retention/source)之前**,先取一次项目列表,建立「项目 id ↔ 名称」对应关系:
|
|
31
|
+
|
|
32
|
+
1. **先执行**:`python3 <SKILL_DIR>/pn_query.py projects`(或 `--json` 取原始列表)
|
|
33
|
+
2. **从返回中学习**:每条为 `id | name | tag`,记下 id、name、tag 的对应关系
|
|
34
|
+
3. **再解析用户请求**:用户提到「项目名」「项目X」「tag」或数字 id 时,用该列表解析出**真实的项目 id (pid)**,再调用 `pn_query.py <pid> <dataType> <YYYY-MM>`
|
|
35
|
+
|
|
36
|
+
未先取 listProject 时,不要猜测 pid;名称/别称与 id 的对应关系以当次 listProject 结果为准。
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
## 项目名称解析(依赖上面 listProject 结果)
|
|
39
|
+
|
|
40
|
+
- 用户说**数字 id**(如 2023、2088)→ 直接作为 pid
|
|
41
|
+
- 用户说**项目名称或 tag** → 用已获取的项目列表按 name/tag 匹配,取对应 id 作为 pid
|
|
42
|
+
- 仅当列表中存在明确对应时再发起数据查询;无法匹配时提示用户说明项目 id 或名称
|
|
20
43
|
|
|
21
44
|
---
|
|
22
45
|
|
|
@@ -34,10 +57,23 @@ description: Analyzes project data on the middle platform (pn_mid_v2). Use when
|
|
|
34
57
|
|
|
35
58
|
## 查询命令
|
|
36
59
|
|
|
37
|
-
|
|
60
|
+
脚本位置:`<SKILL_DIR>/pn_query.py`
|
|
61
|
+
|
|
62
|
+
### 获取项目列表(id、name、tag)
|
|
63
|
+
|
|
64
|
+
无需 pid/月份,直接获取当前密钥对应用户可访问的项目列表,用于学习 **id、name、tag** 的对应关系:
|
|
38
65
|
|
|
39
66
|
```bash
|
|
40
|
-
python3
|
|
67
|
+
python3 <SKILL_DIR>/pn_query.py projects
|
|
68
|
+
python3 <SKILL_DIR>/pn_query.py projects --json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
输出格式:`id | name | tag`,每行一个项目。
|
|
72
|
+
|
|
73
|
+
### 按项目与月份查询数据
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python3 <SKILL_DIR>/pn_query.py <pid> <dataType> <YYYY-MM> [选项]
|
|
41
77
|
```
|
|
42
78
|
|
|
43
79
|
### 四类数据
|
|
@@ -71,23 +107,26 @@ python3 .cursor/skills/pn-data-analysis/pn_query.py <pid> <dataType> <YYYY-MM> [
|
|
|
71
107
|
## 示例
|
|
72
108
|
|
|
73
109
|
```bash
|
|
110
|
+
# 获取项目列表
|
|
111
|
+
python3 <SKILL_DIR>/pn_query.py projects
|
|
112
|
+
|
|
74
113
|
# 流水
|
|
75
|
-
python3
|
|
114
|
+
python3 <SKILL_DIR>/pn_query.py 2023 pay 2026-01
|
|
76
115
|
|
|
77
116
|
# 活跃(全平台)
|
|
78
|
-
python3
|
|
117
|
+
python3 <SKILL_DIR>/pn_query.py 2023 activity 2026-01
|
|
79
118
|
|
|
80
119
|
# 留存(全平台)
|
|
81
|
-
python3
|
|
120
|
+
python3 <SKILL_DIR>/pn_query.py 2023 retention 2026-01
|
|
82
121
|
|
|
83
122
|
# 来源
|
|
84
|
-
python3
|
|
123
|
+
python3 <SKILL_DIR>/pn_query.py 2023 source 2026-01
|
|
85
124
|
|
|
86
125
|
# 仅 iOS 活跃
|
|
87
|
-
python3
|
|
126
|
+
python3 <SKILL_DIR>/pn_query.py 2023 activity 2026-01 --appPlatform=1
|
|
88
127
|
|
|
89
128
|
# 原始 JSON
|
|
90
|
-
python3
|
|
129
|
+
python3 <SKILL_DIR>/pn_query.py 2023 retention 2026-01 --json
|
|
91
130
|
```
|
|
92
131
|
|
|
93
132
|
## 默认行为
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
"""
|
|
3
3
|
pn_query.py - 远程查询 pn_mid_v2 中台数据
|
|
4
4
|
|
|
5
|
-
通过 HTTP API 调用 pnDataAnalysis
|
|
5
|
+
通过 HTTP API 调用 pnDataAnalysis 接口,查询项目的流水、活跃、留存、来源数据,或获取项目列表。
|
|
6
6
|
|
|
7
7
|
用法:
|
|
8
|
+
python3 pn_query.py projects # 获取项目列表
|
|
8
9
|
python3 pn_query.py <pid> <dataType> <YYYY-MM> [选项]
|
|
9
10
|
python3 pn_query.py 2023 pay 2026-01
|
|
10
11
|
python3 pn_query.py 2023 activity 2026-01
|
|
@@ -14,6 +15,7 @@ pn_query.py - 远程查询 pn_mid_v2 中台数据
|
|
|
14
15
|
选项:
|
|
15
16
|
--appPlatform=N 0=全平台(默认) 1=iOS 2=Android
|
|
16
17
|
--group=N 分组类型,默认2(日期)。留存默认8(账号)
|
|
18
|
+
--json 输出原始 JSON
|
|
17
19
|
"""
|
|
18
20
|
|
|
19
21
|
import argparse
|
|
@@ -30,6 +32,42 @@ API_PATH = "/service/pn_data_analysis"
|
|
|
30
32
|
ENV_TOKEN = "PN_DATA_ANALYSIS_TOKEN"
|
|
31
33
|
|
|
32
34
|
|
|
35
|
+
def list_projects() -> list:
|
|
36
|
+
"""获取当前用户可访问的项目列表。"""
|
|
37
|
+
token = os.environ.get(ENV_TOKEN)
|
|
38
|
+
if not token:
|
|
39
|
+
raise SystemExit(
|
|
40
|
+
f"未配置 {ENV_TOKEN}。请在中台右上角 -> 生成数据分析密钥 获取后写入 shell 配置(如 ~/.zshrc)并 source 生效。"
|
|
41
|
+
)
|
|
42
|
+
url = f"{API_BASE}{API_PATH}"
|
|
43
|
+
payload = {"dataType": "listProject"}
|
|
44
|
+
headers = {
|
|
45
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
46
|
+
"X-Pn-Token": token,
|
|
47
|
+
}
|
|
48
|
+
req = urllib.request.Request(
|
|
49
|
+
url,
|
|
50
|
+
data=json.dumps(payload).encode("utf-8"),
|
|
51
|
+
headers=headers,
|
|
52
|
+
method="POST",
|
|
53
|
+
)
|
|
54
|
+
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
55
|
+
out = json.loads(resp.read().decode("utf-8"))
|
|
56
|
+
return out if isinstance(out, list) else out.get("list", out)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def format_projects(data: list) -> str:
|
|
60
|
+
if not data:
|
|
61
|
+
return "无项目数据"
|
|
62
|
+
lines = ["项目列表 (id | name | tag):"]
|
|
63
|
+
for p in data:
|
|
64
|
+
pid = p.get("id", "")
|
|
65
|
+
name = p.get("name", "")
|
|
66
|
+
tag = p.get("tag", "")
|
|
67
|
+
lines.append(f" {pid} | {name} | {tag}")
|
|
68
|
+
return "\n".join(lines)
|
|
69
|
+
|
|
70
|
+
|
|
33
71
|
def query(pid: int, data_type: str, month: str, app_platform: int = 0, group: int = 2) -> dict:
|
|
34
72
|
token = os.environ.get(ENV_TOKEN)
|
|
35
73
|
if not token:
|
|
@@ -126,19 +164,36 @@ def format_source(data: list) -> str:
|
|
|
126
164
|
|
|
127
165
|
def main():
|
|
128
166
|
parser = argparse.ArgumentParser(description="pn_mid_v2 远程数据查询")
|
|
129
|
-
parser.add_argument("pid",
|
|
130
|
-
parser.add_argument("dataType", choices=["pay", "activity", "retention", "source"], help="数据类型")
|
|
131
|
-
parser.add_argument("month", help="月份 YYYY-MM")
|
|
167
|
+
parser.add_argument("pid", nargs="?", help="项目 ID,或写 projects 获取项目列表")
|
|
168
|
+
parser.add_argument("dataType", nargs="?", choices=["pay", "activity", "retention", "source"], help="数据类型")
|
|
169
|
+
parser.add_argument("month", nargs="?", help="月份 YYYY-MM")
|
|
132
170
|
parser.add_argument("--appPlatform", type=int, default=0, help="0=全平台 1=iOS 2=Android (默认0)")
|
|
133
171
|
parser.add_argument("--group", type=int, default=None, help="分组类型,默认2(日期),留存默认8(账号)")
|
|
134
172
|
parser.add_argument("--json", action="store_true", help="输出原始 JSON")
|
|
135
173
|
args = parser.parse_args()
|
|
136
174
|
|
|
175
|
+
# 获取项目列表
|
|
176
|
+
if (args.pid or "").lower() in ("projects", "listproject", "list"):
|
|
177
|
+
try:
|
|
178
|
+
result = list_projects()
|
|
179
|
+
except Exception as e:
|
|
180
|
+
print(f"查询失败: {e}", file=sys.stderr)
|
|
181
|
+
sys.exit(1)
|
|
182
|
+
if args.json:
|
|
183
|
+
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
184
|
+
else:
|
|
185
|
+
print(format_projects(result))
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
if args.pid is None or args.dataType is None or args.month is None:
|
|
189
|
+
parser.error("查询数据时需指定 pid dataType month,或使用 pid=projects 获取项目列表")
|
|
190
|
+
|
|
191
|
+
pid = int(args.pid)
|
|
137
192
|
if args.group is None:
|
|
138
193
|
args.group = 8 if args.dataType == "retention" else 2
|
|
139
194
|
|
|
140
195
|
try:
|
|
141
|
-
result = query(
|
|
196
|
+
result = query(pid, args.dataType, args.month, args.appPlatform, args.group)
|
|
142
197
|
except Exception as e:
|
|
143
198
|
print(f"查询失败: {e}", file=sys.stderr)
|
|
144
199
|
sys.exit(1)
|