juso.go.kr 도로명 주소, 엑셀로 분리하는 방법을 파이썬으로 해보기
juso.go.kr의 도로명 주소를 보면, 형태가 4가지로 나오는데 '건물번호'까지만 있는 것과 괄호 안에 동명칭, 건물 명칭이 있는 것, 그리고 괄호 안에 동명칭만 있거나 동명칭은 없고 건물 명칭만 있는 것 등이다. 도로명 주소를 엑셀을 이용해 주소를 구분(분리)하는 방법도 있지만, 파이썬의 openpyxl 라이브러리 사용하여 빠르게 분리하는 방법도 있다.
파이썬으로 도로명 주소 분리해보기
먼저, 괄호 안에 동명칭이나 건물 명칭이 있는 것은 엑셀로 쉽게 분리할 수 있으니 그 부분은 분리했다고 하고, 건물번호까지 각각을 분리하는 방법을 코드로 구현해보았다.
☞ "강원도 속초시 미시령로3359번길 9(교동, 현대아파트)"에서 (교동, 현대아파트) 부분은 괄호 부분을 find() 함수로 찾아서 mid() 등의 함수로 간단하게 분리 가능함
위 이미지를 보면, 도로명 주소에 대해 엑셀 함수(=LEN(H2)-LEN(SUBSTITUTE(H2," ",""))+1)를 이용해서 공백 기준으로 분리 시 세부 주소 항목의 개수를 구할 수 있다.
구분되는 항목은 "광역시/도, 시군구, 일반구(자치구가 아닌 구), 읍/면, 도로명칭, 건물번호" 등 최소 3개인 "세종특별자치시"에서 최대 6개인 "경상북도 포항시"로 구분이 된다.
이 부분에 대해 아래와 같은 파이썬 소스코드로 빠르게 분리할 수 있다.
도로명 주소 분리 파이썬 소스코드
import openpyxl
## 엑셀 파일 읽기 - 워크북, 워크시트
wb = openpyxl.load_workbook('apt_juso.xlsx')
ws = wb['Sheet1'] # rwb.active
maxRow = ws.max_row # 최대 row
print(maxRow)
wb2 = openpyxl.Workbook()
ws2 = wb2['Sheet']
ws2.cell(1, 1).value = '광역시/도'
ws2.cell(1, 2).value = '시/군/구'
ws2.cell(1, 3).value = '일반구(자치구X)'
ws2.cell(1, 4).value = '동/읍/면'
ws2.cell(1, 5).value = '길/로'
ws2.cell(1, 6).value = '건물번호'
wb2.save('result.xlsx')
## 엑셀 셀값 읽어와서 순환시키기
row = 2
for r in range(2, maxRow + 1):
juso = ws.cell(r, 1).value # 셀 읽어오기
# print(f'\nrow {r} - {juso}')
juso_lst = juso.split(' ')
# print(juso_lst)
print(juso_lst)
# print(juso_lst[-1])
## 엑셀에 추출 데이터 저장하기
ws2.cell(row, 1).value = juso_lst[0]
# 2번째는 시/군/구
if juso_lst[1][-1] in ('시', '군', '구'):
ws2.cell(row, 2).value = juso_lst[1]
# 3번째가 구, 일반구(자치구 아닌 구)에 대해 처리
if juso_lst[2][-1] == '구':
ws2.cell(row, 3).value = juso_lst[2]
## 주소를 공백으로 split 시 리스트 요소는 3~6개, index 벗어날 경우 에러나기 때문에 조건 분기
if len(juso_lst) == 3:
# 세종특별자치시 길/로 처리
if juso_lst[1][-1] in ('길', '로'):
ws2.cell(row, 5).value = juso_lst[1]
if len(juso_lst) == 4:
# 세종특별자치시 읍/면 처리
if juso_lst[1][-1] in ('읍', '면'):
ws2.cell(row, 4).value = juso_lst[1]
# 3번째에 길/로 있는 경우
if juso_lst[2][-1] in ('길', '로'):
ws2.cell(row, 5).value = juso_lst[2]
if len(juso_lst) == 5:
# 3번째가 읍/면
if juso_lst[2][-1] in ('읍', '면'):
ws2.cell(row, 4).value = juso_lst[2]
# 4번째가 길/로
if juso_lst[3][-1] in ('길', '로'):
ws2.cell(row, 5).value = juso_lst[3]
if len(juso_lst) == 6:
# 4번째가 읍/면
if juso_lst[3][-1] in ('읍', '면'):
ws2.cell(row, 4).value = juso_lst[3]
# 5번째에 길/로 있는 경우,
if juso_lst[4][-1] in ('길', '로'):
ws2.cell(row, 5).value = juso_lst[4]
# 마지막 건물번호 처리
ws2.cell(row, 6).value = juso_lst[-1]
row += 1
# if r == 1000:
# break
wb2.save('result.xlsx')
wb.close()
wb2.close()
- 처음의 openpyxl.load_workbook()은 상기 이미지(도로명주소)의 주소 데이터를 불러오는 부분이고,
- 두 번째 openpyxl.Workbook() 부분은 주소를 분리한 결과를 저장하기 위해 엑셀 파일을 생성하는 코드다.
- 불러온 주소를 for 문으로 순환하면서 하나씩 주소를 분리할 때, split()으로 '주소 리스트'를 만들고,
- 도로명 주소에서 세부 주소 항목을 구분하기 위해서 해당 주소 항목의 마지막 문자를 기준으로 체크한 후,
- 분리된 주소 리스트에서 index 0은 광역시/도, 1은 시/군/구, 2는 일반구로 구분하여 엑셀에 저장을 한다.
- 그다음으로 각 리스트의 세부 주소 항목에 대해 index 수가 벗어나지 않도록 주소 리스트의 요소 수를 기준으로 조건 분기를 하여 처리했다. (리스트의 index 범위를 벗어나면 에러남)
- 그리고 마지막의 건물번호는 각 주소 리스트의 끝에 있기 때문에 리스트 슬라이스([-1])로 처리했다.
추출 결과
juso.go.kr에서 아파트로 검색하여 받은 도로명 주소 2만 여개에 대해 이 코드를 사용하면, 십몇 초 내에 세부 주소로 분리할 수 있다.