1.  수직 중앙 정렬에 사용하는 방법 

case 1. line-height로 부모 박스의 높이를 지정
case 2. displaydml table-cell 속성 적용 후 vertical-align 사용
case 3. position이 absolute일 경우 top: 50%; transform

 

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        div {
            width: 200px;
            height: 100px;
            border: 2px solid black;
            background-color: lightgoldenrodyellow;
            text-align: center; /* 수평 중앙 정렬 */
        }
        div.line-height {
            line-height: 100px; /* 높이를 line-height로 사용 */
        }
        div.cell {
            display: table-cell;
            vertical-align: middle;
        }
        div.rel {
            position: relative;
        }
        div.rel p {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
        }
    </style>
</head>
<body>
    <div class="line-height">vertical-align</div>
    <div class="cell">vertical-align</div>
    <div class="rel"><p>vertical-align</p></div>
    <!-- line-height를 사용할 경우에는 요소가 한줄이어야 함 -->
    <div class="inline-height">vertical-align vertical-align vertical-align</div>
</body>

출력 결과


 

2. overflow와 scroll

1)  overflow 속성


🚀  내부 요소가 부모 박스의 범위를 벗어날 때 어떻게 처리할 것인지 지정
🚀  콘텐츠가 자주 업데이트 되는 경우 높이가 콘텐츠 양에 따라 자동으로 변경이 되거나 박스의 높이를 고정값으로 할 때 사용

 

hidden : 영역을 벗어나는 부분은 보이지 않음
scroll : 영역을 벗어나는 부분은 스크롤 바가 나타남
visible : 박스를 넘어가도 보여줌
auto : 박스를 넘어가지 않으면 스크롤 바가 나오지 않고, 박스를 넘어갈 때 스크롤 바가 나타남

 

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .contents1 {
            width: 200px;
            height: 200px;
            border: 2px solid black;
            float: left;
            box-sizing: border-box;
            margin: 10px;
        }
        .contents2 {
            width: 200px;
            height: 200px;
            border: 2px solid black;
            float: left;
            box-sizing: border-box;
            margin: 10px;
            margin-left: 30px; /* 왼쪽과 바깥쪽 여백을 30px로 지정함 */
        }
        .contents3 {
            width: 200px;
            overflow: hidden;  /* 박스 높이가 지정되지 않았을 경우 박스 안의 내용만큼 박스 높이도 함께 늘어남 */
            border: 2px solid black;
            float: left;
            box-sizing: border-box;
            margin: 10px;
            margin-left: 30px;
        }
        .contents4 {
            width: 200px;
            height: 200px;
            overflow: hidden; /* 박스 높이가 지정되어있으면 지정된 높이만큼만 보여줌. */
            border: 2px solid black;
            float: left;
            box-sizing: border-box;
            margin: 10px;
            margin-left: 30px;
        }
    </style>
</head>
<body>
<!--박스의 높이에 맞게 텍스트 양을 넣은 예-->
<div class="contents1">
    <h4>콘텐츠의 양이 일정</h4>
    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown </p>
</div>

<!--박스의 높이보다 텍스트의 양이 많아서 박스 밖으로 흘러넘치는 예-->
<div class="contents2">
    <h4>콘텐츠의 양이 많거나 유동적일때 흘러 넘침</h4>
    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
</div>

<!--박스의 높이를 설정하지 않고 overflow:hidden을 지정하여 텍스트만큼 높이도 함께 늘어나는 예-->
<div class="contents3">
    <h4>콘텐츠의 양에 따라서 높이가 늘어남</h4>
    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
</div>

<!--박스의 높이를 지정하고 overflow:hidden을 주어서 높이만큼만 보여지도록 한 예-->
<div class="contents4">
    <h4>박스의 지정된 높이만큼만 콘텐츠가 보여짐</h4>
    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
</div>
</body>

 

출력 결과

 


 

2) scroll 속성

 

🚀   overflow: scroll 속성 사용
        ▶️  박스(block)의 내부 스크롤 바를 지정하고자 할 때 사용

 

