260107_네이버 검색 api to bigquery with python 1차 완료

Close-up of cracked earth with dark tones, showcasing natural textures and patterns.

signaturehelper.py

import hashlib

import hmac

import base64

class Signature:

    @staticmethod

    def generate(timestamp, method, uri, secret_key):

        message = “{}.{}.{}”.format(timestamp, method, uri)

        hash = hmac.new(bytes(secret_key, “utf-8”), bytes(message, “utf-8”), hashlib.sha256)

        hash.hexdigest()

        return base64.b64encode(hash.digest())

naver_stat.py

import time

import requests

import json

import signaturehelper # 기존에 사용하시던 파일이 있어야 합니다.

def get_header(method, uri, api_key, secret_key, customer_id):

    timestamp = str(round(time.time() * 1000))

    signature = signaturehelper.Signature.generate(timestamp, method, uri, secret_key)

    return {

        ‘Content-Type’: ‘application/json; charset=UTF-8’,

        ‘X-Timestamp’: timestamp,

        ‘X-API-KEY’: api_key,

        ‘X-Customer’: str(customer_id),

        ‘X-Signature’: signature

    }

BASE_URL = ‘https://api.searchad.naver.com’

API_KEY = ‘0100000000b762fc1623971fdfdc6bd721762379d545ec0620b9c44b3150fff8591918ef4c’

SECRET_KEY = ‘AQAAAACrg1MV1zsIdwSDxAXGlRut5XIiGOQmUeXjkIM3oew7jg==’

CUSTOMER_ID = ‘2017471’

#### [특정 날짜를 조회할 때] #####

# 1. 설정값 준비

uri = ‘/stats’

method = ‘GET’

entity_id = ‘cmp-a001-01-000000008695213’ # 실제 조회할 ID 입력

# 조회 필드 설정

fields = [“impCnt”, “clkCnt”, “salesAmt”, “ctr”, “cpc”]

# 2. 파라미터 구성 (기간 직접 지정)

params = {

    ‘id’: entity_id,

    ‘fields’: json.dumps(fields),

    # datePreset 대신 timeRange를 사용합니다.

    ‘timeRange’: json.dumps({“since”: “2026-01-01”, “until”: “2026-01-06”}),

    ‘timeIncrement’: ‘allDays’ # 해당 기간 전체 합계를 가져올 경우

}

# 3. 요청 및 결과 확인

headers = get_header(method, uri, API_KEY, SECRET_KEY, CUSTOMER_ID)

r = requests.get(BASE_URL + uri, params=params, headers=headers)

