빅데이터 | 머신러닝 | 딥러닝/빅데이터 분석

[pandas] 공공 데이터 XML 크롤링을 통해 dataFrame으로 만들어보기

냠냠:) 2020. 9. 4. 04:27

공공 API를 통해 얻는 XML 형태의 파일은 여러 가지 방법으로 크롤링할 수 있다.

 

이 글에서 알려드릴 내용은 XML로 이루어진 페이지를 xmltodict 라이브러리를 이용해 API를 파싱 하는 방법에 대해 다루려고 한다.

 

공공 데이터 API을 발급받는 과정은 생략하고, url과 key값, 원하는 데이터 범위를 설정하는 방식으로 파싱 하는 방법이다.

 

hi
In [1]:
!pip install xmltodict

import pandas as pd
import requests
import xmltodict
import time
Collecting xmltodict
  Downloading https://files.pythonhosted.org/packages/28/fd/30d5c1d3ac29ce229f6bdc40bbc20b28f716e8b363140c26eff19122d8a5/xmltodict-0.12.0-py2.py3-none-any.whl
Installing collected packages: xmltodict
Successfully installed xmltodict-0.12.0
In [3]:
key = "여러분 key값"
start = "1"
end = "10"
url = "http://210.99.248.79/rest/GoodPriceStoreService/getGoodPriceStoreList?authApiKey="+key+"&startPage="+start+"&pageSize="+end