overflow : 영역을 벗어나는 가로, 세로 부분을 스크롤 바로 나타나게 하거나 숨김
overflow-x : 가로 좌표에 대한 스크롤 바를 나타나게 하거나 숨김
overflow-y : 세로 좌표에 대한 스크롤 바를 나타나게 하거나 숨김

 

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .scroll_box1 {
            float: left;
            box-sizing: border-box;
            width: 200px;
            height: 200px;
            border: 2px solid black;
            margin: 10px;
            overflow: scroll; /* 가로 세로 스크롤 바를 모두 보임 */
        }
        .scroll_box2 {
            float: left;
            box-sizing: border-box;
            width: 200px;
            height: 200px;
            border: 2px solid black;
            margin: 10px;
            margin-left: 30px; /* 왼쪽 바깥쪽 여백은 30px로 지정함 */
            overflow-x: scroll; /* 가로 스크롤 바를 표시 */
            overflow-y: hidden; /* 세로 스크롤 바를 숨김 */
        }
        .scroll_box3 {
            float: left;
            box-sizing: border-box;
            width: 200px;
            height: 200px;
            border: 2px solid black;
            margin: 10px;
            margin-left: 30px; /* 왼쪽 바깥쪽 여백은 30px로 지정함 */
            overflow-x: hidden; /* 가로 스크롤 바를 숨김 */
            overflow-y: scroll; /* 세로 스크롤 바를 표시 */
        }
    </style>
</head>
<body>
    <!-- 스크롤 바를 가로, 세로 모두 표시 -->
    <div class="scroll_box1">
        <h4>SCROLL-X,Y</h4>
        <p><img src="../box2/img2/camera02.png" alt="대체이미지"></p>
    </div>
    <!-- 스크롤 바를 가로만 표시 -->
    <div class="scroll_box2">
        <h4>SCROLL-X</h4>
        <p><img src="../box2/img2/camera02.png" alt="대체이미지"></p>
    </div>
    <!-- 스크롤 바를 세로만 표시 -->
    <div class="scroll_box3">
        <h4>SCROLL-Y</h4>
        <p><img src="../box2/img2/camera02.png" alt="대체이미지"></p>
    </div>
</body>

 

출력 결과

 

 

 

 

 

[ 내용 참고: IT 학원 강의 ]


 

1. 통계  메서드

sum() 원소의 합
mean()  평균
std() 표준편차
var() 분산
min() 최솟값
max() 최댓값
cumsum() 원소의 누적 합
cumprod() 원소의 누적 곱

 

# 2012년 부터 2016년 까지 우리나라의 계절별 강수량(단위 mm).
table_data3 = {'봄': [256.5, 264.3, 215.9, 223.2, 312.8],
               '여름': [770.6, 567.5, 599.8, 387.1, 446.2],
               '가을': [363.5, 231.2, 293.1, 247.7, 381.6],
               '겨울': [139.3, 59.9, 76.9, 109.1, 108.1]}
columns_list = ['봄', '여름', '가을', '겨울']
index_list = ['2012', '2013', '2014', '2015', '2016']
df3 = pd.DataFrame(table_data3, columns=columns_list, index=index_list)
df3

df3 출력 결과

 

# 2012년에서 2016년에 걸쳐 계절별로 강수량의 평균(mean)과 표준 편차(std)를 구함.
df3.mean()
'''
봄     254.54
여름    554.24
가을    303.42
겨울     98.66
dtype: float64
'''

df3.std()  # 계절별 강수량 표준편차
'''
봄      38.628267
여름    148.888895
가을     67.358496
겨울     30.925523
dtype: float64
'''

 

    📌  연도별로 평균 강수량과 표준 편차를 구할 경우엔 연산의 방향 설정을 위해 axis인자를 추가
    📌  인자 axis가 0이면 DataFrame의 values에서 열별로 연산을 수행하고, 1이면 행별로 연산

    📌  axis 인자를 설정하지 않으면 기본값을 0으로 설정

 

df3.mean(axis=1)
'''
2012    382.475
2013    280.725
2014    296.425
2015    241.775
2016    312.175
dtype: float64
'''

df3.std(axis=1)
'''
2012    274.472128
2013    211.128782
2014    221.150739
2015    114.166760
2016    146.548658
dtype: float64
'''

💡  df.describe()

 

  -  평균, 표준편차, 최솟값과 최댓값 등을 한 번에 구할 수 있는 메서드
  -  25%, 50%, 75% : 백분위수의 각 지점으로, 분포를 반영해 평균을 보완하는 목적으로 사용

