먼저 코드에 들어가기에 앞서 파서와 파싱에 대해 설명하겠습니다.
파서(Parser) & 파싱(Parsing)
파서(parser)란 주어진 문서나 데이터를 읽고 해석하는 프로그램 또는 모듈을 가리킵니다.
XML 파서는 주로 XML 형식으로 작성된 문서를 읽고 그 구조를 이해하며, 문서를 분석하여 데이터를 추출하는 데 사용됩니다.
XML 문서는 일반적으로 텍스트 기반의 구조를 가지고 있으며,
이를 파싱(parsing)한다는 것은 이러한 텍스트 기반의 문서를 읽고, 데이터를 해석하고 구조화하는 과정을 의미합니다. 파싱을 통해 XML 파서가 XML 문서를 읽고 그 구조를 이해하여 데이터를 추출하고 사용할 수 있습니다.
XML 파서는 XML 문서를 읽어와서 그 내부의 태그, 속성, 텍스트 등을 인식하고 이를 내부적인 데이터 구조로 변환합니다. 이러한 내부 구조화된 데이터를 프로그램에서 쉽게 조작하고 접근할 수 있게 해주기에, 이를 통해 프로그램은 XML 문서의 정보를 분석하고 원하는 정보를 추출하여 활용할 수 있습니다. XML 파서는 파이썬에서는 xml.etree.ElementTree와 같은 모듈로 제공되며, 이를 이용하여 XML 문서를 파싱할 수 있습니다.
로컬 파일의 XML 데이터 읽기 코드
# 웹 문서 읽기 : XML
import xml.etree.ElementTree as etree
''' 방법1. open() 함수로 파일을 직접 열고 읽기
xmlf=open("../testdata_utf8/my.xml",mode="r",encoding="utf-8").read()
print(xmlf,type(xmlf)) #<class str>
root=etree.fromstring(xmlf)
print(root,type(root)) #<class 'xml.etree.ElementTree.Element'>
print(root.tag,' ',len(root))
print()
'''
# 방법2.etree.parse() 함수로 파일을 바로 파싱
xmlfile=etree.parse("../testdata_utf8/my.xml") # 로컬의 XML 파일 불러오기
print(xmlfile,type(xmlfile)) #<class 'xml.etree.ElementTree.ElementTree'> ->노드가 생김-부모자식 형성
root=xmlfile.getroot() #getroot() 메서드로 XML 파일의 루트 요소를 가져오기
print(root.tag)
print(root[0][0].tag) #루트의 첫번째 자식의 첫번쨰 자식을 나타냄, 해당요소의 태그 이름 출력
print(root[0][1].tag)
print(root[0][0].attrib) #{'id': 'ks1'} -> dict 형식으로 잡힌다.
print(root[0][0].attrib.keys())
print(root[0][0].attrib.values())
print()
myname=root.find('item').find('name').text #find() 메서드를 사용하여 특정 태그를 가진 요소를 찾고, 해당 요소의 내용을 추출합니다.
print(myname)
print()
#XML 요소 반복 접근
for child in root:
print(child.tag)
for child2 in child:
print(child2.tag,child2.attrib)
print()
#XML 요소 검색 및 정보 추출 (findall 사용)
children=root.findall('item')
print(children)
for it in children:
re_id=it.find('name').get('id')
re_name=it.find('name').text
re_tel=it.find('tel').text
print(re_id,re_name,re_tel)
웹의 XML 데이터 읽기 코드
# https://www.kma.go.kr/XML/weather/sfc_web_map.xml #기상청이 실시간으로 데이터를 갱신해줌
# 기상청 제공 국내 주요 지역 날씨 정보 xml 문서 읽기
import urllib.request
import xml.etree.ElementTree as etree
# 웹 문서를 읽어, 파일로 저장 후 XML 문서 처리
try:
webdata =urllib.request.urlopen("https://www.kma.go.kr/XML/weather/sfc_web_map.xml")
print(webdata) #<http.client.HTTPResponse object at 0x0000025BF6E5B040>-> 객체로 나옴->읽어주어야 한다.
webxml = webdata.read() #데이터 인코딩
webxml = webxml.decode('utf-8') #데이터 디코딩
# print(webxml)
webdata.close() #할일 마치고 자원 반납
with open('pandas6.xml',mode='w',encoding='utf-8') as obj:
obj.write(webxml)
print("success")
except Exception as e:
print('err : ',e)
xmlfile=etree.parse('pandas6.xml')
print(xmlfile) #ElementTree object
root=xmlfile.getroot()
print(root.tag)
print(root[0].tag) #weather
children = root.findall('{current}weather')
print(children) #Element 객체가 잡힘
for it in children:
y=it.get('year') # 속성값 읽기
m=it.get('month')
d=it.get('day')
h=it.get('hour')
print()
print(y+"년 "+m+"월 "+d+"일 " +h+"시 현재 날씨 정보")
datas=[] #데이터를 담아둘 그릇 만들기
for child in root:
# print(child.tag) # {current}weather
for it in child:
# print(it.tag) # {current}local
localName=it.text # 지역명
re_ta=it.get("ta") #속성 값 얻기
re_desc=it.get("desc")
# print(localName,re_ta,re_desc)
datas += [[localName,re_ta,re_desc]] #list에는 += 을 할수 있다
# print(datas) ['동두천', '18.8', '맑음'], ['파주', '18.2', '흐림'], ['대관령', '16.6', '맑음'], ['춘천', '19.7', '맑음'] ...
import pandas as pd
import numpy as np
df=pd.DataFrame(datas,columns=['지역','온도','상태'])
print(df.head(3))
print(df.tail(3))
imsi=np.array(df.온도)
imsi=list(map(float,imsi))
# print(imsi) #['20.7' '19.8' '18.7'
print('평균온도 : ',round(np.mean(imsi),2))
코드 리뷰
webdata = urllib.request.urlopen("https://www.kma.go.kr/XML/weather/sfc_web_map.xml"): urllib 라이브러리를 사용하여 기상청의 XML 데이터가 포함된 URL 에서 데이터를 가져와 webdata 변수에 할당
webxml = webxml.decode('utf-8'): 읽어온 데이터를 UTF-8 형식으로 디코딩-> 문서가 한글로 되어있기에 한글이 깨질수 있음을 사전에 방지하고자 함입니다.
with open('pandas6.xml', mode='w', encoding='utf-8') as obj:
'pandas6.xml'이라는 파일을 쓰기 모드로 엽니다. 여기에 URL에서 받아온 XML 데이터를 기록할 것입니다.
obj.write(webxml): 디코딩한 데이터를 'pandas6.xml' 파일에 씁니다.
xmlfile = etree.parse('pandas6.xml'): 'pandas6.xml' 파일을 열어 XML 데이터를 파싱(일련의 데이터를 해석하고 구조화하는 과정을 말합니다. XML 파서가 XML 문서를 읽고 그 구조를 이해하여 데이터를 추출하고 사용할 수 있도록 해주는 과정입니다. )하고, 이를 xmlfile 변수에 할당합니다.
children = root.findall('{current}weather'): root 요소에서 {current}weather 태그의 모든 하위 요소를 찾아 children 변수에 할당합니다.
localName = it.text, re_ta = it.get("ta"), re_desc = it.get("desc"): 각 하위 요소에서 'text', 'ta', 'desc' 속성의 값을 가져옵니다.
참고개념 : 인코딩과 디코딩
인코딩
특정 문자 집합을 컴퓨터가 이해할 수 있는 이진 데이터 형태로 변환하는 과정.
예를 들어, 사람이 읽을 수 있는 텍스트(예: 한글, 영어)를 컴퓨터가 이해할 수 있는 이진 데이터(0과 1로 이루어진 데이터)로 변환하는 과정을 말합니다.
디코딩
인코딩과 반대로, 이진 데이터를 사람이 읽을 수 있는 텍스트로 변환하는 과정.
컴퓨터가 이해할 수 있는 이진 데이터를 다시 사람이 읽을 수 있는 문자로 변환합니다. 위의 코드 중 설명한 파이썬에서 webxml.decode('utf-8') 코드는 웹에서 가져온 데이터가 바이트(byte) 형태로 되어 있고, 이를 UTF-8 형식의 문자열로 변환하는 것입니다. UTF-8은 텍스트 데이터를 처리하기 위한 인코딩 방식 중 하나이며, 한글을 비롯한 다양한 언어의 문자를 표현할 수 있습니다.
즉, 인코딩과 디코딩은 데이터를 컴퓨터에서 다룰 수 있는 형태로 변환하는 방법입니다.