88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the per-user post census from JSONPlaceholder /users + /posts.
|
|
|
|
Extract lane (data extraction into a table). Produces:
|
|
2026-11-01-posts-census.csv (tab-separated)
|
|
2026-11-01-posts-census.md (markdown table)
|
|
2026-11-01-posts-census.json (machine-readable)
|
|
|
|
Canned run: python3 build_posts_census.py
|
|
"""
|
|
import csv
|
|
import json
|
|
import urllib.request
|
|
import urllib.error
|
|
|
|
BASE = "https://jsonplaceholder.typicode.com"
|
|
OUT_DIR = "/root/troupe-standup/wizard-work/ledger"
|
|
|
|
|
|
def fetch(path):
|
|
with urllib.request.urlopen(BASE + path, timeout=20) as r:
|
|
return json.loads(r.read().decode("utf-8"))
|
|
|
|
|
|
def build(users, posts):
|
|
by_id = {u["id"]: u for u in users}
|
|
post_counts = {}
|
|
for p in posts:
|
|
post_counts[p["userId"]] = post_counts.get(p["userId"], 0) + 1
|
|
|
|
rows = []
|
|
for uid in sorted(by_id):
|
|
u = by_id[uid]
|
|
rows.append({
|
|
"id": uid,
|
|
"name": u["name"],
|
|
"username": u["username"],
|
|
"email": u["email"],
|
|
"city": u["address"]["city"],
|
|
"post_count": post_counts.get(uid, 0),
|
|
})
|
|
return rows
|
|
|
|
|
|
def write_artifacts(rows):
|
|
# CSV (comma-separated, the CSV convention)
|
|
csv_path = f"{OUT_DIR}/2026-11-01-posts-census.csv"
|
|
with open(csv_path, "w", encoding="utf-8", newline="") as f:
|
|
w = csv.writer(f, lineterminator="\n") # comma-separated (CSV convention)
|
|
w.writerow(["id", "name", "username", "email", "city", "post_count"])
|
|
for r in rows:
|
|
w.writerow([r["id"], r["name"], r["username"], r["email"],
|
|
r["city"], r["post_count"]])
|
|
|
|
# Markdown table
|
|
md_path = f"{OUT_DIR}/2026-11-01-posts-census.md"
|
|
with open(md_path, "w", encoding="utf-8") as f:
|
|
f.write("# Per-user Post Census (JSONPlaceholder)\n\n")
|
|
f.write("Table of each user with their post count "
|
|
f"({len(rows)} users, {sum(r['post_count'] for r in rows)} posts total).\n\n")
|
|
f.write("| id | name | username | email | city | post_count |\n")
|
|
f.write("|---:|---|---:|---:|---:|---:|\n")
|
|
for r in rows:
|
|
f.write(f"| {r['id']} | {r['name']} | {r['username']} | "
|
|
f"{r['email']} | {r['city']} | {r['post_count']} |\n")
|
|
|
|
# JSON
|
|
json_path = f"{OUT_DIR}/2026-11-01-posts-census.json"
|
|
payload = {
|
|
"source": "https://jsonplaceholder.typicode.com/users + /posts",
|
|
"n_users": len(rows),
|
|
"total_posts": sum(r["post_count"] for r in rows),
|
|
"rows": rows,
|
|
}
|
|
with open(json_path, "w", encoding="utf-8") as f:
|
|
json.dump(payload, f, indent=2)
|
|
|
|
print(f"wrote {csv_path} ({len(rows)} data rows)")
|
|
print(f"wrote {md_path}")
|
|
print(f"wrote {json_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
users = fetch("/users")
|
|
posts = fetch("/posts")
|
|
rows = build(users, posts)
|
|
write_artifacts(rows)
|