AppsFlyer Click Gap

运行目标是 mac2。流水线复用 appsflyer/af_click_gap.py 的 Superset 查询、AppsFlyer payload、特殊包名映射和差值公式,但新入口增加 timeout/重试、严格错误边界、AppsFlyer 重复键按 dt+pkg_name 求和,并将日志写到仓库外 ~/Library/Logs/af-click-gap/pipeline.log。固定数据库:/Users/ads-center/Documents/database/af_click_gap.db;不复制或提交数据库、cookie、token、.env、日志和缓存。

文件和字段

  • scripts/af_click_gap_pipeline.py:提取、校验、发布和 Git 操作。
  • data/YYYYMMDD.json:直接 JSON 数组;无数据日期也写 []。每行字段为 dt(YYYYMMDD 字符串)、attr_platform、pkg_name(非空字符串)、shareit_clicks、af_clicks、installs_ua、clicks_diff(有限 number)、clicks_diff_rate(有限 number 或 null)。业务键为 pid + dt + pkg_name。
  • data/index.json:版本、生成时间及 data/YYYYMMDD.json 清单。
  • index.html:无构建依赖的静态看板。

默认窗口是 mac2 本地运行日及前 6 天,首尾包含,共 7 天;这是对旧脚本实际可能覆盖 8 个日期的修正。空 Superset 结果、无达标包或 AppsFlyer 合法空数组都是成功空结果(退出码 0),仍生成日期数组、同步清空 SQLite 窗口并可提交;HTTP、认证、响应格式、SQLite schema 或文件校验错误退出码 1,不覆盖正式文件。

SQLite 必须预先存在 click_gap 表,列类型为 pid TEXT NOT NULL, dt TEXT NOT NULL, attr_platform TEXT NOT NULL, pkg_name TEXT NOT NULL, shareit_clicks REAL NOT NULL, af_clicks REAL NOT NULL, installs_ua REAL NOT NULL, clicks_diff REAL NOT NULL, clicks_diff_rate REAL, updated_at TEXT NOT NULL,主键严格为 (pid, dt, pkg_name)。脚本不建表、不迁移;每次成功运行先删除窗口内 shareit 旧行再插入完整新结果,因此消失日期/业务键也会清零。

手工运行

在 mac2 先确认依赖和登录环境(pandas、requests、requests_toolbelt、af_browser、superset_login):

cd /Users/shareit./Library/CloudStorage/OneDrive-个人/ubuntu/Gitea/af-click-gap
python3 -m py_compile scripts/af_click_gap_pipeline.py
python3 scripts/af_click_gap_pipeline.py --help
python3 scripts/af_click_gap_pipeline.py --dry-run
# 正式写入并提交、push(默认行为)
python3 scripts/af_click_gap_pipeline.py --push
# 只写 data 和 SQLite,不操作 Git
python3 scripts/af_click_gap_pipeline.py --no-push
# 手工补数,日期首尾包含且最多 7 天
python3 scripts/af_click_gap_pipeline.py --start-date 2026-10-10 --end-date 2026-10-16 --no-push

--dry-run 只生成仓库外临时 JSON 并校验,不写 data、数据库或执行 Git。正式文件先原子替换,再提交 SQLite,最后才 git add/commit/push;数据库提交失败时不执行 Git。commit/push 失败会保留本地文件和数据库,下一次可重跑或手工 git add data index.html ... && git commit && git push;不会伪造认证或 force push。工作区在 push 模式有非本任务改动时拒绝继续。

看板

直接打开 index.html 或运行 python3 -m http.server 后访问。页面读取并校验 data/index.json 及清单路径,只执行安全 JSON 解析;缺失/损坏文件显示“数据不完整”并跳过该文件,清单本身失败则不展示数据。默认最近 30 天,可选有效开始/结束日期和 pkg_name;默认 dt 降序、同日期 shareit_clicks 降序,点击表头切换排序。

mac2 launchd

launchd/com.roasbloom.af-click-gap.plist.template 明确为 TEMPLATE_ONLY。当前开发机不能证明自己是 mac2,因此没有伪造最终 plist、解释器或安装结果。必须在 mac2 执行并记录:

hostname
command -v python3
python3 --version
python3 -c 'import pandas,requests,requests_toolbelt,af_browser,superset_login; print("dependencies ok")'
cd /Users/shareit./Library/CloudStorage/OneDrive-个人/ubuntu/Gitea/af-click-gap
mkdir -p "$HOME/Library/Logs/af-click-gap"
PY=$(command -v python3); sed -e "s#__MAC2_PYTHON3__#$PY#" -e "s#__PROJECT_DIR__#$PWD#g" -e "s#__LOG_DIR__#$HOME/Library/Logs/af-click-gap#g" launchd/com.roasbloom.af-click-gap.plist.template > /tmp/com.roasbloom.af-click-gap.plist
plutil -lint /tmp/com.roasbloom.af-click-gap.plist
cp /tmp/com.roasbloom.af-click-gap.plist "$HOME/Library/LaunchAgents/"
launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.roasbloom.af-click-gap.plist"
launchctl print "gui/$(id -u)/com.roasbloom.af-click-gap"
# 卸载:launchctl bootout "gui/$(id -u)/com.roasbloom.af-click-gap"; rm "$HOME/Library/LaunchAgents/com.roasbloom.af-click-gap.plist"

定时任务失败不会触发成功 push;stdout/stderr 位于 mac2 用户日志目录。Git remote、SSH/HTTPS credential helper 或 Gitea token 必须由用户在 mac2 预先配置。若 git remote -v 为空,请按组织 Git 文档创建仓库并绑定 remote 后再运行;本项目不会猜测仓库名称或修改 git config。

安全和验证

允许提交的路径仅为脚本、README、看板、data/*.json、data/index.json、模板和 .gitignore。提交前禁止 .env*、SQLite、日志、浏览器状态,脚本还扫描 cookie、authorization、password、api-key、token 文本。建议验证:python3 -m py_compile ...、--help、mac2 上 --dry-run、python3 -m json.tool data/index.json,以及浏览器/静态 HTTP 打开页面。当前环境未验证 mac2 依赖、固定数据库、外部登录、launchd 安装和远程 push;这些不能以本机结果冒充。不要新增测试套件。

S
Description
Click Gap 数据看板
Readme
300 KiB
Languages
Python 46.1%
HTML 44.5%
Shell 9.4%