# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # 15장 웹 API

# ## 15.1 웹 API의 이해

# ### 웹 API의 데이터 획득 과정

# ### 웹 API의 인증 방식

# ### 응답 데이터의 형식 및 처리
#
# - json.dumps(데이터) 파이썬데이터를 제이슨데이터로 
# - json.loads(데이터) 제이슨데이터를 파이썬데이터로
# - requests.get(url).json() 제이슨데이터를 파이썬 데이터로
# - xmltodict.parse(데이터) xml데이터를 파이썬데이터로

# ### 웹 API 정리된 사이트
# - https://www.programmableweb.com/category/all/apis

# #### JSON 형식의 데이터 처리

# **[15장: 458 ~ 459페이지]**

# +
import json

python_dict = {          # 파이썬 딕셔너리 생성
    "이름": "홍길동",
    "나이": 25,
    "거주지": "서울",
    "신체정보": {
        "키": 175.4,
        "몸무게": 71.2
    },
    "취미": [
        "등산",
        "자전거타기",
        "독서"
    ]
}
type(python_dict)
# -

# **[15장: 459페이지]**

# +
json_data = json.dumps(python_dict)   # 파이썬 파일을 제이슨 파일로 변경하는 함수

print(type(json_data))
# -

# **[15장: 459페이지]**
# - python 파일 -> json 파일 : json.dumps()
# - 한글데이터가 깨져서 출력되기때문에 인코딩이 필수

print(json_data)

# **[15장: 459페이지]**

json_data = json.dumps(python_dict, indent=4, sort_keys=True, ensure_ascii=False) # ensure_ascii=False를 써야 한글인코딩이 됨
                                                                                    # sort_keys=True 가나다 순으로 정렬
print(type(json_data))   # 제이슨데이터                                             # indent=4 4칸 들여쓰기
print(json_data)         

# **[15장: 460페이지]**
# - json 파일 -> python 파일 : json.loads()

json_dict = json.loads(json_data)   # 제이슨 데이터를 다시 파이썬데이터로 출력
print(type(json_dict))   # 타입? 파이썬파일
display(json_dict)         # 파이썬 딕셔너리 출력

# **[15장: 460페이지]**

json_dict['신체정보']['몸무게']   # 신체정보의 몸무게를 출력 (딕셔너리 안의 딕셔너리를 키값으로 출력)

# **[15장: 460페이지]**

json_dict['취미']   # 키가 취미인 값을 출력 (리스트출력)

json_dict['취미'][0:2] # 딕셔너리의 리스트를 슬라이싱으로 출력

# **[15장: 461페이지]**

json_dict['취미'][0]  # 취미 키, 0번째 리스트 원소 출력

# #### XML 형식의 데이터 처리

# **[15장: 465페이지]**

# +
#xml데이터 작성

xml_data = """<?xml version="1.0" encoding="UTF-8" ?>
<사용자정보>
    <이름>홍길동</이름>
    <나이>25</나이>
    <거주지>서울</거주지>
    <신체정보>
        <키 unit="cm">175.4</키>
        <몸무게 unit="kg">71.2</몸무게>
    </신체정보>
    <취미>등산</취미>
    <취미>자전거타기</취미>
    <취미>독서</취미>
</사용자정보> 
"""
print(type(xml_data))    # json이나 xml은 파이썬 파일로 변환되기 전까진 str타입으로 표기됨
print(xml_data)          # xml데이터 출력
# -

# **[15장: 465페이지]**
# - json 파일 -> python 파일 (json 모듈 사용)
# - xml 파일 -> python 파일 (xmltodict 모듈 사용)
# <br/><br/>
# - json.dumps(): json파일을 파이썬파일로
# - xmltodict.parse(): xml파일을 파이썬파일로

conda install xmltodict     # xmltodict 모듈 설치하기

# - **xml to python**
# - python to json
# - json to python

# +
import xmltodict    # XML 모듈 불러오기

dict_data = xmltodict.parse(xml_data, xml_attribs=True)   # xmltodict.parse()  # xml데이터를 파이썬데이터로 변경
                                                           # 파라미터로 xml_attribs=True를 넣어 유닛값을 살려줌

display(dict_data)

#xml을 파이썬데이터로 변환시키면 orderedDictionary 형태로 변환됨 (키:값이 튜플 형태에 저장되어 있음)
# 키와 벨류를 튜플로 바꿈
# 속성값을 @unit으로 표기
# 입력값을 #text로 표기
# -

# ### xml데이터에서 파이썬로, 다시 파이썬데이터에서 제이슨데이터로
# - xml to python
# - **python to json**
# - json to python
# - 유닛값이 들어간 딕셔너리 형태로 변환됨

data_ex = json.dumps(dict_data, indent=4, sort_keys=True, ensure_ascii=False)
print(data_ex)

# - xml to python
# - python to json
# - **json to python**

# +
data_ex1 = json.loads(data_ex)
display(data_ex1)
type(data_ex1)

#딕셔너리 안의 딕셔너리 구조
# -

# **[15장: 466페이지]**
# - xml데이터에서 파이썬데이터로 변경한 후, 원소 출력하기
# - 파이썬데이터로 변경하면 이전에 json이였든 xml이였든 모두 동일한 형식(파이썬 딕셔너리)으로 출력함

dict_data['사용자정보']['이름']

# **[15장: 466페이지]**

dict_data['사용자정보']['신체정보']  # 신체정보 변수에 들어있는 딕셔너리의 각 항목을 유닛과 텍스트로 구분하여 출력

data_ex1['사용자정보']['신체정보']   # xml -> 파이썬 -> json -> 파이썬

# **[15장: 466 ~ 467페이지]**

dict_data['사용자정보']['신체정보']['키']['@unit']  # 유닛 출력, 딕셔너리로 들어있기에 키값으로 입력

dict_data['사용자정보']['신체정보']['키']['#text']  # 벨류 출력

print(data_ex1['사용자정보']['신체정보']['키']['#text'], dict_data['사용자정보']['신체정보']['키']['@unit'], sep='')

# **[15장: 467페이지]**
# - xml파일을 파이썬파일로 파싱한 다음, 각 요소를 변수로 저장해서 사용하기

# +
import xmltodict

dict_data = xmltodict.parse(xml_data)      # xml에서 파이썬데이터로 변환, xml_attribs=False로 입력하지 않는 한 속성값 유지

user_name = dict_data['사용자정보']['이름']        # 사용자정보의 이름 벨류 선택
body_data = dict_data['사용자정보']['신체정보']    # 사용자정보의 신체정보 벨류 선택

height = body_data['키']['#text']             # 키의 벨류 선택
height_unit = body_data['키']['@unit']        # 키의 유닛 선택

weight = body_data['몸무게']['#text']            # 몸무게의 벨류 선택
weight_unit = body_data['몸무게']['@unit']       # 몸무게의 유닛 선택

print("[사용자 {0}의 신체정보]".format(user_name))       #  사용자 이름 벨류를 넣은 문장 출력
print("*키: {0}{1}".format(height, height_unit))         #  키 벨류와 키 유닛 출력
print("*몸무게: {0}{1}".format(weight, weight_unit))     # 몸무게 벨류와 몸무게 유닛 출력
# -

# **[15장: 467페이지]**

# +
dict_data2 = xmltodict.parse(xml_data, xml_attribs=False)   # 유닛값 제외하고 파이썬데이터로 변환

