Python 챌린지 - 2회차

Suhyeon Lee·2024년 11월 15일
0

라이브 세션

목록 보기
21/37

1회차 숙제 해설

숙제



목적

  • API를 이용하여 데이터를 수집하고 CSV 파일로 저장하는 방법을 학습
    • Requests로 API 요청 보내기
    • 응답 데이터 처리 및 JSON 데이터 파싱
    • 수집한 데이터를 CSV 파일로 저장



OpenWeatherAPI 회원가입 및 API_KEY 발급

https://openweathermap.org/



API(Application Programming Interface)란?

  • 서로 다른 소프트웨어 시스템이 통신할 수 있도록 도와주는 인터페이스
  • 데이터 분석에서는 웹사이트나 서버에서 제공하는 데이터를 API를 통해 요청하여 쉽게 가져올 수 있음
  • 일반적으로 JSON 형식으로 데이터를 응답하며, 이를 파싱하여 원하는 형태로 처리할 수 있음

데이터분석가에게 API란?

  • 외부 서비스와의 통신을 통해 방대한 양의 데이터를 효율적으로 수집할 수 있는 강력한 도구
  • 실시간 데이터, 공공 데이터, 소셜 미디어 데이터 등 다양한 소스에서 분석에 필요한 자료를 신속히 확보할 수 있음
  • 구조화된 데이터를 활용하여 보다 정밀한 분석과 시계열 모니터링, 트렌드 분석이 가능
  • 데이터 분석가가 다양한 데이터 소스를 활용할 수 있는 능력을 키우는 데 중요한 기술


Requests로 API 요청 보내기

  • requests 라이브러리를 사용하여 API에 요청을 보낼 수 있음
import requests

url = "https://api.example.com/data"  # 예제 API URL
params = {
    "key": "YOUR_API_KEY",  # API 키 (실제 키로 교체)
    "parameter1": "value1",  # 예시 파라미터 값
    "parameter2": "value2"   # 예시 파라미터 값
}

response = requests.get(url, params=params)

API 키

  • 보안과 인증을 위해 API 키가 필요한 경우가 많음
  • 요청 시 키를 포함하여 인증 절차를 거치게 되며, 보통 API 제공자가 발급한 키를 사용
  • 제공하는 데이터 소스에 따라 해당 API KEY를 header에 붙여서 보내는 방법도 존재
    • 자세한 부분은 제공 업체의 API Documentation을 확인하면 됨!

파라미터 ★

  • 요청에 함께 전달하는 값
  • 특정 데이터나 필터링 조건을 지정할 수 있음

    • API 문서에서
      요구되는 필수 및 선택 파라미터를
      확인하여 사용


응답 데이터 처리 및 JSON 파싱

  • 응답 데이터는 일반적으로 JSON(JavaScript Object Notation) 형식으로 제공됨
  • JSON 형식
    • Python의 딕셔너리 형태와 매우 유사
    • 키-값 쌍으로 데이터를 저장하는 구조
    • 문자열로 된 키와 다양한 데이터 유형의 값을 사용할 수 있음 → Python 딕셔너리의 사용 방식과 거의 동일하여 변환과 활용이 쉽다!
data = response.json()  # JSON 응답을 Python 딕셔너리로 변환
print(data)

예제: JSON 데이터에서 특정 값 추출 ★

# 예제 데이터가 {'name': 'John', 'age': 30, 'location': 'Seoul'} 형식이라고 가정
name = data.get('name')
# data['name']도 가능 → API가 제공하는 데이터는 형식이 갖춰져 있어서 쉽게 접근 가능
age = data.get('age')
location = data.get('location')

print(f"이름: {name}, 나이: {age}, 위치: {location}")

실습: OpenWeather API를 활용해 서울의 날씨 데이터 가져오기 ★★★

  1. API 문서 확인
    a. 입력 파라미터 확인: https://openweathermap.org/current#name
    → 도시 이름을 받아서 날씨 정보를 가져오는 API request(call by city name) url 확인
    b. 응답 예시: https://openweathermap.org/current#example_JSON
    → API respose sample 확인(JSON 형식)

https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}
: 물음표 다음에 나오는 게 파라미터