df3.describe()

 

출력 결과


 

2.  판다스 데이터  읽기

1) 표 형식 데이터 읽기

🍯  판다스에서 csv파일을 읽을 때는 read_csv() 메서드 이용

🍯  파이썬에서 텍스트파일을 생성하면 기본 문자 인코딩이 ’utf-8’이고, 메모장의 경우 기본 문자 인코딩이 ‘cp949’

DataFrame_data = pd.read_csv(file_name [, options])

 

import pandas as pd

df1 = pd.read_csv('../input/sea_rain1.csv')
df1

 

출력 결과

df1.dtypes
'''
연도      int64
동해    float64
남해    float64
서해    float64
전체    float64
dtype: object
'''

pd.read_csv('../input/sea_rain1_from_notepad.csv')
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbf in position 0: 
# invalid start byte

 

    📌  sea_rain1_from_notepad.csv 파일을 메모장으로 생성해서, 인코딩이 'cp949'이므로 에러가 남

            ▶️  메소드 안에 encoding='cp949' 를 붙여주면 된다.

# 올바른 실행 예
pd.read_csv('../input/sea_rain1_from_notepad.csv', encoding='cp949')

 

🍯  txt 파일의 경우 콤마가 아니라 공백(빈칸)으로 구분된 경우 sep 옵션을 이용해서 구분자가 콤마가 아니라 공백임을 지정
🍯  아래 처럼 확장자가 txt라도 read_csv()로 읽을 수 있음.

pd.read_csv('../input/sea_rain1_space.txt', sep=' ')

 

📌  read_csv()로 텍스트 파일을 읽어오면 index가 자동으로 지정
📌  이 때 특정 열 column을 index로 선택하려면

       'index_col=열_이름'을 추가

 

 

pd.read_csv('../input/sea_rain1.csv', index_col='연도')

출력 결과

 

 

 

 

 

[ 내용 참고 :  IT 학원 강의 ]


 

1.  DataFrame을 활용한 데이터 생성

 

🍯  표 Table와 2차원 데이터 처리를 위해 DataFrame을 제공
       ▶️  데이터 Data를 담는 틀 Frame이라는 뜻

 

 

1) 데이터 생성

df = pd.DataFrame(data [, index = index_data, columns = columns_data])


  🐰  data 인자에는 리스트와 형태가 유사한 데이터 타입은 모두 사용 가능
        🥕  리스트, 딕셔너리, numpy의 배열 데이터, Series나 DataFrame 타입의 데이터 입력 가능
  🐰  세로축 라벨을 index라 하고, 가로축 라벨을 columns 라고 함
  🐰  index와 columns를 제외한 부분을 values라고 함

 

import pandas as pd
d1 = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9]])
d1

d1 결과

 

🥕  values 부분에는 입력한 data가 순서대로 입력 돼 있고 가장 좌측의 열과 가장 윗줄의 행에는 각각 숫자가 자동으로 생성되어 index, columns를 구성
  ▶️   명시적으로 입력하지 않더라도 자동으로 index, columns가 생성

 

 


 

📁  numpy의 배열 데이터를 입력해 생성한 DataFrame 데이터의 예

import numpy as np
data_list = np.array([[10,20,30], [40,50,60], [70,80,90]])
print(data_list)
'''
[[10 20 30]
 [40 50 60]
 [70 80 90]]
'''

d2 = pd.DataFrame(data_list)
d2

d2 출력 결과


 

📁 data뿐만 아니라 index와 columns도 지정한 예

data = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])  # values
index_date = pd.date_range('2019-09-01', periods=4)
columns_list = ['A', 'B', 'C']
d3 = pd.DataFrame(data=data, index=index_date, columns=columns_list)
d3

d3 출력 결과


 

📁  딕셔너리 타입으로 2차원 데이터를 입력한 예

 

      📌  리스트나 넘파이 배열은 행 단위로 입력이 되고, 딕셔너리는 열 단위로 입력됨

table_data = {'연도': [2015, 2016, 2016, 2017, 2017],
              '지사': ['한국', '한국', '미국', '한국', '미국'],
              '고객 수': [200, 250, 450, 300, 500]}
d4 = pd.DataFrame(table_data)

d4 출력 결과