print(type(dict_data2))
dict_data2

# +
dict_data3 = ([('이름', '홍길동'), ('나이', '25'), ('거주지', '서울')])
print(type(dict_data3))

dict_data3['이름']  

# 리스트안에 직접 튜플을 넣을 경우, 딕셔너리처럼 검색되지 않음
# 하지만 xml을 파이썬객체로 변환시키면 OrderedDict타입으로 변환되고, 리스트 안의 튜플형태로 저장되고 딕셔너리의 기능을 수행함
# -

# ### 웹 사이트 주소에 부가 정보 추가하기

# #### 웹 사이트 주소에 경로 추가하기

# **[15장: 468페이지]**
# - url 합치기

base_url = "https://api.github.com/"
sub_dir = "events"
url = base_url + sub_dir
print(url)

# - requests.get()하여 해당 url 가져오기

# +
import requests

r = requests.get(base_url+sub_dir).url
r
# -

dir(requests.get(base_url+sub_dir))   # requests.get() 하여 사용할 수 있는 메소드 리스트

# **[15장: 469페이지]**

# +
#방법1
import requests

base_url = "https://api.github.com/"      # 상위 주소
sub_dirs = ["events", "user", "emails" ]  # 하위 주소 (리스트)


for sub_dir in sub_dirs:           # for반복문
    url_dir = base_url + sub_dir   # 상위주소와 하위주소를 더함 (3번 반복, 3개 주소 생성)
    r = requests.get(url_dir)      # 주소의 데이터를 requests로 불러오기
    print(r.url)                   # 스크래핑에서는 .text를 붙여서 소스코드를 불러왔지만,
                                   # 이번에는 .url를 붙여서 주소를 불러오기

# +
'''
같은 방법
웹스크레이핑에서 requests.get(주소).text로 바로 소스코드를 불러왔듯
                 requests.get(주소).url로 바로 url을 불러오기'''

import requests

base_url = "https://api.github.com/"      # 상위 주소
sub_dirs = ["events", "user", "emails" ]  # 하위 주소 (리스트)


for sub_dir in sub_dirs:             # for반복문
    url_dir = base_url + sub_dir
    r = requests.get(url_dir).url
    print(r)
# -

# request.get()을 넣지 않은 반복문?  (딕셔너리 형태의 파라미터를 넣지 않는다면 차이 없음)
for sub_dir in sub_dirs:          
    url_dir = base_url + sub_dir
    print(url_dir)

# #### 웹 사이트 주소에 매개변수 추가하기

# **[15장: 470페이지]**

# +
import requests

LAT = '37.57'  # 위도
LON = '126.98' # 경도
API_KEY = '<KEY>' # API 키(임의의 API 키, 권한을 받지 않은 API이기에 실행 안됨)
UNIT = 'metric' # 단위

site_url = "http://api.openweathermap.org/data/2.5/weather"    # 상위주소
parameter = "?lat=%s&lon=%s&appid=%s&units=%s"%(LAT, LON, API_KEY, UNIT)  # 하위 주소 (문자열의 %s 부분에 변수를 대입)
url_para = site_url + parameter    # 전체 주소

r = requests.get(url_para)   # 주소의 웹정보 가져오기
print(r.url)                 # 가져온 웹정보중 주소 불러오기
print(url_para)              # 그냥 출력해도 동일 (딕셔너리 파라미터를 쓰지 않는 경우 동일하게 출력됨)
# -

# - url주소 디코딩 함수 : requests.utils.unquote()

# +
url_ex = 'https://www.google.com/search?biw=1280&bih=610&tbm=isch&sa=1&ei=Z_ZcXeDMLrnemAW68bDYBA&q=우주&oq=우주&gs_l=img.3..35i39j0l9.7639.7987..8131...1.0..1.99.386.4......0....1..gws-wiz-img.eOi8KabzOfY&ved=0ahUKEwignOP2u5PkAhU5L6YKHbo4DEsQ4dUDCAY&uact=5'

decode_ex = requests.utils.unquote(url_ex)

print(url_ex)
print(decode11)   # 이미 디코딩 되어있는 API키였음
# -

# **[15장: 471페이지]**

# +
import requests  

LAT = '37.57'  # 위도
LON = '126.98' # 경도
API_KEY = '<KEY>' # API 키(실행되지 않는 임의의 API 키)
UNIT = 'metric' # 단위

req_url = "http://api.openweathermap.org/data/2.5/weather"
req_parameter = {"lat":LAT, "lon":LON , "appid": API_KEY, "units":UNIT}  # 파라미터를 딕셔너리에 입력
r = requests.get(req_url,params=req_parameter)  # requests.get()함수안에 params=을 써서 속성값 지정
                                                 # 속성값으로 입력된 req_parameter딕셔너리는 하위주소로 자동생성됨
                                                 # 해당 주소의 정보를 불러옴
        
print(r.url)    # 해당 주소 정보의 url불러오기
print(r.text)
print(r)

# 여기서 쓰인 requests.get()함수는 딕셔너리를 자동으로 입력하여 주소를 만들어주기때문에 꼭 필요한 기능을 수행함
# -

# #### 웹 사이트 주소의 인코딩과 디코딩 
# - requests.utils.unquote()로 url 주소 디코딩하기

# **[15장: 471 ~ 472페이지]**

# +
import requests

API_KEY = "<KEY>" 
                                                   # 서버와 브라우저 간 통신을 하기위해 인코딩이 되어있는 API키

API_KEY_decode = requests.utils.unquote(API_KEY)  # requests 모듈의 utils.unquote()함수로 API를 디코딩함

print("Encoded url(인코딩된 주소):", API_KEY)
print("Decoded url(디코딩된 주소):", API_KEY_decode)
# -

# **[15장: 472페이지]**

# +
req_url = "http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList"   # 상위주소

tm_x = 244148.546388    # 1번 파라미터 tm_x
tm_y = 412423.75772     # 2번 파라미터 tm_y

req_parameter = {"ServiceKey":API_KEY_decode, "tmX":tm_x, "tmY":tm_y}   # API와 그외 파라미터를 담아 딕셔너리 생성

r = requests.get(req_url,  params = req_parameter) # requests.get()으로 상위주소와 딕셔너리 파라미터를 담아서 전체주소를 만들고,
                                                   # 해당 주소의 정보 가져오기
print(r.url)   # 해당 주소의 url 가져오기

# +
# 가져온 url 디코딩하기

url = 'http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList?ServiceKey=<KEY>2Bx3evdvbaRBvhWEerg3efac2r3f3RfhDTERTw%2B9rkvoewRV%2Fovmrk3dq%3D%3D&tmX=244148.546388&tmY=412423.75772'

decode1 = requests.utils.unquote(url)
decode1 

#디코딩을 하면 전체 주소는 (상위주소) ? (API_key) & (파라미터1) & (파라미터2).. 로 구성됨
# -

# **[15장: 473페이지]**

# +
req_url = "http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList"   # 상위주소
req_parameter = {"ServiceKey":API_KEY, "tmX":tm_x, "tmY":tm_y}     # 디코딩하지 않은 API와 다른 파라미터로 딕셔너리 생성

r = requests.get(req_url,  params = req_parameter)    # 상위주소와 하위주소(딕셔너리정보)를 넣어 requests.get으로 정보 받아오기
print(r.url)    # 받아온 정보에서 url 불러오기 (동일)
# -

