File size: 2,693 Bytes
21bdc64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0685414
21bdc64
0685414
 
21bdc64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# ๋„ค์ด๋ฒ„ ๋ฐ์ดํ„ฐ๋žฉ ๊ฒ€์ƒ‰์–ด ํŠธ๋ Œ๋“œ๋กœ ์„ฑ๋ณ„ร—์—ฐ๋ น ์ถ”์ • ๋น„์ค‘์„ ์‚ฐ์ถœํ•˜๋Š” ๋ชจ๋“ˆ
# ์ฃผ์˜: ์„ธ๊ทธ๋จผํŠธ๋ณ„ ๋…๋ฆฝ ์ •๊ทœํ™”๋ฅผ ์•ต์ปค ํ‚ค์›Œ๋“œ ๋น„์œจ๋กœ ์ƒ์‡„ํ•œ '์ถ”์ •' ์ƒ๋Œ€๊ฐ’. ์ ˆ๋Œ€ ๊ฒ€์ƒ‰๋Ÿ‰ ์•„๋‹˜.
import os
from datetime import date, timedelta

import requests

URL = "https://openapi.naver.com/v1/datalab/search"
ANCHOR = "๋‚ ์”จ"  # ์ •๊ทœํ™” ์ƒ์‡„์šฉ ๊ด‘๋ฒ”์œ„ ํ‚ค์›Œ๋“œ (๊ฐ€์ •: ์—ฐ๋ นยท์„ฑ๋ณ„ ๋ถ„ํฌ๊ฐ€ ๋น„๊ต์  ๊ณ ๋ฆ„)

AGE_BANDS = {  # ํ‘œ์‹œ ๊ตฌ๊ฐ„ โ†’ ๋ฐ์ดํ„ฐ๋žฉ ์—ฐ๋ น ์ฝ”๋“œ
    "20๋Œ€ ์ดํ•˜": ["1", "2", "3", "4"],   # ~29์„ธ
    "30๋Œ€": ["5", "6"],
    "40๋Œ€": ["7", "8"],
    "50๋Œ€ ์ด์ƒ": ["9", "10", "11"],       # 50์„ธ~
}
GENDERS = {"m": "๋‚จ์„ฑ", "f": "์—ฌ์„ฑ"}


def _headers() -> dict:
    # .strip(): ์‹œํฌ๋ฆฟ ๋“ฑ๋ก ์‹œ ๋”ธ๋ ค์˜จ ๊ฐœํ–‰/๊ณต๋ฐฑ์ด HTTP ํ—ค๋” ๊ฒ€์ฆ์„ ๊นจ๋Š” ๊ฒƒ ๋ฐฉ์ง€(HF Secrets ๋ถ™์—ฌ๋„ฃ๊ธฐ ์ด์Šˆ)
    return {
        "X-Naver-Client-Id": os.environ["NAVER_CLIENT_ID"].strip(),
        "X-Naver-Client-Secret": os.environ["NAVER_CLIENT_SECRET"].strip(),
        "Content-Type": "application/json",
    }


def _segment_score(keyword: str, gender: str, ages: list, start: str, end: str) -> float:
    # ํ•œ ์„ธ๊ทธ๋จผํŠธ์—์„œ [ํ‚ค์›Œ๋“œ, ์•ต์ปค]๋ฅผ ๊ฐ™์€ ์š”์ฒญ์œผ๋กœ ์ •๊ทœํ™” โ†’ ํ‚ค์›Œ๋“œ/์•ต์ปค ํ‰๊ท ๋น„์œจ ๋ฐ˜ํ™˜
    body = {
        "startDate": start, "endDate": end, "timeUnit": "month",
        "keywordGroups": [
            {"groupName": "kw", "keywords": [keyword]},
            {"groupName": "anchor", "keywords": [ANCHOR]},
        ],
        "gender": gender, "ages": ages,
    }
    res = requests.post(URL, json=body, headers=_headers(), timeout=10)
    res.raise_for_status()
    groups = {g["title"]: g["data"] for g in res.json()["results"]}

    def avg(rows):
        return sum(d["ratio"] for d in rows) / len(rows) if rows else 0.0

    kw, anchor = avg(groups.get("kw", [])), avg(groups.get("anchor", []))
    return kw / anchor if anchor else 0.0


def demographics(keyword: str) -> dict:
    # ์„ฑ๋ณ„ร—์—ฐ๋ น 8๊ฐœ ์„ธ๊ทธ๋จผํŠธ์˜ ์ถ”์ • ๋น„์ค‘(%) ๋ฐ˜ํ™˜
    end = date.today().replace(day=1) - timedelta(days=1)        # ์ง€๋‚œ๋‹ฌ ๋ง์ผ
    start = end.replace(year=end.year - 1, day=1)                # ์•ฝ 13๊ฐœ์›” ์ „ 1์ผ
    cells, total = [], 0.0
    for g, glabel in GENDERS.items():
        for alabel, ages in AGE_BANDS.items():
            score = _segment_score(keyword, g, ages, start.isoformat(), end.isoformat())
            cells.append({"gender": glabel, "age": alabel, "score": round(score, 4)})
            total += score
    for c in cells:
        c["pct"] = round(c["score"] / total * 100, 1) if total else 0.0
    return {"cells": cells, "anchor": ANCHOR}