# 입력시 키의 순서를 지정할 수도 있음.
d5 = pd.DataFrame(table_data, columns=['지사', '고객 수', '연도'])
d5

d5 출력 결과


 

📁  DataFrame 데이터에서 index, columns, values을 각각 구한 예

d5.index
# RangeIndex(start=0, stop=5, step=1)

d5.columns
# Index(['지사', '고객 수', '연도'], dtype='object')

d5.values
# 0,한국,200,2015
# 1,한국,250,2016
# 2,미국,450,2016
# 3,한국,300,2017
# 4,미국,500,2017

 


 

2.  데이터 연산

🍯  Pandas의 Series()와 DataFrame()으로 생성된 데이터 끼리는 사칙연산이 가능

🍯  파이썬의 리스트와 numpy의 배열과 달리 pandas의 데이터 끼리는 서로 크기가 달라도 연산이 가능
        ▶️  이 경우 연산을 할 수 있는 항목만 연산을 수행

 

1)  Series()로 생성한 데이터의 예

import pandas as pd

s1 = pd.Series([1,2,3,4,5])
s2 = pd.Series([10,20,30,40,50])
# 덧셈
s1 + s2

'''
0    11
1    22
2    33
3    44
4    55
dtype: int64
'''
# 뺄셈
s2 - s1

'''
0     9
1    18
2    27
3    36
4    45
dtype: int64
'''
# 곱셈
s1 * s2

'''
0     10
1     40
2     90
3    160
4    250
dtype: int64
'''
# 나눗셈
s2 / s1

'''
0    10.0
1    10.0
2    10.0
3    10.0
4    10.0
dtype: float64
'''

 


 

2) 데이터의 크기가 다른 경우

 

🐰   연산할 수 있는 부분만 연산한 결과를 보여주고 연산할 수 없는 부분은 NaN으로 표시

s3 = pd.Series([1,2,3,4])
s4 = pd.Series([10,20,30,40,50])
# 덧셈
s3 + s4

'''
0    11.0
1    22.0
2    33.0
3    44.0
4     NaN
dtype: float64
'''
# 뺄셈
s4 - s3

'''
0     9.0
1    18.0
2    27.0
3    36.0
4     NaN
dtype: float64
'''
# 곱셈
s3 * s4

'''
0     10.0
1     40.0
2     90.0
3    160.0
4      NaN
dtype: float64
'''
# 나눗셈
s4 / s3

'''
0    10.0
1    10.0
2    10.0
3    10.0
4     NaN
dtype: float64
'''

 


3) DataFrame 연산

 

🐰  Series와 마찬가지로 DataFrame도 연산할 수 있는 항목 끼리만 연산하고 그렇지 못한 항목은 NaN으로 표시
        🥕 공간은 차지하되 데이터는 없는 상태

# DataFrame()으로 생성한 데이터의 예
table_data1 = {'A': [1,2,3,4,5],
               'B': [10,20,30,40,50],
               'C': [100,200,300,400,500]}
df1 = pd.DataFrame(table_data1)
df1

table_data2 = {'A': [6,7,8],
               'B': [60,70,80],
               'C': [600,700,800]}
df2 = pd.DataFrame(table_data2)
df2

 

df 1 출력결과
df2 출력 결과

df1 + df2

출력 결과

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

45


 

1.  XML 이란?

🍋  eXtensible Markup Language 은 데이터 저장 및 전달을 위해 만든 다목적 마크업 언어 Markup Language
      📌  마크업 언어는 일반적인 텍스트와 구분되는 태그 Tag를 이용해 문서나 데이터를 구조화 하는 언어

      📌  JSON과 마찬가지로 데이터 전달을 목적으로 만든 구조화된 텍스트 형식
      📌  대표적인 마크업 언어로는 HTML HyperText Markup Language

🍋  HTML의 경우는 태그가 미리 정해져 있지만 XML은 자신이 태그를 정의해서 사용할 수 있음
       ➡️ 단 XML 문서의 규칙을 따라야 함

🍋  태그는 '<문자열>'로 시작해서 '</문자열>'로 끝나야 한다
      📌  시작과 끝 태그의 문자열은 같아야 하며 대소문자를 구분

      📌  중첩해 여러 개를 이용할 수 있는데 이때 태그는 반드시 올바른 순서대로 이용해야 함

             ex.  '<abc><def> ~ </def></abc>' 와 같이 나중에 나온 시작 태그에 대응하는 끝 태그가 먼저 나와야

     📌  XML 문서에서는 시작 태그에서 끝 태그까지로 이루어진 것을 요소 element라고 함