둘 다 똑같은 결과 나오지만 적는 방법이 두 개로 나눠짐 → 우리는 2번째 사용

  1. .env 파일에 API_KEY 저장
  • .env 파일
    • 중요한 정보(API KEY, DB password 등)를 숨기는 데 중요한 파일

  • templete.env 파일 열고 API_KEY = '...'의 ... 대신 Key 넣고 .env로 파일 이름 수정하기
    • 터미널에서 해당 파일이 있는 경로로 이동한 뒤 mv template.env .env 해도 됨
  • .env 파일 쓰는 이유
    • 유료 계정을 전체 공개해 버리면 다른 사람이 다 쓰잖아요…
      🡆 dotenv로 불러와서 사용하면 보안상 좋음

.env 저장이 곤란하신 분들은 terminal 이나 command prompt 에서 아래와 같이 입력해서 만들어주세요.
폴더는 현재 챌린지 수업 자료 ipynb 폴더랑 동일해야됩니다. (pwd 로 확인)
... 말고 실제 키를 입력해주세요
<mac / 리눅스 환경>
echo 'API_KEY="..."' > .env
< windows 환경 >
echo API_KEY="..." > .env

Jupyter 노트북에서 401 오류 뜨시면 .env 파일 다시 저장해주시고 노트북을 꼭 restart 한 다음에 코드를 돌려주세요!

  1. requests를 활용하여 OpenWeather API에 요청을 보내고 응답 가져오기
  2. 응답에서 날씨, 온도, 습도 정보 등을 추출

01. 패키지 불러오기

import requests
import pandas as pd 
import os 
from dotenv import load_dotenv
load_dotenv()

02. Requests를 통해 웹사이트 HTML 가져오기

# OpenWeather API 요청을 위한 기본 설정
# (https://openweathermap.org/api/one-call-3#current)

# 첫 번째 방법
api_key = os.environ.get('API_KEY')  # 본인의 API 키를 입력하세요.
city_name = "Seoul"                  # 도시는 "서울"로 설정
url = f"http://api.openweathermap.org/data/2.5/weather?q={city_name}&units=metric&appid={api_key}"
response = requests.get(url)
# 두 번째 방법
api_key = os.environ.get('API_KEY')  # 본인의 API 키를 입력하세요.
city_name = "Seoul"                  # 도시는 "서울"로 설정
params = {
    "q": city_name,  
    "units": "metric", 
    "appid": api_key
}
url = "http://api.openweathermap.org/data/2.5/weather"
response = requests.get(url, params=params)

03. Python 딕셔너리를 통해 HTML 파싱 후 출력

# API 응답 데이터 처리
data = response.json()

# 간단한 Pandas 전처리 수행
df_weather = pd.json_normalize(data) # JSON 데이터를 Pandas 형태로 변환(테이블화)
df_weather["measured_at"] = pd.to_datetime(df_weather["dt"], unit="s") + pd.Timedelta(hours=9) # 기준시간 
df_weather["dt"] = df_weather["measured_at"].dt.strftime('%Y%m%d') # 기준년월일 (YYYYMMDD) 
df_weather["time"] = df_weather["measured_at"].dt.strftime('%H%M%S') # 기준년월일 (HHHHMMSS) 
df_selected = df_weather[["dt", "time", "measured_at", "id", "name", "main.temp", "main.humidity", "wind.speed"]]
df_selected = df_selected.rename( # 컬럼명 수정 
    columns={"name": "city", "main.temp": "temperature", "main.humidity": "humidity", "wind.speed": "wind_speed"}
)
df_selected
  • 시간이 UTC임 → 전처리 시 한국 시간으로 맞춰줘야 함!
    • pd.Timedelta(hours=9)
  • 파라미터 unit
    • imperial: Fahrenheit
    • metric: Celsius
    • standard: Kelvin (default)
  • 파라미터 lang
    • description 언어 설정 변경
    • defalut는 영어: "rain"
      • 한국어로 바꾸면 "비"라고 써져 있음

QnA

  • 서울 말고 whole global cities를 가져오려면 for 문 써야되나요?



데이터 CSV 파일로 저장

  • 수집한 데이터를 CSV 파일로 저장하여 활용할 수 있음
import pandas as pd