# #인코딩 url - http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList?ServiceKey=et5piq3pfpqLEWPpCbvtSQ%252Bertertg%252Bx3evdvbaRBvhWEerg3efac2r3f3RfhDTERTw%252B9rkvoewRV%252Fovmrk3dq%253D%253D&tmX=244148.546388&tmY=412423.75772
# #디코딩 url - http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList?ServiceKey=et5piq3pfpqLEWPpCbvtSQ%2Bertertg%2Bx3evdvbaRBvhWEerg3efac2r3f3RfhDTERTw%2B9rkvoewRV%2Fovmrk3dq%3D%3D&tmX=244148.546388&tmY=412423.75772

# ## 15.2 API 키를 사용하지 않고 데이터 가져오기

# ### 국제 우주 정거장의 정보 가져오기 (API가 필요없는 경우)

# **[15장: 473 ~ 474페이지]**

# +
import requests    # 주소의 정보를 가져올 때 사용
import json        # 제이슨데이터를 파이썬데이터로 가져올 때 사용

url = "http://api.open-notify.org/iss-now.json"   # 주소

r = requests.get(url)    # 해당 주소의 정보를 가져오기
r.text             # url의 텍스트를 출력하기 (제이슨파일)
# -

# **[15장: 474페이지]**

# +
json_to_dict = json.loads(r.text)   # 가져온 제이슨데이터를 파이썬데이터로 변경
              
print(json_to_dict)
print(type(json_to_dict))   # 파이썬 딕셔너리 형태로 변경됨
# -

# **[15장: 474 ~ 475페이지]**
# - requests 모듈의 .json()함수를 사용해서 바로 제이슨데이터를 파이썬데이터로 가져오기

# +
import requests

url = "http://api.open-notify.org/iss-now.json"

r = requests.get(url)    # 해당 url의 정보 가져오기
json_to_dict = r.json()  # 해당 사이트의 제이슨 정보를 바로 파이썬데이터로 가져오기  .json()함수 사용

print(json_to_dict)
type(json_to_dict)       # 파이썬데이터로 저장 변수 타입확인
# -

# **[15장: 475페이지]**
# - requests.get(url).json()을 한번에 써서 해당 url의 제이슨데이터를 파이썬데이터로 한번에 가져오기

# +
import requests     # 사이트 정보 가져오는 모듈 호출

url = "http://api.open-notify.org/iss-now.json"  # url 지정

json_to_dict = requests.get(url).json()   # 해당 url의 제이슨데이터를 파이썬데이터로 받아옴(.json()함수 사용)

print(json_to_dict)
type(json_to_dict)
# -

# **[15장: 475페이지]**

json_to_dict     # 딕셔너리데이터 출력

# **[15장: 475페이지]**

# +
# 딕셔너리의 키로 값 호출

print(json_to_dict["iss_position"])   
print(json_to_dict["iss_position"]["latitude"])
print(json_to_dict["iss_position"]["longitude"])
print(json_to_dict["message"])
print(json_to_dict["timestamp"])
# -

# **[15장: 476페이지]**

# +
import requests    # 사이트 정보 가져오는 모듈 호출
import time       # 출력 간격 지정할 때 사용할 모듈 호출

url = "http://api.open-notify.org/iss-now.json"   # 사이트 주소 지정

# 함수 생성
def ISS_Position(api_url):   # url을 파라미터로 받음
    json_to_dict = requests.get(api_url).json()  # url에서 json정보를 파이썬데이터로 받아옴
    return json_to_dict["iss_position"]  # 받아온 딕셔너리의 iss_position키의 값만 리턴값으로 반환

for k in range(5):             # for 반복문으로 5회 반복
    print(ISS_Position(url))   # 함수 실행 (리턴값 출력)
    time.sleep(1)             # 10초간 휴식 (정거장의 위치를 10초에 한번씩 출력하기) 
# -

# #### 지도에서 위치 표시하기 (반복변수 실패)

# !pip install folium

# +
import requests    
import time 
import folium

url = "http://api.open-notify.org/iss-now.json"   # 사이트 주소 지정

iss_lon = 0
iss_lat = 0

# 함수 생성
def ISS_Position(iss_position_api_url): 
    json_to_dict = requests.get(iss_position_api_url).json() 
    
    global iss_lon
    global iss_lat
    
    iss_lon = json_to_dict["iss_position"]['longitude']
    iss_lat = json_to_dict["iss_position"]['latitude']
                                            

ISS_loc = folium.Map(location =[iss_lon, iss_lat]) 
ISS_loc
        
#for k in range(5):      # for 반복문으로 5회 반복
#    ISS_Position(url)   # 함수 실행
#    ISS_loc = folium.Map(location =[iss_lon, iss_lat])
#    time.sleep(5)             # 10초간 휴식 (정거장의 위치를 10초에 한번씩 출력하기) 
# -

# ### 국가 정보 가져오기

# **[15장: 476 ~ 477페이지]**

# +
import requests

url_temp = "https://restcountries.eu/rest/v1/name/"  # 각 나라별 정보를 보여주는 사이트 (상위주소)
country = "South Korea"    # 파라미터1 (국가명)

url = url_temp + country   # 상위주소 + 파라미터

js_data = requests.get(url).text   # 해당 주소의 url정보를 텍스트로 출력
display(js_data)                           # 텍스트로 출력(제이슨데이터)
type(js_data)
# -

# **[15장: 477페이지]**

json_to_list = requests.get(url).json()   # 해당 주소의 제이슨데이터를 파이썬데이터로 저장 (리스트에 담긴 딕셔너리 형태)
json_to_list

json_to_list[0]   # 가장 밖에 있는 리스트 벗기기

# **[15장: 478페이지]**

json_to_list[0]["capital"]  # 딕셔너리 전체가 리스트에 들어있음
                            # 0번째 리스트의 'capital'키를 갖는 벨류 출력 (수도명)

# **[15장: 478페이지]**

# +
import requests   # 사이트의 정보를 불러올 때 사용
import json       # 사이트의 제이슨데이터를 파이썬데이터로 변환할 때 사용

countries =["South Korea", "United States of America", "United Kingdom", "France", "Germany"]  # 국가명 리스트 생성

def country_to_capital(country):                          # 함수 생성 (파라미터는 국가명)
    url_temp = "https://restcountries.eu/rest/v1/name/"   # 상위url(api)
    url = url_temp + country                              # 상위url+파라미터(국가명)
    json_to_list = requests.get(url).json()               # 해당 주소의 제이슨데이터를 파이썬데이터로 저장 (리스트안의 딕셔너리)
    return json_to_list[0]["capital"]                     # 리턴값으로 수도명 출력
    
for country in countries:                         # for반복문 실행, 국가명 리스트의 원소를 하나씩 실행
    capital = country_to_capital(country)         # 함수에 반복변수(국가명)을 넣어 실행 (리턴값 수도명)
    print("*{0}: {1}".format(country, capital))   # 반복변수(국가명)와 for반복문의 리턴값(국가명)을 문자열에 출력
# -

# ## 15.3 트위터에 메시지 작성하고 가져오기

#  ### API 키 및 접속 토큰 생성
#

# ### Tweepy 설치 및 인증

# https://developer.twitter.com/en/apps 트위터 개발자 사이트

# **[15장: 485페이지]**

# !pip install tweepy

