# 모듈 import
import requests
import pprint
#인증키 입력
encoding = '발급받은 인코딩 인증키를 복사하여 붙여넣기 해 주세요.'
decoding = '발급받은 디코딩 인증키를 복사하여 붙여넣기 해 주세요.'
#url 입력
url = 'http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19SidoInfStateJson'
params ={'serviceKey' : decoding , 'pageNo' : '1', 'numOfRows' : '10', 'startCreateDt' : '2020', 'endCreateDt' : '20211103' }
response = requests.get(url, params=params)
# xml 내용
content = response.text
# 깔끔한 출력 위한 코드
pp = pprint.PrettyPrinter(indent=4)
#print(pp.pprint(content))
### xml을 DataFrame으로 변환하기 ###
from os import name
import xml.etree.ElementTree as et
import pandas as pd
import bs4
from lxml import html
from urllib.parse import urlencode, quote_plus, unquote
## 각 컬럼 값 ## (포털 문서에서 꼭 확인하세요)
"""
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT: 등록일시분초
DEATH_CNT: 사망자 수
GUBUN: 시도명(한글)
GUBUN_CN: 시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수
"""
#bs4 사용하여 item 태그 분리
xml_obj = bs4.BeautifulSoup(content,'lxml-xml')
rows = xml_obj.findAll('item')
print(rows)
"""
# 컬럼 값 조회용
columns = rows[0].find_all()
print(columns)
"""
# 각 행의 컬럼, 이름, 값을 가지는 리스트 만들기
row_list = [] # 행값
name_list = [] # 열이름값
value_list = [] #데이터값
# xml 안의 데이터 수집
for i in range(0, len(rows)):
columns = rows[i].find_all()
#첫째 행 데이터 수집
for j in range(0,len(columns)):
if i ==0:
# 컬럼 이름 값 저장
name_list.append(columns[j].name)
# 컬럼의 각 데이터 값 저장
value_list.append(columns[j].text)
# 각 행의 value값 전체 저장
row_list.append(value_list)
# 데이터 리스트 값 초기화
value_list=[]
#xml값 DataFrame으로 만들기
corona_df = pd.DataFrame(row_list, columns=name_list)
print(corona_df.head(19))
#DataFrame CSV 파일로 저장
corona_df.to_csv('corona_kr.csv', encoding='utf-8-sig')
마이바티스의 가장 큰 장점은 매핑구문이다. 이건 간혹 마법을 부리는 것처럼 보일 수 있다. SQL Map XML 파일은 상대적으로 간단하다. 더군다나 동일한 기능의 JDBC 코드와 비교하면 아마도 95% 이상 코드수가 감소하기도 한다. 마이바티스는 SQL을 작성하는데 집중하도록 만들어졌다.
SQL Map XML파일은 첫번째(first class)엘리먼트만을 가진다.
cache- 해당 네임스페이스을 위한 캐시 설정
cache-ref- 다른 네임스페이스의 캐시 설정에 대한 참조
resultMap- 데이터베이스 결과데이터를 객체에 로드하는 방법을 정의하는 엘리먼트
parameterMap- 비권장됨! 예전에 파라미터를 매핑하기 위해 사용되었으나 현재는 사용하지 않음
4. InputSource is = new InputSource(new StringReader( 1.에서 받은 xml문자열 )); 로InputSource를 생성한다.
- XML파일에서 받는거면 InputSource is = new InputSource(new FileReader( File객체 ));로 생성한다.
5. Document doc = builder.parse(is); 로 XML을 파싱한다.
6. XPath xpath = XPathFactory.newInstance().newXPath(); 로 XPath 객체를 생성하고
7. XpathExpression expr = xpath.complie( 선택하는 문법 ); 으로 가져올 element를 선택한다.
8. 해당 노드(Element)에 접근해서 필요한 데이터를 추출한다.
대략적으로 위와 같은 과정으로 XML데이터 파싱이 이루어진다.
DocumentBuilderFactory로부터 builder를 만들어내고 InputSource에 XML을 넣어서 document를 만드는 것까지는 일반적이다.
여기서 XML을 파싱해서 새롭게 만들어진 DOM객체를 접근하는데에 XPath가 쓰인다.
중점적으로 봐야할 부분은 역시 XPath의 문법이다. XPath는 노드에 접근하는데에 표현식(XPathExpression)이 사용된다.
다른 블로그에서 Xpath 표현식 문법(?)에 대해 잘 정리한 곳이 많으므로 여기서는 자주 쓰이고 중요한 부분만 정리한다.
XPathExpression
표현식까지 익혀야 한다고 번거로운 라이브러리라고 판단할 수도 있겠지만 한 번 익혀두거나 나중에 찾아보면서 사용해도 훌륭한 것 같은 라이브러리니 간단하게 배운다.
item : <item>요소를 모두 선택함
/item : "/" 루트 노드의 자식 노드중에서 <item>엘리먼트를 선택함 (앞에 "/"가 들어가면 절대 경로)
item/jeongpro : <item>엘리먼트의 자식 노드중에서 <jeongpro>엘리먼트를 선택 (상대 경로)
// : 현재 노드의 위치와 상관없이 지정된 노드부터 탐색
//item : 위치와 상관없이 엘리먼트 이름이 <item>인 모든 엘리먼트
item/@id : 모든 <item>엘리먼트의 id속성 노드를 모두 선택함
item[k] : <item>엘리먼트 중에서 k번 째 <item>엘리먼트
item[@attr = val] : attr이라는 속성이 val값을 가지는 모든 <item>엘리먼트
이런 표현식들이 있으니 잘 사용하면된다. 위의 예제에서는 //items/item 이라는 표현식을 적었으므로 "위치와 상관없이 <items>라는 노드들 중에서 자식 노드가 <item>인 노드(element)들을 NodeList로 받았다.
결과적으로 파싱을 마친 후 노드에서 원하는 데이터를 정확하게 추출하는 것이 중요하다.
node.getNodeName() 으로 "element 이름"을 받았고
node.getTextContent() 로 "값"을 받았다. (* 참고로 getNodeValue()가 있는데 혼란을 겪지 않길 바란다.)