headers = {'User-Agent' : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"}
req = requests.get(url, headers= headers).content
xmlObject = xmltodict.parse(req)
allData = xmlObject['rfcOpenApi']['body']['data']['list']
In [4]:
print(allData)                # xml 전체 데이터
print(allData[0])             # rfcOpenApi -> body -> data -> list 부분 중 0번째 데이터
print(len(allData))           # list 개수
print(allData[0].items())     # key : value를 key, value로 반환하는 함수
[OrderedDict([('address', '만덕로 36 (건입동)'), ('category', '한식'), ('goods_price', '대패 삼겹살(200g) 6,000원'), ('location', '건입동'), ('name', '인풍감자탕'), ('num', '107'), ('telephone', '758-8414')]), OrderedDict([('address', '임항로 261, 나동 101호(건입동, 신천지빌라)'), ('category', '이미용업'), ('goods_price', '커트(성인) 8,000원, 커트(경로) 6,000원,파마(성인) 25,000원, 파마(경로) 20,000원'), ('location', '건입동'), ('name', '전원미용실'), ('num', '108'), ('telephone', '751-5682')]), OrderedDict([('address', '임항로 68(건입동)'), ('category', '한식'), ('goods_price', '몸국 6,000원, 자리물회 10,000원, 고등어구이 10,000원'), ('location', '건입동'), ('name', '김만덕객주'), ('num', '109'), ('telephone', '727-8800')]), OrderedDict([('address', '월광로 162 (노형동)'), ('category', '한식'), ('goods_price', '생오겹살(200g) 12,000원, 생오리백숙(한마리) 50,000원'), ('location', '노형동'), ('name', '길벗식당'), ('num', '110'), ('telephone', '748-0848')]), OrderedDict([('address', '달마루길 22(노형동)'), ('category', '한식'), ('goods_price', '도새기샤브샤브(1인분) 9,000원'), ('location', '노형동'), ('name', '도새기샤브마을'), ('num', '111'), ('telephone', '772-8000')]), OrderedDict([('address', '진군3길 27-27(노형동)'), ('category', '한식'), ('goods_price', '김치찌개 5,000원, 된장찌개 5,000원, 순두부 5,000원'), ('location', '노형동'), ('name', '떡뽁기대학 라면학과'), ('num', '112'), ('telephone', '749-1800')]), OrderedDict([('address', '다랑곶4길 18(노형동)'), ('category', '이미용업'), ('goods_price', '커트 8,000원(샴푸시 10,000원)'), ('location', '노형동'), ('name', '라영미용실'), ('num', '113'), ('telephone', '744-3340')]), OrderedDict([('address', '월랑로 56-1(노형동)'), ('category', '한식'), ('goods_price', '매운탕 5,000원, 돔지리 5,000원'), ('location', '노형동'), ('name', '승범이네집'), ('num', '114'), ('telephone', '744-3538')]), OrderedDict([('address', '진군3길 28(노형동)'), ('category', '한식'), ('goods_price', '김치찌개백반 4,000원, 된장찌개백반 4,000원, 비빔밥 4,000원'), ('location', '노형동'), ('name', '시니어손맛집'), ('num', '115'), ('telephone', '711-3999')]), OrderedDict([('address', '진군4길 30(노형동)'), ('category', '한식'), ('goods_price', '김치찌개 3,500원, 참치찌개 4,000원, 순두부 3,500원'), ('location', '노형동'), ('name', '천하대장군'), ('num', '116'), ('telephone', '711-2999')])]
OrderedDict([('address', '만덕로 36 (건입동)'), ('category', '한식'), ('goods_price', '대패 삼겹살(200g) 6,000원'), ('location', '건입동'), ('name', '인풍감자탕'), ('num', '107'), ('telephone', '758-8414')])
10
odict_items([('address', '만덕로 36 (건입동)'), ('category', '한식'), ('goods_price', '대패 삼겹살(200g) 6,000원'), ('location', '건입동'), ('name', '인풍감자탕'), ('num', '107'), ('telephone', '758-8414')])
In [5]:
df_cols =[]

for key, val in allData[0].items():       # 컬럼 구하기
  df_cols.append(key)                     # 첫 번째 데이터에서 컬럼 부분만 가져옴

print(df_cols)                            # 컬럼 

                           
df_rows = {}                              #하나의 열이 될 딕셔너리
out_df = pd.DataFrame(columns=df_cols)    #데이터 프레임. 컬럼만 먼저 설정

for i in range(len(allData)):             #전체 list 개수만큼
  for key, val in allData[i].items():     #해당 인덱스 list에서 key, val을 가져옴
    df_rows[key] = val                    #df_rows 는 key, val으로 이루어짐. 딕셔너리 형태
  
  print(df_rows)                          #하나의 list의 데이터들
  out_df = out_df.append(df_rows, ignore_index=True)        #한 row씩 df에 추가 

out_df
['address', 'category', 'goods_price', 'location', 'name', 'num', 'telephone']
{'address': '만덕로 36 (건입동)', 'category': '한식', 'goods_price': '대패 삼겹살(200g) 6,000원', 'location': '건입동', 'name': '인풍감자탕', 'num': '107', 'telephone': '758-8414'}
{'address': '임항로 261, 나동 101호(건입동, 신천지빌라)', 'category': '이미용업', 'goods_price': '커트(성인) 8,000원, 커트(경로) 6,000원,파마(성인) 25,000원, 파마(경로) 20,000원', 'location': '건입동', 'name': '전원미용실', 'num': '108', 'telephone': '751-5682'}
{'address': '임항로 68(건입동)', 'category': '한식', 'goods_price': '몸국 6,000원, 자리물회 10,000원, 고등어구이 10,000원', 'location': '건입동', 'name': '김만덕객주', 'num': '109', 'telephone': '727-8800'}
{'address': '월광로 162 (노형동)', 'category': '한식', 'goods_price': '생오겹살(200g) 12,000원, 생오리백숙(한마리) 50,000원', 'location': '노형동', 'name': '길벗식당', 'num': '110', 'telephone': '748-0848'}
{'address': '달마루길 22(노형동)', 'category': '한식', 'goods_price': '도새기샤브샤브(1인분) 9,000원', 'location': '노형동', 'name': '도새기샤브마을', 'num': '111', 'telephone': '772-8000'}
{'address': '진군3길 27-27(노형동)', 'category': '한식', 'goods_price': '김치찌개 5,000원, 된장찌개 5,000원, 순두부 5,000원', 'location': '노형동', 'name': '떡뽁기대학 라면학과', 'num': '112', 'telephone': '749-1800'}
{'address': '다랑곶4길 18(노형동)', 'category': '이미용업', 'goods_price': '커트 8,000원(샴푸시 10,000원)', 'location': '노형동', 'name': '라영미용실', 'num': '113', 'telephone': '744-3340'}
{'address': '월랑로 56-1(노형동)', 'category': '한식', 'goods_price': '매운탕 5,000원, 돔지리 5,000원', 'location': '노형동', 'name': '승범이네집', 'num': '114', 'telephone': '744-3538'}
{'address': '진군3길 28(노형동)', 'category': '한식', 'goods_price': '김치찌개백반 4,000원, 된장찌개백반 4,000원, 비빔밥 4,000원', 'location': '노형동', 'name': '시니어손맛집', 'num': '115', 'telephone': '711-3999'}
{'address': '진군4길 30(노형동)', 'category': '한식', 'goods_price': '김치찌개 3,500원, 참치찌개 4,000원, 순두부 3,500원', 'location': '노형동', 'name': '천하대장군', 'num': '116', 'telephone': '711-2999'}
Out[5]:
address category goods_price location name num telephone
0 만덕로 36 (건입동) 한식 대패 삼겹살(200g) 6,000원 건입동 인풍감자탕 107 758-8414
1 임항로 261, 나동 101호(건입동, 신천지빌라) 이미용업 커트(성인) 8,000원, 커트(경로) 6,000원,파마(성인) 25,000원, 파... 건입동 전원미용실 108 751-5682
2 임항로 68(건입동) 한식 몸국 6,000원, 자리물회 10,000원, 고등어구이 10,000원 건입동 김만덕객주 109 727-8800
3 월광로 162 (노형동) 한식 생오겹살(200g) 12,000원, 생오리백숙(한마리) 50,000원 노형동 길벗식당 110 748-0848
4 달마루길 22(노형동) 한식 도새기샤브샤브(1인분) 9,000원 노형동 도새기샤브마을 111 772-8000
5 진군3길 27-27(노형동) 한식 김치찌개 5,000원, 된장찌개 5,000원, 순두부 5,000원 노형동 떡뽁기대학 라면학과 112 749-1800
6 다랑곶4길 18(노형동) 이미용업 커트 8,000원(샴푸시 10,000원) 노형동 라영미용실 113 744-3340
7 월랑로 56-1(노형동) 한식 매운탕 5,000원, 돔지리 5,000원 노형동 승범이네집 114 744-3538
8 진군3길 28(노형동) 한식 김치찌개백반 4,000원, 된장찌개백반 4,000원, 비빔밥 4,000원 노형동 시니어손맛집 115 711-3999
9 진군4길 30(노형동) 한식 김치찌개 3,500원, 참치찌개 4,000원, 순두부 3,500원 노형동 천하대장군 116 711-2999

 

해당 기능은 colab을 이용했다.

반응형