# +
import tweepy

# 본인이 신청해서 생성한 문자열을 각각 복사해 넣습니다.
consumer_key = '7JXVmTEI9Fpxyi9CneAnJYYvL'
consumer_secret = '<KEY>'

access_token = '<KEY>'
access_secret = '<KEY>'
# -

# **[15장: 485페이지]**

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)   # OAuth 인증 실행
auth.set_access_token(access_token, access_secret)        

# **[15장: 485페이지]**

api = tweepy.API(auth)         # API클래스를 이용해 api 객체 생성
api

# **[15장: 486페이지]**

print("name:",api.me().name)   # api키를 넣어 트위터 계정의 이름을 출력

# ### 트윗 작성하기
# @sample57448511

# **[15장: 487페이지]**

tweet_var = api.update_status('.update_status()함수를 사용하여 트윗 작성하기')  
# 생성된 api와 tweepy라이브러리의 .update_status()함수를 결합시켜 사용해 트윗을 작성함

tweet_var   # 트위터 메시지 변수의 상태정보

# **[15장: 487페이지]**

# 이미지 업로드하기
tweet_img_var = api.update_with_media("C:/myPyCode/download/python-logo.png",
                                                  '.update_with_media()함수를 사용하여 이미지와 텍스트를 작성')

tweet_img_var  # 트위터 메시지 변수의 상태정보

# ### 타임라인에서 메시지 가져오기
# - 키워드를 지정해 데이터 가져오기
# 1. Tweepy의 Stream_Listener를 상속받아 클래스를 정의
# 2. 정의한 클래스를 이용해 객체를 생성
# 3. 생성한 객체를 Tweepy의 Stream을 이용해 트위터 Stream API와 연결
# 4. Stream의 Filter를 이용해 단어를 지정하고 Stream을 시작 (Tweepy의 Stream)

# **[15장: 488페이지]**

for status in tweepy.Cursor(api.home_timeline).items(2):
    print("*", status.text)

# **[15장: 489페이지]**

for status in tweepy.Cursor(api.home_timeline).items(2):
    print("*", status._json['text'])
    print(" ==> Created at", status._json['created_at'])

# ### 키워드를 지정해 데이터 가져오기

# **[15장: 490페이지]**

# +
import tweepy

class MyStreamListener(tweepy.StreamListener):   # tweepy.StreamListener를 상속받는 클래스를 생성
    
    def on_status(self, status):                  # 클래스 안에 기능을 수행하는 함수 존재
        print(status.text) # 140자까지 출력


# -

# **[15장: 490페이지]**

myStreamListener = MyStreamListener()             # 객체 생성

# **[15장: 490페이지]**

myStream = tweepy.Stream(auth, myStreamListener)  # 


# **[15장: 491페이지]**

# +
#myStream.filter(track = ['파이썬', 'python'])   # 단어 목록을 필터에 걸음
# -

# **[15장: 491페이지]**

class MyStreamListener(tweepy.StreamListener):

    def __init__(self):
        super().__init__()
        self.tweet_num = 0

    def on_status(self, status):
        self.tweet_num = self.tweet_num + 1    # 메세지가 올때마다 1 증가
        if(self.tweet_num <= 5):
            print("***", status.text) # 140자까지 출력
            return True
        else:
            return False


# **[15장: 491페이지]**

myStreamListener = MyStreamListener()
myStream = tweepy.Stream(auth, myStreamListener)
myStream.filter(track = ['trump'])

# **[15장: 492 ~ 493페이지]**

# +
import tweepy
 
# 키, 토근, 비밀번호 지정
consumer_key = 'YOUR-CONSUMER-KEY'
consumer_secret = 'YOUR-CONSUMER-SECRET'

access_token = 'YOUR-ACCESS-TOKEN'
access_secret = 'YOUR-ACCESS-SECRET'

# OAuth 인증 진행
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_secret)
 
# 인증된 auth 변수를 이용해 트위터 API 클래스의 정의
class MyStreamListener2(tweepy.StreamListener):

    def __init__(self, max_num):
        super().__init__()
        self.tweet_num = 0
        self.max_num = max_num
    
    def on_status(self, status):
        self.tweet_num = self.tweet_num + 1
        file_name = 'C:/myPyCode/data/twitter_stream_test.txt'
        if(self.tweet_num <= self.max_num ):
            with open(file_name, 'a', encoding="utf-8") as f:
                write_text = "*** " + status.text + "\n"
                f.write(write_text)
            return True
        else:
            return False
            
    def on_error(self, status):
        print(status) # 오류 메시지 출력
        return False
        
if __name__ == '__main__':  
    myStreamListener = MyStreamListener2(5)
    myStream = tweepy.Stream(auth, myStreamListener)
    myStream.filter(track = ['머신 러닝', 'Machine Learning'])
    print("End of streaming!")
# -

# ## 15.4 정부의 공공 데이터 가져오기

# ### 회원 가입 및 서비스 신청

# ### 주소 및 우편번호 가져오기
# https://www.data.go.kr

# **[15장: 502페이지]**

# +
import requests    # 주소 정보 가져오는 모듈 호출

API_KEY  = '<KEY>'  # 인증키
API_KEY_decode = requests.utils.unquote(API_KEY)   # 디코딩한 인증키

print(API_KEY)
print(API_KEY_decode)   # 출력
# -

# **[15장: 503페이지]**

# +
req_url = "http://openapi.epost.go.kr/postal/retrieveNewAdressAreaCdService/retrieveNewAdressAreaCdService/getNewAddressListAreaCd?"
                              # 상위 주소

search_Se = "road"          # 검색구분 (dong, road, post 중에 선택)
srch_wrd = "동일로52길 3-4"  # 검색어

req_parameter = {"ServiceKey":API_KEY_decode, "searchSe":search_Se, "srchwrd":srch_wrd}  # 하위 주소 생성

r = requests.get(req_url, params = req_parameter)   # 상위주소 + 하위주소의 url 정보 받아오기
xml_data = r.text   # xml 텍스트데이터를 변수에 저장

print(xml_data)   # string 데이터
# -

# **[15장: 503페이지]**

# +
import xmltodict  # xml데이터를 파이썬데이터로 변환하는 모듈 호출 

dict_data = xmltodict.parse(xml_data)   # xmltodict.parse()함수를 이용해 xml데이터를 파이썬테이터로 변환
dict_data
# -

# **[15장: 504페이지]**

dict_data['NewAddressListResponse']['newAddressListAreaCd']  #불필요한 정보를 제외한 주소 딕셔너리

# +
adress_list = dict_data['NewAddressListResponse']['newAddressListAreaCd'] # 딕셔너리 키를 넣어 주소리스트 지정

print("[입력한 도로명 주소]", srch_wrd)   # 위에서 입력한 주소명
print("[응답 데이터에서 추출한 결과]")
print("- 우편번호:", adress_list['zipNo'])        # 주소리스트의 zipNo 값 출력 (우편번호)
print("- 도로명 주소:", adress_list['lnmAdres'])  # 주소리스트의 lnmAdres 값 출력 (도로명주소)
print("- 지번 주소:", adress_list['rnAdres'])      # 주소리스트의 rnAdres 값 출력 (지번주소)
# -

# ### 날씨 정보 가져오기

# #### 날씨 정보를 위한 서비스 신청

# #### 날씨 실황 조회

# **[15장: 509페이지]**