🍋  XML 문서에는 반드시 최상위 root 요소가 있어야 함 

      📌  최상위 요소는 시작과 끝 태그로 다른 모든 요소를 감싸야 함

🍋  주석은 '<!--'와  '-->'로 문자열을 감싸서 표시. 즉 '<!-- 이것은 주석입니다 -->'와 같이 사용

🍋  xml을 지정하는 모듈은 내장 모듈로 xml이 있고, 외부 모듈의 경우 xmltodict 사용
     📌  xml 데이터를 파이썬의 딕셔너리 타입으로 바로 변환
 

🍋  xmltodict 라이브러리에서 XML 형식의 데이터를 파이썬의 딕셔너리 타입으로 변환하는 함수
     📌  xmltodict.parse(xml_input, [ xml_attribs=True 혹은 False ])
     📌  xml_input은 XML 타입의 데이터
     📌  xml_attribs은 기본 값은 True
            ➡️  False 이면 XML 형식의 데이터를 딕셔너리 타입으로 변환할 때 속성을 무시

 

🍋   pprint.pprint() 함수를 사용하면 내용이 들여쓰기 된 상태로 보기좋게 출력 가능  

import xmltodict
import pprint

with open('../input_2/data.xml', 'r', encoding='utf-8') as xml_file:
    dict_data = xmltodict.parse(xml_file.read(), xml_attribs=True)  # xml 데이터를 딕셔너리로 변경
    #print(dict_data)
    #print(dict_data['response']['body']['items'])
    datas = dict_data['response']['body']['items']
    pprint.pprint(datas)

 

data.xml 내용

 

실행 결과

 

 


 

2. 오페라 공연 제목과 링크주소 추출 및 저장

 

import csv
from datetime import datetime
import xmltodict
import pprint
import requests

# 1. 데이터 추출
url = 'https://www.daeguoperahouse.org/rss.php'
response = requests.get(url)
dict_data = xmltodict.parse(response.text)
pprint.pprint(dict_data)

실행 결과


 

# 2. 필요한 데이터 추출하기

data_list = dict_data['rss']['channel']['item']

new_datas:list[dict] = list()  # 필요 내용만 담을 리스트 필요

for k in data_list:
    new_data = dict()
    new_data['title'] = k['title']
    new_data['link'] = k['link']
    new_datas.append(new_data)
pprint.pprint(new_datas)

 

실행 결과


# 3. 현재 날짜로 파일명 지정해서 저장하기

today = datetime.now().strftime('%y%m%d')  # 현재 날짜 구하기
print(today)

with open(f'../output_02/daeguoperahouse_{today}.csv', 'wt', newline='', encoding='utf-8') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames=['title', 'link'])
    writer.writeheader()
    for k in new_datas:
        writer.writerow(k)

print('파일 생성을 성공했습니다.')

파일 생성 완료

 

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

 


 

1.  API 통해 위치 정보 얻기

import urllib.request as request
import json
import datetime

# API 이용하기
# openweathermap.org

api_key: str = 'd1569da48f0b4251e9ec538982a29548'

# 대구 위치 정보 얻기
# https://openweathermap.org/api/geocoding-api

city: str = 'Taegu'
url: str = f'http://api.openweathermap.org/geo/1.0/direct?q={city}&limit=5&appid={api_key}'
print(url)

json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
lat = dict_data[0]['lat']
lon = dict_data[0]['lon']
print(f'{lat} / {lon}')

# 현재 날씨
# https://openweathermap.org/current
# lang=kr : 한국어 사용
# units=metric : 섭씨온도

url = (f'https://api.openweathermap.org/data/2.5/weather?lat={lat}&'  #위도
       f'lon={lon}&'  #경도
       f'appid={api_key}&'
       f'lang=kr&'
       f'units=metric')
print(url)
json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
json_data = json.dumps(dict_data, indent=4)
# print(json_data)

