strava api를 이용해 운동 데이터 mysql에 적재하기 -1

2023. 9. 5. 14:24학습/Data Engineering

import pandas as pd
import numpy as np
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

auth_url = "https://www.strava.com/oauth/token"
activites_url = "https://www.strava.com/api/v3/athlete/activities"

payload = {
    'client_id': "---",
    'client_secret': '---',
    'refresh_token': '---f',
    'grant_type': "refresh_token",
    'f': 'json'
}

print("Requesting Token...\n")
res = requests.post(auth_url, data=payload, verify=False)
access_token = res.json()['access_token']

print("Access Token = {}\n".format(access_token))
header = {'Authorization': 'Bearer ' + access_token}

# The first loop, request_page_number will be set to one, so it requests the first page. Increment this number after
# each request, so the next time we request the second page, then third, and so on...
request_page_num = 1
all_activities = []

while True:
    param = {'per_page': 200, 'page': request_page_num}
    my_dataset = requests.get(activites_url, headers=header, params=param).json()


    if len(my_dataset) == 0:
        print("breaking out of while loop because the response is zero, which means there must be no more activities")
        break

    if all_activities:
        print("all_activities is populated")
        all_activities.extend(my_dataset)

    else:
        print("all_activities is NOT populated")
        all_activities = my_dataset

    request_page_num += 1


# 평탄화 함수 - dict type mysql 넣기위해서
def flatten(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)


data_flattened = [flatten(item) for item in all_activities]
df = pd.DataFrame(data_flattened)

# NaN 처리
df = df.fillna(0)

# 고도경도 list 분리 함수
def split_latlng(row):
    if row['start_latlng']:
        row['start_latitude'], row['start_longitude'] = row['start_latlng']
    else:
        row['start_latitude'], row['start_longitude'] = [None, None]
    
    if row['end_latlng']:
        row['end_latitude'], row['end_longitude'] =  row['end_latlng']
    else:
        row['end_latitude'],  row['end_longitude'] = [None, None]
    
    return row

df = df.apply(split_latlng, axis=1)
df.drop(['start_latlng', 'end_latlng'], axis=1, inplace=True)

print(df)

payload 에 받고싶은 id와 토큰값을 입력해주면 된다.

 

 

MySQL과 같은 RDBMS에 dict 형태나 list 형태의 data를 str로 그냥 저장할수도 있겠지만.. 하지 않는 이유가 있다.

 

1. 데이터의 구조성 손실: dict와 list는 구조화된 데이터를 표현하는 데 사용되며, 이들을 문자열로 변환하면 원래의 구조 정보가 손실됩니다. 이렇게 되면 데이터를 분석하거나 처리하기 어렵다.
2. 검색 및 쿼리 성능 저하: 문자열로 저장된 데이터에 대한 검색이나 쿼리 수행 시에는 전체 문자열을 검사해야 하므로 성능이 저하된다. 반면, 정확한 자료형에 맞추어 데이터를 저장하면 인덱싱 등의 방법으로 효율적인 검색 및 쿼리가 가능합니다.
3. 데이터 무결성 문제: dict와 list를 문자열로 변환하여 저장할 경우, 해당 필드에 어떤 값이 들어갈 수 있는지 제약하기 어렵다. 따라서 잘못된 형식의 값이 입력되더라도 그것을 감지하기 어렵고, 이런 상황은 결국 데이터 무결성 문제를 야기할 수 있다.
4. 변환 과정에서 오류 발생 가능성: dict나 list를 문자열로 변환하거나 그 반대 작업을 할 때 오류가 발생할 수 있으며, 이러한 오류 처리도 추가적인 작업이 필요하다.

 

MySQL과 같은 관계형 DBMS에서는 보통 JSON 필드 타입 등을 사용하여 구조화된 데이터(dict, list 등)를 직접 저장한다.

JSON 필드 타입을 사용하면 JSON 객체 내부에 대한 수정 등이 가능해져서 위에서 언급한 문제들을 피할 수 있다.

 

이까지가 정석이고.
내가 json 타입으로 저장할수도 있겠지만 풀어서 저장한 이유는

 

to_sql() 을 이용해서 넣으려고하니 

ProgrammingError: (pymysql.err.ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')

오류가 나오기도 하고 풀어서 저장하는게 유리할 것 같아서 이다.

 

문제가되는 dict 형태의 타입을 재귀함수로 a:{e:{값1},f:{값2}} 의 형태의 데이터를

a_e = 값1

a_f = 값2 

이런식으로 차원을 눌러줬다.

 

고도는 아예 [a,b] 이런 리스트 형태라서 int 값으로 저장하는게 좋을것 같아. 풀어서 저장시키는 것이 유리하다고 생각하였다.

 

728x90