# +
import requests   # 웹사이트 정보 가져오는 모듈 호출

API_KEY  = 'UqlfWtXrhSxnPuX3G9jNHGX6K2jS1pmP%2Fz4AzQr9DRS6AWtBKNbYs8gOnz4o2H6gdBPSac0wR229Gy%2BJYHCh9Q%3D%3D'  # 승인된 API키
API_KEY_decode = requests.utils.unquote(API_KEY)   # 디코딩 하기

print('인코딩 API_key :', API_KEY)
print('디코딩 API_key :', API_KEY_decode)
# -

# **[15장: 510 ~ 511페이지]**

# +
import json          # 제이슨데이터를 파이썬 데이터로 변환하는 모듈
import datetime      # 날짜정보를 가져오는 모듈


                               # [날짜 및 시간 설정]
now = datetime.datetime.now() # 현재 날짜와 시간을 변수에 저장 (년월일시분초)

date = "{:%Y%m%d}".format(now) # 현재의 년월일을 변수에 저장, {:년월일} (%Y 년, %m월, %d일)
time = "{:%H00}".format(now)   # 현재의 시간(정시)을 변수에 저장, {:시00} (%H 시간, 00 정시표시)


if (now.minute >= 30):        
    time = "{0}00".format(now.hour)   # 현재 분이 30분 이상이면 이후 시간(정시) 설정
else:
    time = "{0}00".format(now.hour-1) # 현재 분이 30분 미만이면 현재 시간(정시) 설정

time = '1000'


                     # [요청 주소 및 요청 변수 지정]
req_url = "http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService2/ForecastGrib"  # 요청 주소
           

baseDate = date     # 예보 일자 지정
baseTime = time     # 예보 시간 지정(정시로 지정)

nx_val = 62         # 예보지점 X 좌표(서울시 광진구 군자동)
ny_val = 126        # 예보지점 Y 좌표(서울시 광진구 군자동)

num_of_rows = 6     # 한 페이지의 출력 개수
page_no = 1         # 페이지 번호

output_type = "json" # 응답 데이터의 형식

req_parameter = {"ServiceKey":API_KEY_decode,                  # 파라미터1 : API키
                 "nx":nx_val, "ny": ny_val,                    # 파라미터2, 3: x, y좌표
                 "base_date":baseDate, "base_time":baseTime,   # 파라미터4, 5 : 예보일자, 예보시간
                 "pageNo":page_no, "numOfRows":num_of_rows,    # 파라미터6, 7 : 페이지번호, 한페이지의 출력개수
                 "_type":output_type}                          # 파라미터8 : 응답 데이터 형식

                                                  # [데이터 요청]
r = requests.get(req_url, params = req_parameter) # 해당주소의 데이터를 가져오기

dict_data = r.json()                              # json형태의 데이터를 파이썬데이터로 변환
dict_data


# +
#편집

import json          # 제이슨데이터를 파이썬 데이터로 변환하는 모듈
import datetime      # 날짜정보를 가져오는 모듈


                               # [날짜 및 시간 설정]
now = datetime.datetime.now() # 현재 날짜와 시간을 변수에 저장 (년월일시분초)

date = "{:%Y%m%d}".format(now) # 현재의 년월일을 변수에 저장, {:년월일} (%Y 년, %m월, %d일)
time = "{:%H00}".format(now)   # 현재의 시간(정시)을 변수에 저장, {:시00} (%H 시간, 00 정시표시)


now_hour_edit = 0

if (now.hour < 10):
    global now_hour_edit
    now_hour_edit = '0' + now.hour
else:
    now_hour_edit = now.hour

print(now_hour_edit)
    
if (now.minute >= 30):        
    time = "{0}00".format(now_hour_edit)   # 현재 분이 30분 이상이면 이후 시간(정시) 설정
else:
    time = "{0}00".format(now_hour_edit-1) # 현재 분이 30분 미만이면 현재 시간(정시) 설정



                     # [요청 주소 및 요청 변수 지정]
req_url = "http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService2/ForecastGrib"  # 요청 주소
           

baseDate = date     # 예보 일자 지정
baseTime = time     # 예보 시간 지정(정시로 지정)

nx_val = 62         # 예보지점 X 좌표(서울시 광진구 군자동)
ny_val = 126        # 예보지점 Y 좌표(서울시 광진구 군자동)

num_of_rows = 6     # 한 페이지의 출력 개수
page_no = 1         # 페이지 번호

output_type = "json" # 응답 데이터의 형식

req_parameter = {"ServiceKey":API_KEY_decode,                  # 파라미터1 : API키
                 "nx":nx_val, "ny": ny_val,                    # 파라미터2, 3: x, y좌표
                 "base_date":baseDate, "base_time":baseTime,   # 파라미터4, 5 : 예보일자, 예보시간
                 "pageNo":page_no, "numOfRows":num_of_rows,    # 파라미터6, 7 : 페이지번호, 한페이지의 출력개수
                 "_type":output_type}                          # 파라미터8 : 응답 데이터 형식

                                                  # [데이터 요청]
r = requests.get(req_url, params = req_parameter) # 해당주소의 데이터를 가져오기

dict_data = r.json()                              # json형태의 데이터를 파이썬데이터로 변환
dict_data

# -

# **[15장: 512 ~ 513페이지]**

# +
# [딕셔너리 데이터를 분석해서 원하는 값 추출]

weather_items = dict_data['response']['body']['items']['item']

sky_cond = ["맑음", "구름 조금", "구름 많음", "흐림"]
rain_type = ["없음", "비", "진눈개비", "눈"] 

print("[ 발표 날짜: {} ]".format(weather_items[0]['baseDate']))
print("[ 발표 시간: {} ]".format(weather_items[0]['baseTime']))

for k in range(len(weather_items)):
    weather_item = weather_items[k]
    obsrValue = weather_item['obsrValue']
    if(weather_item['category'] == 'T1H'):
        print("* 기온: {} 도".format(obsrValue))
    elif(weather_item['category'] == 'REH'):
        print("* 습도: {} 퍼센트".format(obsrValue))
    elif(weather_item['category'] == 'SKY'):
        print("* 하늘: {}".format(sky_cond[obsrValue-1]))    
    elif(weather_item['category'] == 'PTY'):
        print("* 강수: {}".format(rain_type[obsrValue])) 
# -

# #### 일기 예보 조회

# **[15장: 513 ~ 515페이지]**

# +
import json         # 제이슨데이터를 파이썬데이터로 변환하는 모듈
import datetime     # 현재 날짜시간정보를 가져오는 모듈
    
                                 # [날짜 및 시간 설정]
now = datetime.datetime.now()    # 현재 날짜와 시간을 변수에 저장(년월일시분초)
date = "{:%Y%m%d}".format(now)   # 현재시간의 년월일을 변수에 저장 {:년월일}
time = "{:%H00}".format(now)     # 현재시간의 시간(정시)을 변수에 저장

# 현재 분이 30분 이전이면 이전 시간(정시)을 설정
if (now.minute >= 30):
    time = "{0,0=2d}00".format(now.hour)
else:
    time = "{0,0=2d}00".format(now.hour-1)

# time = '1000'    
    
    
                      # [요청 주소 및 요청 변수 지정]
req_url = "http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService2/ForecastTimeData"

baseDate = date       # 예보 일자 지정
baseTime = time       # 예보 시간 지정(정시로 지정)