print(“#response body = “, json.dumps(r.json(), indent=4, ensure_ascii=False))

##### [최근 7일 조회할 때] #####

# # 1. 설정값 준비

# uri = ‘/stats’

# method = ‘GET’

# # 조회할 엔티티 ID (캠페인ID나 광고그룹ID 등을 입력하세요)

# entity_id = ‘cmp-a001-01-000000008695213’

# # 조회하고 싶은 필드들 (노출수, 클릭수, 비용, 클릭률, 평균클릭비용)

# fields = [“impCnt”, “clkCnt”, “salesAmt”, “ctr”, “cpc”]

# # 2. 파라미터 구성 (Query String)

# params = {

#     ‘id’: entity_id,

#     ‘fields’: json.dumps(fields),         # 리스트를 JSON 문자열로 변환

#     ‘datePreset’: ‘last7days’,            # 최근 7일 (today, yesterday 등으로 변경 가능)

#     ‘timeIncrement’: ‘allDays’            # 기간 전체 합계를 가져올 때 (일별은 ‘1’)

# }

# # 중요: GET 방식의 Signature 생성 시 uri에는 파라미터가 포함되지 않은 순수 경로(‘/stats’)만 들어갑니다.

# headers = get_header(method, uri, API_KEY, SECRET_KEY, CUSTOMER_ID)

# # 3. 요청 보내기

# r = requests.get(BASE_URL + uri, params=params, headers=headers)

# # 4. 결과 출력

# print(“#response status_code = {}”.format(r.status_code))

# if r.status_code == 200:

#     print(“#response body = “, json.dumps(r.json(), indent=4, ensure_ascii=False))

# else:

#     print(“Error Message: “, r.text)

ad_management_sample.py

# import time

# import random

# import requests

# import signaturehelper

# def get_header(method, uri, api_key, secret_key, customer_id):

#     timestamp = str(round(time.time() * 1000))

#     signature = signaturehelper.Signature.generate(timestamp, method, uri, SECRET_KEY)

#     return {‘Content-Type’: ‘application/json; charset=UTF-8’, ‘X-Timestamp’: timestamp, ‘X-API-KEY’: API_KEY, ‘X-Customer’: str(CUSTOMER_ID), ‘X-Signature’: signature}

# BASE_URL = ‘https://api.searchad.naver.com’

# API_KEY = ‘0100000000b762fc1623971fdfdc6bd721762379d545ec0620b9c44b3150fff8591918ef4c’

# SECRET_KEY = ‘AQAAAACrg1MV1zsIdwSDxAXGlRut5XIiGOQmUeXjkIM3oew7jg==’

# CUSTOMER_ID = ‘2017471’

# # 평균 입찰가

# uri = ‘/estimate/average-position-bid/keyword’

# method = ‘POST’

# r = requests.post(BASE_URL + uri, json={‘device’: ‘PC’, ‘items’: [{‘key’: ‘강남성형’, ‘position’: 1}, {‘key’: ‘게스트하우스’, ‘position’: 2}, {‘key’: ‘자전거여행’, ‘position’: 3}]}, headers=get_header(method, uri, API_KEY, SECRET_KEY, CUSTOMER_ID))

# print(“#response status_code = {}”.format(r.status_code))

# print(“#response body = {}”.format(r.json()))

################260116 업데이트######################

import time

import requests

import signaturehelper

# 설정 정보

BASE_URL = ‘https://api.searchad.naver.com’

API_KEY = ‘0100000000b762fc1623971fdfdc6bd721762379d545ec0620b9c44b3150fff8591918ef4c’

SECRET_KEY = ‘AQAAAACrg1MV1zsIdwSDxAXGlRut5XIiGOQmUeXjkIM3oew7jg==’

CUSTOMER_ID = ‘2017471’

def get_header(method, uri, api_key, secret_key, customer_id):

    timestamp = str(round(time.time() * 1000))

    signature = signaturehelper.Signature.generate(timestamp, method, uri, secret_key)

    return {

        ‘Content-Type’: ‘application/json; charset=UTF-8’,

        ‘X-Timestamp’: timestamp,

        ‘X-API-KEY’: api_key,

        ‘X-Customer’: str(customer_id),

        ‘X-Signature’: signature

    }

# 평균 입찰가 조회 요청

uri = ‘/estimate/average-position-bid/keyword’

method = ‘POST’

payload = {

    ‘device’: ‘PC’,

    ‘items’: [

        {‘key’: ‘강남성형’, ‘position’: 1},

        {‘key’: ‘게스트하우스’, ‘position’: 2},

        {‘key’: ‘자전거여행’, ‘position’: 3}

    ]

}

r = requests.post(

    BASE_URL + uri,

    json=payload,

    headers=get_header(method, uri, API_KEY, SECRET_KEY, CUSTOMER_ID)

)

print(f”#response status_code = {r.status_code}”)

print(f”#response body = {r.json()}”)

bigquery_key.json

{

  “type”: “service_account”,

  “project_id”: “api-practice-20260103”,

  “private_key_id”: “4e54e760d73e785832fc5202852142f36471fb7b”,

  “private_key”: “—–BEGIN PRIVATE KEY—–\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCiaPYye31aEYGl\nXIwahmCh/0N5YV1bUNfzJQvjQn4xWD77p4K2w/6n5r73H72TEb10c7XJGfMa/8jI\nxUukzbTPzh+3vPN3UjOHQSmWI0CELrTV6fjh7zGTZPaGXWBC8TyIwA5wzj+jviCA\nIy4FSPjIFQGh9HuwPolySIvsj9zI5D9dh6HDm4AMMV0rlp9pASYInil3s65VJlpP\nTrbDcDvfv19ueVNsrdD9VHnYLd6la+3GA7Bq4NfBXcWms1G6+WY03YKWC9BLAeus\nChV8Jm8nBXgif8bx1ZZTj5CKw6zclk6TIkPIhnEdvgLMbg2GAybrUEvswTT+a7qq\nzPlWeIclAgMBAAECggEAGa+aCH/pYl5Ub8/ERMmt7NEPXdodRrzxen4IdEfm52z6\ngRiMHtW+p9VhrHnzpJfwq8NFI+obvdBodABoJ0d1akxCTe/vXZa9mY2fwyQOJxmv\n9gkMGMeYwqP8LWIFQHEgzsv5PLQR8pa2Uy29MI7K8fIIkRG2ojgxysZYgvB5zbey\n/NRv+M87hDmM6TNT7SUQQjGaB+joz/2k1gw0s51IgNvLGIc102aGuyk08l4d1Unq\ntQxJjJX3f33tTCmhY6nwFNnag1D4Z8HUaLY2P/1Cw2fMae5SRGqukDSpOoJTCclp\nFOcTpn+xAZ0TnsBHDQBG1cxgYjYVd1GQZrYhGKGl3QKBgQDaIO9HxRuaFkKDMngm\ndZC63FLjT/I+ZE+wBcGJ5DkgT38noXKyk8vY+FQymHHrxiO31TI63UmMjkgG8olw\nCex4sBRNJS/7Ah7Yr4Yj6fHTeZTrzNHLCbN+NJB0WTW3nBHhDDPbK8tro5TNK5oR\nzUv3+SSg/Jav5LldHJ81rv2XrwKBgQC+m4aS0b2pQ+E9PhiXUYQX6HNg/WyBh1C0\na9tNhx229oUgv838Y7RMTG5CEqIVnOxhu2U9g+vPWZRUeSkghG/aAxiBtKTpGYJs\nwIg3qRahV3mXoOr1sHB2i9ZYzKwToOE5Lubi+qaIqwmKTIja9uX3Za4lOwpYgneQ\nsv26/a8vawKBgQCDis0B+QoWOEpQGEWA2/E13txVnMa3fYLY4f+/ClSw+X/zBFfI\n/Xw3EjqkcG5zAwBTQkySVxSdoMgq+GSNnk5u0bDMfRqcQsEbZ257hf+BypZWRSRX\nTzhhaY2bvJi6a3IUx2kWSSjZdsKroBm/lpCzsBm4w9qTpFlsn3AbzbW8nQKBgQCY\nGy6yPXRX/lZhdAtVvfRmy9Y/QR105FIQGL5CSR/6YRHuB4JO9hXsiVW3nn0AOGEe\nwNfS1lK4/mhzXNjoHSfRV4UYBNtRNU0ykhZiLKpliJP836qA9BNbVs5vwK1VYJ46\n7uXLnnCFQdB0MA1Kh5sO6XKmPU5NQZg+vcfjkAxcDwKBgQCk9hBpafo2NLaPUl7g\ncmtw7RO0BeOHflbHAYFtdilYLDhglsLd6wvrqvsLExdaXJPNQHUP4JUQ1VK0e4yT\nUulWT0pKoW2iwhiKKrXikdM8MzSQraYITniITYiDO+CaZoLJcpbu6Te7VAhuC6sw\n7WioeKk55NzPWaL/xx+ZSXzH7Q==\n—–END PRIVATE KEY—–\n”,

  “client_email”: “id-api-practice-20260103@api-practice-20260103.iam.gserviceaccount.com”,

  “client_id”: “112353028205533869479”,

  “auth_uri”: “https://accounts.google.com/o/oauth2/auth”,

  “token_uri”: “https://oauth2.googleapis.com/token”,

  “auth_provider_x509_cert_url”: “https://www.googleapis.com/oauth2/v1/certs”,

  “client_x509_cert_url”: “https://www.googleapis.com/robot/v1/metadata/x509/id-api-practice-20260103%40api-practice-20260103.iam.gserviceaccount.com”,

  “universe_domain”: “googleapis.com”

}

bigquery_naver_api.py

import time

import json

import requests

import pandas as pd

from google.cloud import bigquery

from google.oauth2 import service_account

import signaturehelper

# — [1] 설정 정보 (기존과 동일) —

BASE_URL = ‘https://api.searchad.naver.com’

API_KEY = ‘0100000000b762fc1623971fdfdc6bd721762379d545ec0620b9c44b3150fff8591918ef4c’

SECRET_KEY = ‘AQAAAACrg1MV1zsIdwSDxAXGlRut5XIiGOQmUeXjkIM3oew7jg==’

CUSTOMER_ID = ‘2017471’

KEY_PATH = “bigquery_key.json”

PROJECT_ID = “api-practice-20260103”

TABLE_ID = f”{PROJECT_ID}.naver_ads.daily_performance”

ENTITY_ID = ‘cmp-a001-01-000000008695213’

FIELDS = [“impCnt”, “clkCnt”, “salesAmt”, “ctr”, “cpc”]

DATE_RANGE = {“since”: “2026-01-01”, “until”: “2026-01-11”}

# — [2] 함수 정의 —

def get_header(method, uri, api_key, secret_key, customer_id):

    timestamp = str(round(time.time() * 1000))

    signature = signaturehelper.Signature.generate(timestamp, method, uri, secret_key)

    return {

        ‘Content-Type’: ‘application/json; charset=UTF-8’,

        ‘X-Timestamp’: timestamp,

        ‘X-API-KEY’: api_key,

        ‘X-Customer’: str(customer_id),

        ‘X-Signature’: signature

    }

def fetch_and_upload_naver_stats():

    uri = ‘/stats’

    method = ‘GET’

    params = {

        ‘id’: ENTITY_ID,

        ‘fields’: json.dumps(FIELDS),

        ‘timeRange’: json.dumps(DATE_RANGE),

        ‘timeIncrement’: ‘1’  

    }

    headers = get_header(method, uri, API_KEY, SECRET_KEY, CUSTOMER_ID)

    print(“1. 네이버 API 요청 중…”)

    r = requests.get(BASE_URL + uri, params=params, headers=headers)

    if r.status_code != 200:

        raise Exception(f”API Error: {r.text}”)

    data_json = r.json()

    if not data_json.get(‘data’):

        print(“>> 데이터가 없습니다.”)

        return

    # 3. 데이터프레임 변환 및 컬럼명 수정

    df = pd.DataFrame(data_json[‘data’])

    if ‘dateStart’ in df.columns:

        df = df.rename(columns={‘dateStart’: ‘date’})

    # — [핵심 수정: 데이터 타입 변환] —

    # 1) date 컬럼을 문자열에서 datetime64[ns] 타입으로 변환 (BigQuery DATE 타입과 호환)

    df[‘date’] = pd.to_datetime(df[‘date’]).dt.date

    # 2) 숫자형 컬럼 변환

    numeric_cols = [‘impCnt’, ‘clkCnt’, ‘salesAmt’, ‘cpc’, ‘ctr’]

    for col in numeric_cols:

        if col in df.columns:

            df[col] = pd.to_numeric(df[col], errors=’coerce’).fillna(0)

    df[‘entity_id’] = ENTITY_ID

    # 필요한 컬럼만 필터링

    target_columns = [‘date’, ‘impCnt’, ‘clkCnt’, ‘salesAmt’, ‘ctr’, ‘cpc’, ‘entity_id’]

    df = df[target_columns]

    # 5. BigQuery 적재

    print(“2. BigQuery 데이터 적재 시작…”)

    credentials = service_account.Credentials.from_service_account_file(KEY_PATH)

    client = bigquery.Client(credentials=credentials, project=credentials.project_id)

    job_config = bigquery.LoadJobConfig(

        schema=[

            bigquery.SchemaField(“date”, “DATE”),

            bigquery.SchemaField(“impCnt”, “INTEGER”),

            bigquery.SchemaField(“clkCnt”, “INTEGER”),

            bigquery.SchemaField(“salesAmt”, “INTEGER”),

            bigquery.SchemaField(“ctr”, “FLOAT”),

            bigquery.SchemaField(“cpc”, “FLOAT”),

            bigquery.SchemaField(“entity_id”, “STRING”),

        ],

        write_disposition=”WRITE_APPEND”,

    )

    try:

        # 데이터프레임을 BigQuery에 로드

        job = client.load_table_from_dataframe(df, TABLE_ID, job_config=job_config)

        job.result()

        print(f”✅ 성공! {len(df)}건의 데이터가 {TABLE_ID}에 적재되었습니다.”)

    except Exception as e:

        print(f”❌ BigQuery 적재 실패: {e}”)

if __name__ == “__main__”:

    fetch_and_upload_naver_stats()


게시됨

카테고리

작성자

태그:

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다