# 데이터 준비
df = pd.DataFrame(df_selected)
df.to_csv('weather_api.csv', index=False)

print("날씨 정보가 CSV 파일로 저장되었습니다.")


한국어 사용자를 위한 서비스에 사용하기 위한 오픈 API 모음

https://github.com/dl0312/open-apis-korea



API 활용의 장단점

장점

  • 데이터 수집의 용이성
  • 실시간 데이터
  • 일관된 데이터 형식

단점

  • 요청 제한
  • 인증 필요
  • 데이터 접근 제한


Class로 만들어보자

  • 날씨 API를 활용하여 클래스 만들기
    • 특정 도시의 날씨 정보를 API를 통해 가져오는 기능을 하는 WeatherApiClient 클래스 생성
import requests

class WeatherApiClient:
    """
    OpenWeatherMap API 클라이언트를 사용하여 날씨 데이터를 가져오는 클래스입니다.
    """

    def __init__(self, api_key: str):
        self.base_url = "http://api.openweathermap.org/data/2.5"
        if api_key is None:
            raise Exception("API 키는 None으로 설정할 수 없습니다.")
        self.api_key = api_key

    def get_city(self, city_name: str, temperature_units: str = "metric") -> dict:
        """
        지정된 도시의 최신 날씨 데이터를 가져옵니다.

        Parameters:
        - city_name (str): 날씨 정보를 조회할 도시 이름.
        - temperature_units (str): 온도 단위 (기본값은 'metric'으로 섭씨 기준).
                                   'metric'은 섭씨, 'imperial'은 화씨, 'standard'는 켈빈 단위를 의미합니다.

        Returns:
        - dict: 요청한 도시의 날씨 데이터가 포함된 JSON 응답을 반환합니다.

        Raises:
        - Exception: API 요청이 실패한 경우 상태 코드와 응답 메시지와 함께 예외가 발생합니다.
        """
        params = {"q": city_name, "units": temperature_units, "appid": self.api_key}
        response = requests.get(f"{self.base_url}/weather", params=params)
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(
                f"Open Weather API에서 데이터를 추출하지 못했습니다. 상태 코드: {response.status_code}. 응답: {response.text}"
            )

작성한 함수 상세

__init__

  • API 클라이언트 객체를 생성할 때 API 키를 초기화함
  • API 키가 없는 경우 예외를 발생시킴

get_city

  • 도시 이름과 온도 단위를 파라미터로 받아 해당 도시의 최신 날씨 데이터를 Open Weather API를 통해 가져옴
  • requests 라이브러리를 사용하여 API 요청을 보내고, 응답 상태 코드가 200인 경우 데이터를 반환
  • docstring을 꼼꼼하게 써 주면 좋다.

새로 만든 WeatherApiClient 를 활용해 API 를 통해 데이터를 요청하고 CSV 파일에 저장하기

import pandas as pd 
from dotenv import load_dotenv
import os 
load_dotenv()

weather_api_client = WeatherApiClient(api_key = os.environ.get("API_KEY")) 
data = weather_api_client.get_city("Seoul") 

# 간단한 전처리
df_weather = pd.json_normalize(data) # JSON 데이터를 Pandas 형태로 변환 
df_weather["measured_at"] = pd.to_datetime(df_weather["dt"], unit="s") # 기준시간 
df_weather["dt"] = df_weather["measured_at"].dt.strftime('%Y%m%d') # 기준년월일 (YYYYMMDD) 
df_weather["time"] = df_weather["measured_at"].dt.strftime('%H%M%S') # 기준년월일 (HHHHMMSS) 
df_selected = df_weather[["dt", "time", "measured_at", "id", "name", "main.temp", "main.humidity", "wind.speed"]]
df_selected = df_selected.rename( # 컬럼명 수정 
    columns={"name": "city", "main.temp": "temperature", "main.humidity": "humidity", "wind.speed": "wind_speed"}
)

# DataFrame 생성 및 CSV 파일로 저장
df = pd.DataFrame(df_selected)
df.to_csv('weather_api.csv', index=False)

추가: 미국 주식 API

숙제

OpenWeather API 회원가입 후 받은 API_KEY로 sydney에 대한 다른 정보도 출력하기

profile
2 B R 0 2 B

0개의 댓글

관련 채용 정보