nx_val = 61           # 예보지점 X 좌표(서울시 강남구 역삼동)
ny_val = 125          # 예보지점 Y 좌표(서울시 강남구 역삼동)

num_of_rows = 50      # 한 페이지에 포함된 결과 수
page_no = 1           # 페이지 번호

output_type = "json"  # 응답 데이터 형식 지정

req_parameter = {"ServiceKey":API_KEY_decode, 
                 "nx":nx_val, "ny": ny_val, 
                 "base_date":baseDate, "base_time":baseTime, 
                 "pageNo":page_no, "numOfRows":num_of_rows, 
                 "_type":output_type}

                
                       # [데이터 요청]
r = requests.get(req_url, params = req_parameter)
dict_data = r.json()  # json데이터를 파이썬데이터로 변환


weather_items = dict_data['response']['body']['items']['item']  # 변환된 파이썬데이터에서 원하는 값만 추출

#print(len(weather_items))
#print(weather_items)


    
sky_cond = ['없음', "맑음", "구름 조금", "구름 많음", "흐림"]  # 날씨상태 리스트
rain_type = ["없음", "비", "진눈개비", "눈", '소나기']           # 강수형태 리스트

print("[ 발표 날짜: {} ]".format(weather_items[0]['baseDate'])) # 발표일 출력
print("[ 발표 시간: {} ]".format(weather_items[0]['baseTime'])) # 발표시간 출력

print("[ 초단기 일기 예보 ]") # 문자열 출력


                                            # [for 반복문]
for k in range(len(weather_items)):         # weather_items의 길이만큼 실행 (30개)
    weather_item = weather_items[k]
    
    fcstTime = weather_item['fcstTime']    # weather_items 딕셔너리의 fcstTime키의 값을 변수에 저장
    fcstValue = weather_item['fcstValue']  # weather_items 딕셔너리의 fcstValue키의 값을 변수에 저장
    
    if(weather_item['category'] == 'T1H'):
        print("* 시간: {0}, 기온: {1} 도".format(fcstTime, fcstValue))
    elif(weather_item['category'] == 'REH'):
        print("* 시간: {0}, 습도: {1} 퍼센트".format(fcstTime, fcstValue))
    elif(weather_item['category'] == 'SKY'):
        print("* 시간: {0}, 하늘: {1}".format(fcstTime, sky_cond[fcstValue-1]))
    elif(weather_item['category'] == 'PTY'):
        print("* 시간: {0}, 강수: {1}".format(fcstTime, rain_type[fcstValue]))
# -

# # 실습

# +
import json         # 제이슨데이터를 파이썬데이터로 변환하는 모듈
import datetime     # 현재 날짜시간정보를 가져오는 모듈
    
                                 
now = datetime.datetime.now()    # 현재 날짜와 시간을 변수에 저장(년월일시분초)
date = "{:%Y%m%d}".format(now)   # 현재시간의 년월일을 변수에 저장 {:년월일}
time = '1000'                    #현재 시간을 임의로 설정   
    
    
                      # [요청 주소 및 요청 변수 지정]
req_url = "http://newsky2.kma.go.kr/service/SecndSrtpdFrcstInfoService2/ForecastTimeData"

baseDate = date       # 발표 일자 지정
baseTime = time       # 발표 시간 지정(정시로 지정)

nx_val = 61           # 예보지점 X 좌표(서울시 강남구 역삼동)
ny_val = 125          # 예보지점 Y 좌표(서울시 강남구 역삼동)

num_of_rows = 30      # 한 페이지에 포함된 결과 수
page_no = 1           # 페이지 번호

output_type = "json"  # 응답 데이터 형식 지정

req_parameter = {"ServiceKey":API_KEY_decode, 
                 "nx":nx_val, "ny": ny_val, 
                 "base_date":baseDate, "base_time":baseTime, 
                 "pageNo":page_no, "numOfRows":num_of_rows, 
                 "_type":output_type}
                      
r = requests.get(req_url, params = req_parameter)  # 데이터 요청
dict_data = r.json()  # json데이터를 파이썬데이터로 변환


weather_items = dict_data['response']['body']['items']['item']  # 변환된 파이썬데이터에서 원하는 값만 추출



    
sky_cond = ['없음', "맑음", "구름 조금", "구름 많음", "흐림"]  # 날씨상태 리스트
rain_type = ["없음", "비", "진눈개비", "눈"]           # 강수형태 리스트
thunder_type = ['확률없음', '낮음', '보통', '높음']  # 낙뢰 정보 리스트

print("[ 발표 날짜: {} ]".format(weather_items[0]['baseDate'])) # 발표일 출력
print("[ 발표 시간: {} ]".format(weather_items[0]['baseTime'])) # 발표시간 출력

print("[ 초단기 일기 예보 ]") # 문자열 출력

                                            # [for 반복문]
for k in range(len(weather_items)):         # weather_items의 길이만큼 실행 (30개)
    weather_item = weather_items[k]
    
    fcstTime = weather_item['fcstTime']    # 예측 시간, weather_items 딕셔너리의 fcstTime키의 값을 변수에 저장
    fcstValue = weather_item['fcstValue']  # 예측 값, weather_items 딕셔너리의 fcstValue키의 값을 변수에 저장
    
    if(weather_item['category'] == 'T1H'):    # 기온
        print("* 시간: {0}, 기온: {1} ℃".format(fcstTime, fcstValue))  
        
    elif(weather_item['category'] == 'RN1'):  # 강수량
        print("* 시간: {0}, 1시간 강수량: {1} mm".format(fcstTime, fcstValue))        

    elif(weather_item['category'] == 'SKY'):
        print("* 시간: {0}, 하늘상태: {1}".format(fcstTime, sky_cond[fcstValue]))
        
        
    elif(weather_item['category'] == 'UUU'):  # 바람1
        print("* 시간: {0}, 동서바람성분: {1} m/s".format(fcstTime, fcstValue))
        
    elif(weather_item['category'] == 'VVV'):  # 바람2
        print("* 시간: {0}, 남북바람성분: {1} m/s".format(fcstTime, fcstValue))        
                
    elif(weather_item['category'] == 'REH'):   # 습도
        print("* 시간: {0}, 습도: {1} %".format(fcstTime, fcstValue))
        
    elif(weather_item['category'] == 'PTY'):   # 강수형태 
        print("* 시간: {0}, 강수형태: {1}".format(fcstTime, rain_type[fcstValue]))  
             
    elif(weather_item['category'] == 'LGT'):   # 낙뢰
        print("* 시간: {0}, 낙뢰: {1} ".format(fcstTime, thunder_type[fcstValue]))         
        
    elif(weather_item['category'] == 'VEC'):  # 풍향
        print("* 시간: {0}, 풍향: {1} 0".format(fcstTime, fcstValue))
        
    elif(weather_item['category'] == 'WSD'):  # 풍속
        print("* 시간: {0}, 풍속: {1} 1".format(fcstTime, fcstValue))

# -