print(f'도시 : {dict_data["name"]}')
print(f'현재날씨 : {dict_data["weather"][0]["description"]}')
print(f'최고기온 : {dict_data["main"]["temp_max"]}')
print(f'최저기온 : {dict_data["main"]["temp_min"]}')
print(f'일출시간 : {datetime.datetime.fromtimestamp(dict_data["sys"]["sunrise"])}')
print(f'일몰시간 : {datetime.datetime.fromtimestamp(dict_data["sys"]["sunset"])}')

# 날씨 예보 : 5days / 3 hours
# https://openweathermap.org/forecast5

url: str = (f'https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={api_key}&lang=kr&'
       f'units=metric')
print(url)

json_data = request.urlopen(url).read()
dict_data = json.loads(json_data)
json_data = json.dumps(dict_data, indent=4)
print(json_data)

weather_list = dict_data['list']  #json 데이터 중에서 list key에 해당하는 목록 가져오기.
#print(weather_list)

for item in weather_list:
       print(f'시간: {datetime.datetime.fromtimestamp(item["dt"])}', end=', ')
       print(f'최고기온: {item["main"]["temp_max"]}', end=', ')
       print(f'날씨: {item["weather"][0]["main"]}', end=', ')
       print(f'날씨: {item["weather"][0]["description"]}')
       print()

 

print(url) 을 실행했을 때 나온 주소창으로 들어가면 나오는 데이터

 

실행결과

 


 

2. 공공데이터를 JSON 타입으로 받아 필요한 내용 출력하고  CSV 타입으로 저장

 

# 공공데이터 포탈에서 '대구광역시_맛집' 검색 (키사용이 없음)
# https://www.data.go.kr/data/15057236/openapi.do
# 중구의 맛집 목록을 json 타입으로 받아서 처리

# 1. 음식카테고리 출력
# {'한식', '일식', '세계요리', '중식', '전통차/커피전문점', '특별한 술집', '디저트/베이커리', '양식'}

# 2. 일식의 음식점명, 연락처, 메뉴 출력
# --------------------
# 음식점명: 종로초밥
# 연락처: 053-252-0321
# 메뉴: 광어회 50,000원 <br />모둠회 40,000원 <br />무침회 20,000원<br />
# --------------------
# 음식점명: 삼삼구이초밥
# 연락처: 053-425-3392
# 메뉴: 회덮밥 9,000원 <br />미주구리 30,000원 <br />점심특선 6,000원<br />
# --------------------
import json
import urllib.request as request


url: str = "https://www.daegufood.go.kr/kor/api/tasty.html?mode=json&addr=%EC%A4%91%EA%B5%AC"

json_data = request.urlopen(url).read()
dict_data: dict = json.loads(json_data)
# print(dict_data)

# 문제 1)
food_kind = set()  # 중복 값 걸러주는 set 활용
for row in dict_data['data']:
    food_kind.add(row['FD_CS'])
print(food_kind)


# 문제 2)
for item in dict_data['data']:
    kind = item['FD_CS']
    if kind == "일식":
        print(f'음식점명: {item["BZ_NM"]}')
        print(f'연락처: {item["TLNO"]}')
        print(f'메뉴: {item["MNU"]}')
        print("-" * 20)

# 3. csv 파일 저장
# 파일명 : daegu_food_jonggu_list.csv
# 인코딩 : utf-8
# 헤더 : '음식 카테고리', '음식점명', '연락처', '메뉴'
import csv

food_list: list[dict] = list()
name_list: list[str] = ['음식 카테고리', '음식점명', '연락처', '메뉴']  
# csv 헤더 및 딕셔너리의 key값으로 사용.

for data in dict_data['data']:
    if data['FD_CS'] == '일식':
        new_data: dict = dict()
        new_data[name_list[0]] = data['FD_CS']
        new_data[name_list[1]] = row["BZ_NM"]
        new_data[name_list[2]] = row["TLNO"]
        new_data[name_list[3]] = row["MNU"]

        food_list.append(new_data)

file_name = 'daegu_food_jonggu_list.csv'
with open(f'../output_02/{file_name}', 'w', newline='', encoding='UTF-8') as csvfile:
    writer = csv.DictWriter(csvfile, name_list)
    writer.writeheader()
    for data in food_list:
        data: dict
        writer.writerow(data)

print(f'{file_name} 파일이 생성되었습니다.')

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 자료 ]

 


 

1. 서버에서 데이터 받기

 