{'baseDate': 20190808, 'baseTime': 1030, 'category': 'LGT', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'LGT', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 0, 'nx': 61, 'ny': 125},
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'PTY', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0, 'nx': 61, 'ny': 125},
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'PTY', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 0, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'RN1', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'RN1', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 0, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'SKY', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 4, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'SKY', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 4, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'T1H', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 31, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'T1H', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 31, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'REH', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 75, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'REH', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 75, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'UUU', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0.5, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'UUU', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 1.3, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'VVV', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0.7, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'VVV', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 0.8, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'VEC', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 216, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'VEC', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 238, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'WSD', 'fcstDate': 20190808, 'fcstTime': 1100, 'fcstValue': 0.9, 'nx': 61, 'ny': 125}, 
{'baseDate': 20190808, 'baseTime': 1030, 'category': 'WSD', 'fcstDate': 20190808, 'fcstTime': 1200, 'fcstValue': 1.5, 'nx': 61, 'ny': 125}
 발표일자               발표시간          예보값(카테고리)   예측일자              예측시간           예보값(수치)     x좌표     y좌표

# ### 대기 오염 정보 가져오기

# #### 대기 오염 정보를 위한 서비스 신청

# #### 근접 측정소 목록 조회하기

# **[15장: 519페이지]**

# +
import requests   # 웹사이트 정보 가져오는 모듈 호출

API_KEY  = '<KEY>' # API인증키 입력
API_KEY_decode = requests.utils.unquote(API_KEY)   # 디코딩실행

print('인코딩 API :', API_KEY)
print('디코딩 API :', API_KEY_decode)
# -

# **[15장: 520페이지] 동이름을 입력해서 TM 기준좌표 구하기**

# +
req_url = "http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getTMStdrCrdnt"   # 상위주소 입력
                                       # 측정소정보 조회 서비스의 TM 기준좌표 조회 오퍼레이션

umd_name = "군자동" #읍, 면, 동 지정            # 동을 변수에 저장, 논현동
num_of_rows = 10 # 한 페이지에 포함된 결과 수   # 한페이지 출력개수를 변수에 저장
page_no = 1 # 페이지 번호                       # 출력할 페이지수를 변수에 저장
output_type = "json"                            # 불러올 데이터형식을 변수에 저장


req_parameter = {"ServiceKey":API_KEY_decode, "umdName":umd_name,   # 파라미터1, 2 : API키, 동이름
                  "pageNo":page_no, "numOfRows":num_of_rows,        # 파라미터3, 4 : 출력할페이지수, 한페이지출력개수
                 "_returnType":output_type}                         # 파라미터5 : 불러올데이터형식

dict_data = requests.get(req_url, params = req_parameter).json()    # 상위주소와 파라미터를 입력해서 생성한주소의 json정보를
                                                                    # 파이썬데이터로 불러오기
print(dict_data['totalCount']) # totalCount항목의 값
print(dict_data)

# +
{'MsrstnInfoInqireSvrVo': {'_returnType': 'json', 'addr': '', 'districtNum': '', 'dmX': '', 'dmY': '', 'item': '', 'mangName': '', 'map': '', 'numOfRows': '10', 'oper': '', 'pageNo': '1', 'photo': '', 'resultCode': '', 'resultMsg': '', 'rnum': 0, 'serviceKey': '<KEY>', 'sggName': '', 'sidoName': '', 'stationCode': '', 'stationName': '', 'tm': 0, 'tmX': '', 'tmY': '', 'totalCount': '', 'umdName': '논현동', 'ver': '', 'vrml': '', 'year': ''}, 
 'list': [{'_returnType': 'json', 'addr': '', 'districtNum': '', 'dmX': '', 'dmY': '', 'item': '', 'mangName': '', 'map': '', 'numOfRows': '10', 'oper': '', 'pageNo': '1', 'photo': '', 'resultCode': '', 'resultMsg': '', 'rnum': 0, 'serviceKey': '', 'sggName': '강남구', 'sidoName': '서울특별시', 'stationCode': '', 'stationName': '', 'tm': 0, 'tmX': '202733.974301', 'tmY': '445717.50469', 'totalCount': '', 'umdName': '논현동', 'ver': '', 'vrml': '', 'year': ''}, 
          {'_returnType': 'json', 'addr': '', 'districtNum': '', 'dmX': '', 'dmY': '', 'item': '', 'mangName': '', 'map': '', 'numOfRows': '10', 'oper': '', 'pageNo': '1', 'photo': '', 'resultCode': '', 'resultMsg': '', 'rnum': 0, 'serviceKey': '', 'sggName': '남동구', 'sidoName': '인천광역시', 'stationCode': '', 'stationName': '', 'tm': 0, 'tmX': '175850.136025', 'tmY': '434153.586394', 'totalCount': '', 'umdName': '논현동', 'ver': '', 'vrml': '', 'year': ''}
         ], 
 'parm': {'_returnType': 'json', 'addr': '', 'districtNum': '', 'dmX': '', 'dmY': '', 'item': '', 'mangName': '', 'map': '', 'numOfRows': '10', 'oper': '', 'pageNo': '1', 'photo': '', 'resultCode': '', 'resultMsg': '', 'rnum': 0, 'serviceKey': '<KEY>', 'sggName': '', 'sidoName': '', 'stationCode': '', 'stationName': '', 'tm': 0, 'tmX': '', 'tmY': '', 'totalCount': '', 'umdName': '논현동', 'ver': '', 'vrml': '', 'year': ''}, 
 'totalCount': 2
}

# 4개의 키가 들어있는 딕셔너리
# -

# **[15장: 520 ~ 521페이지]**

# +
print("[입력한 읍/면/동명]", umd_name)         # 문자열과 입력한 동이름을 출력
print("[TM 기준 좌표 조회 결과]")              # 문자열 출력

for k in range(dict_data['totalCount']):       # tatalCount키의 값 만큼(리스트의 개수만큼) 반복
    sido = dict_data['list'][k]['sidoName']    # list키값의 k번째 리스트의 sidoName키값 출력
    sgg = dict_data['list'][k]['sggName']      # list키값의 k번째 리스트의 sggName키값 출력
    umd = dict_data['list'][k]['umdName']      # list키값의 k번째 리스트의 umdName키값 출력
    tmX = dict_data['list'][k]['tmX']          # list키값의 k번째 리스트의 tmX키값 출력
    tmY = dict_data['list'][k]['tmY']          # list키값의 k번째 리스트의 tmY키값 출력
    
    print("- 위치: {0} {1} {2}".format(sido, sgg, umd))   # list키값의 k번째 리스트의 시도, 구, 동 변수를 문자열에 입력
    print("- k = {0}, TM 좌표(X, Y): {1}, {2}\n".format(k, tmX, tmY))    # 변수 k, tmX, tmY를 문자열에 입력
                                                                         # TM좌표? 정부기관에서 사용하는 좌표명
# -

# **[15장: 521페이지]**

# +
k = 1   # 원하는 위치 선택 (출력된 여러 동 중에 하나의 동 선택하기)
TM_X = dict_data['list'][k]['tmX'] # TM X 좌표   # list키값의 k번째 리스트의 tmX키값 선택
TM_Y = dict_data['list'][k]['tmY'] # TM Y 좌표   # list키값의 k번째 리스트의 tmY키값 선택

print("TM 좌표(X, Y): {0}, {1}".format(TM_X, TM_Y))  # list키값의 k번째 리스트의 tmX, tmY키값을 문자열과 출력
# -

# **[15장: 522 ~ 523페이지] 근접측정소 구하기**

# +
req_url = "http://openapi.airkorea.or.kr/openapi/services/rest/MsrstnInfoInqireSvc/getNearbyMsrstnList"
                                                              # 측정소정보 조회 서비스의 근접측정소 목록 조회 오퍼레이션