1) 아이디와 이름 순서대로 데이터를 전달
 

    🚀  test, tom  ➡️ 인덱스를 사용하는 것처럼 위치값으로 파악
    🚀  빈값이나, 값에 구분자가 들어가는 경우 어려움등의 문제로 사용 빈도 낮음

 


2) xml 방식

 

    🚀  <id>test</id>
          <name>tom</name>
           ➡️  마크업 방식, 속성값이 반복되어서 상대적으로 데이터의 크기가 커짐

 


3) json 방식

 

    🚀  'id': 'test',
           'name': 'tom'
            ➡️  객체 속성 표현 방식. 상대적으로 간결한 표현

 


 

2.  JSON 파일 입출력

 

 1) JSON 파일이란?

 

    👾  JavaScript Object Notation의 약자로 JavaScript의 객체 표현 방법이라는 뜻

    👾  데이터를 전달할 때 사람이 읽고 쓰기 쉽도록 텍스트 형식을 정해 놓은 개방형 데이터 표준 형식
    👾  많은 양의 데이터를 처리할 때는 속도가 느린 단점이 있으므로 경량의 데이터를 주고 받을 때 주로 사용
 


 2) JSON 데이터 형식


    👾  속성 attribute - 값 value 쌍으로 구성된 데이터들이 순서없이 모여 있는 구조
          ⚡️ 중괄호를 이용해서 전체 JSON 데이터를 묶어 주고 속성과 값 사이에 콜론(:)을 붙여 줌
          ⚡️ 속성과 값으로 구성된 각 데이터의 구분은 쉼표(,)를 이용
                ∴  즉, 파이썬의 딕셔너리와 같은 모습

 



3) JSON 파일 생성


    👾  JSON 데이터 처리를 위해서 json 모듈 제공
         ⚡️  json 모듈을 import 하면 리스트나 딕셔너리와 같은 파이썬 객체를 JSON 데이터로 변환하거나,
              JSON 데이터를 다시 파이썬 객체로 변환할 수 있음

    👾  JSON 인코딩 encoding : 파이썬 객체를 JSON 문자열로 변환하는 것
         ⚡️ 변환된 문자열을 파일에 기록하면 확장자가 json인 JSON 파일 (*.json)을 만들 수 있음
         ⚡️ json.dumps() 메소드를 이용해서 JSON 인코딩을 처리할 수 있음

# json 모듈 import
import json

dict_list = [
    {
        'name': 'james',
        'age': 20,
        'spec': [
            175.5,
            70.5
        ]
    },
    {
        'name': 'alice',
        'age': 21,
        'spec': [
            168.5,
            60.5
        ]
    }
]

# 인코딩 메소드를 이용해 json 문자열로 변환
json_string: str = json.dumps(dict_list)
print(json_string)
'''
실행결과)
[{"name": "james", "age": 20, "spec": [175.5, 70.5]}, 
 {"name": "alice", "age": 21, "spec": [168.5, 60.5]}]
'''

# output_02 디렉토리에 json 파일 생성
with open('../output_02/dict_list_01.json', 'w') as file:
    file.write(json_string)

print('dict_list_01.json 파일이 생성되었습니다.')

 


(1) indent 옵션

 

📌  JSON 데이터는 네트워크를 주고받는 데이터의 표준 형식
📌  파일의 크기를 줄이기 위해서 의도적으로 불필요한 공백 문자 white space가 제거된 상태로 만들어 지기 때문에 

      사람들이 직접 그 내용을 해석하기에는 불편

 

    ⚡️ 보기 좋은 형식으로 만들기 위해서 json.dump() 메소드에 indent 옵션을 추가 할 수 있음
           ➡️  indent 옵션을 추가하면 JSON 데이터에 들여쓰기와 줄 바꿈이 추가되면서 보기 좋은 형식으로 만들어짐

json_string = json.dumps(dict_list, indent=4)  # indent 옵션 사용

with open('../output_02/dict_list_02.json', 'w') as file:
    file.write(json_string)

print('dict_list_02.json 파일이 생성되었습니다.')

 

 

📁  indent = 4는 들여쓰기로 공백문자 4개로 처리 한다는 의미
📁  하지만 indent 옵션을 사용하면 파일의 크기가 커지기 때문에 네트워크 전송이 목적이라면 사용하지 않는 것이 좋음
📁 JSON 데이터는 문자열을 큰따옴표로 묶어서 처리

 

 

 

 

 

 

 

 


 

 4) JSON 파일 읽기


    👾  JSON 디코딩 decording : 인코딩된 JSON 데이터를 다시 파이썬 객체로 변경하는 것
    👾  디코딩을 처리하는 메소드는 json.loads()

with open('../output_02/dict_list_02.json', 'r') as file:
    json_reader = file.read()
    dict_list = json.loads(json_reader)
    print(dict_list)
    # [{'name': 'james', 'age': 20, 'spec': [175.5, 70.5]}, 
    # {'name': 'alice', 'age': 21, 'spec': [168.5, 60.5]}]
    print(type(dict_list))  # <class 'list'>

 

    📁  json 파일을 read() 메소드로 한 번에 전체를 읽어 들여 json_reader에 저장
    📁  json.loads(json_reader)를 통해서 디코딩이 이뤄지면 파이썬 객체인 dict_list가 생성
    📁  dict_list는 리스트 내부에 2개의 딕셔너리가 저장된 구조이기 때문에 for 문을 이용해서 그 내용을 모두 처리 가능

 


 

3. JSON과 API

🚀  JSON은 데이터를 사람이 읽을 수 있는 문자열(바이너리가 아니라 텍스트)로 나타내는 방식 
🚀  많은 웹 사이트에서 프로그램이 웹 사이트와 상호 작용하는 데 JSON 형식의 내용을 제공
        ➡️  이를 API 제공이라고 하고, API로 접근하는 것은 URL을 통해 일반 웹 페이지에 접근하는 것과 동일
        ➡️  차이점API가 반환하는 값은 기계를 위한 JSON 형식으로 되어 있음

🚀  원하는 데이터를 얻으려면 프로그램이 요청해야 할 URL 뿐만 아니라 반환되는 JSON 데이터 구조의 일반적인 형식에 대한 문서도 찾아 봐야 되는데, API를 제공하는 모든 사이트는 이 문서를 제공

 


 

1) JSON 모듈


👾  JSON 모듈은 json.loads(), json.dumps() 함수로 JSON 데이터와 파이썬 값을 서로 변환하는 모든 세부 사항을 처리
👾  JSON문자열, 정수, 부동 소수점 수, 불, 리스트(배열) '[]', 딕셔너리(객체) '{}', NoneType 자료형 값만 저장 가능

import json

 


 

2) loads() 함수를 사용하여 JSON 읽기


👾  JSON 데이터가 들어 있는 문자열을 파이썬 값으로 변환하려면, 이를 json.loads() 함수에 전달
👾  JSON 문자열은 큰 따옴표를 사용

string_json_data: str = '{"name": "Zopgie", "isCat": true, "miceCaught": 0, "felineIQ": null}'
json_data_as_python_value = json.loads(string_json_data)
print(type(json_data_as_python_value))  # <class 'dict'>
print(json_data_as_python_value)
# {'name': 'Zopgie', 'isCat': True, 'miceCaught': 0, 'felineIQ': None}

 

# 온라인에서 JSON 파일 열기
import urllib.request as request

# urlopen() 함수 사용하여 소스 가져옴
json_data = request.urlopen("https://jsonplaceholder.typicode.com/todos/1").read()
print(type(json_data))  # <class 'bytes'>

# loads() 함수로 파이썬 객체로 변환
python_data = json.loads(json_data)
print(type(python_data))  # <class 'dict'>
print(python_data)  
#{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}

   

    📌  urllib.request : 내부모듈(url 라이브러리). 기본적인 기능만 제공
    📌  requests : 외부모듈. 다양한 기능을 제공. 실작업에 많이 사용

 


 

3) dupms() 함수를 이용하여 JSON 작성하기


👾  파이썬 값을 JSON 형식 데이터 문자열로 변환

python_data: dict = {'name': 'Zopgie', 'isCat': True, 'miceCaught': 0, 'felineIQ': None}
json_data: str = json.dumps(python_data)
print(type(json_data))  # <class 'str'>
print(json_data)  
# {"name": "Zopgie", "isCat": true, "miceCaught": 0, "felineIQ": null}

 

    📌  JSON 에서는 True ▶️ true,  None ▶️ null 로 표현

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 자료 ]

+ Recent posts