x_value = TM_X # TM 측정방식 X좌표
y_value = TM_Y # TM 측정방식 Y좌표

num_of_rows = 10 # 한 페이지에 포함된 결과 수
page_no = 1 # 페이지 번호

output_type = "json"
req_parameter = {"ServiceKey":API_KEY_decode, 
                 "tmX":x_value, "tmY":y_value,
                 "pageNo":page_no, "numOfRows":num_of_rows, 
                 "_returnType":output_type}

dict_data = requests.get(req_url, params = req_parameter).json()

print("해당 지역 근처에 있는 측정소의 개수:", dict_data['totalCount'])
# -

# **[15장: 523페이지]**

# +
print("[측정소 정보]")

for k in range(dict_data['totalCount']):
    
    stationName = dict_data['list'][k]['stationName']
    ditance = dict_data['list'][k]['tm']
    addr = dict_data['list'][k]['addr']
    
    print("- 측정소 이름:{0}, 거리:{1}[km]".format(stationName, ditance))
    print("- 측정소 주소:{0} \n".format(addr))
# -

# ## 측정 정보 가져오기

# **[15장: 525페이지]**

# +
req_url = "http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty"
                                                        # 대기오염 정보 조회서비스의 측정소별 실시간 측정정보 조회 오퍼레이션

station_name = "도산대로"    # 측정소명을 변수로 지정
data_term = "DAILY"          # 데이터기간을 'Daily'로 설정하고 변수로 지정
num_of_rows = 10             # 한페이지 출력할 결과수 지정
page_no = 1                  # 출력할 페이지수 지정
version = 1.3                # 오퍼레이션 버젼 지정
output_type = "json"         # 출력할 데이터타입을 json으로 지정

req_parameter = {"ServiceKey": API_KEY_decode,                    # 파라미터1 : API키
                 "stationName": station_name,                     # 파라미터2 : 측정소이름
                 "dataTerm":data_term, "ver": version,            # 파라미터3,4 : 데이터기간, 오퍼레이션버젼
                 "pageNo": page_no, "numOfRows" : num_of_rows,    # 파라미터5,6 : 출력할페이지수, 한페이지출력 결과수
                 "_returnType": output_type}                      # 파라미터7 : 출력할 데이터타입

dict_data = requests.get(req_url,  params = req_parameter).json()   # 해당주소의 정보 호출하기
dict_data['list'][0]   # list키값의 첫번째 리스트값 출력
#dict_data
# -

# **[15장: 527페이지]**

# +
#Grade
dataTime = dict_data['list'][0]['dataTime']   # 해당 딕셔너리의 dataTime키값을 변수에 지정

so2Grade = dict_data['list'][0]['so2Grade']   # 해당 딕셔너리의 so2Grade키값을 변수에 지정
coGrade = dict_data['list'][0]['coGrade']     # 해당 딕셔너리의 coGrade키값을 변수에 지정
o3Grade = dict_data['list'][0]['o3Grade']     # 해당 딕셔너리의 o3Grade키값을 변수에 지정
no2Grade = dict_data['list'][0]['no2Grade']   # 해당 딕셔너리의 no2Grade키값을 변수에 지정

pm10Grade1h = dict_data['list'][0]['pm10Grade1h']  # 해당 딕셔너리의 pm10Grade1h키값을 변수에 지정
pm25Grade1h = dict_data['list'][0]['pm25Grade1h']  # 해당 딕셔너리의 pm25Grade1h키값을 변수에 지정
khaiGrade = dict_data['list'][0]['khaiGrade']      # 해당 딕셔너리의 khaiGrade키값을 변수에 지정

#Value
so2Value = dict_data['list'][0]['so2Value']   # 해당 딕셔너리의 so2Grade키값을 변수에 지정
coValue = dict_data['list'][0]['coValue']     # 해당 딕셔너리의 coGrade키값을 변수에 지정
o3Value = dict_data['list'][0]['o3Value']     # 해당 딕셔너리의 o3Grade키값을 변수에 지정
no2Value = dict_data['list'][0]['no2Value']   # 해당 딕셔너리의 no2Grade키값을 변수에 지정

pm10Value = dict_data['list'][0]['pm10Value']  # 해당 딕셔너리의 pm10Grade1h키값을 변수에 지정
pm25Value = dict_data['list'][0]['pm25Value']  # 해당 딕셔너리의 pm25Grade1h키값을 변수에 지정
khaiValue = dict_data['list'][0]['khaiValue']      # 해당 딕셔너리의 khaiGrade키값을 변수에 지정

#Unit
so2Unit = 'ppm'
coUnit = 'ppm'
o3Unit = 'ppm'
no2Unit = 'ppm'

pm10Unit = '㎍/㎥'
pm25Unit = '㎍/㎥'
khaiUnit = '㎍/㎥'



print("[측정소({0})에서 측정된 대기 오염 상태]".format(station_name))  # 문자열에 측정소명을 입력하여 출력
print("- 측정 시간:{0}".format(dataTime))                              # 문자열에 측정시간을 입력하여 출력

#line1
print("- [지수] ", end='')
print("아황산가스:등급({}),농도({}{})/일산화탄소:등급({}),농도({}{})/오존:등급({}),농도({}{})/이산화질소:등급({}),농도({}{})".
      format(so2Grade, so2Value, so2Unit, coGrade, coValue, coUnit, o3Grade, o3Value, o3Unit, no2Grade, no2Value, no2Unit))# 문자열에 각각의 변수를 입력하여 출력

#line2
print("- [등급] ", end='')
print("미세 먼지:등급({}),농도({}{})/ 초미세먼지:등급({}),농도({}{})/통합대기환경:등급({}),농도({}{})".
      format(pm10Grade1h, pm10Value, pm10Unit, pm25Grade1h, pm25Value, pm25Unit, khaiGrade, khaiValue, khaiUnit)) # 문자열에 각각의 변수를 입력하여 출력
# -

# **[15장: 527 ~ 528페이지]**

# +
gradeNum2Str = {"1":"좋음", "2":"보통", "3":"나쁨", "4":"매우나쁨" }    # 등급을 문자로 변환할 딕셔너리 생성

print("[측정소({0})에서 측정된 대기 오염 상태]".format(station_name))   # 측정소를 입력한 문자열 출력
print("- 측정 시간:{0}".format(dataTime))                               # 측정시간을 입력한 문자열 출력

print("- 아황산가스:{},({}{}), 일산화탄소:{},({}{}), 오존:{},({}{}), 이산화질소:{},({}{})".
          format(gradeNum2Str[so2Grade],so2Value, so2Unit,
                 gradeNum2Str[coGrade], coValue, coUnit,
                 gradeNum2Str[o3Grade], o3Value, o3Unit,
                 gradeNum2Str[no2Grade], no2Value, no2Unit))

print("- 미세 먼지:{},({}{}), 초미세 먼지:{},({}{}), 통합대기환경:{},({}{})".
          format(gradeNum2Str[pm10Grade1h], pm10Value, pm10Unit,
                 gradeNum2Str[pm25Grade1h], pm25Value, pm25Unit,
                 gradeNum2Str[khaiGrade], khaiValue, khaiUnit))
# -

# ## 15.5 정리

StarcoderdataJupyterScriptsDedupFiltered