본문 바로가기
코딩 연습/코딩배우기

juso.go.kr에서 파이썬으로 도로명주소 등 추출

by good4me 2022. 2. 2.

goodthings4me.tistory.com

juso 사이트의 검색란에 '고양시 아파트'처럼 키워드를 입력하여 우편주소, 도로명 주소, 도로명 영문주소, 지번 주소를 추출해보는 파이썬 크롤링 연습용 코드를 작성해봤다. 

 

 

파이썬으로 juso 사이트에서 주소 추출하기

juso.go.kr의 검색란에 검색 키워드(예로, 고양시 아파트)를 입력하고 검색하면 도로명주소와 지번주소, 영문과 국문 변환, 우편번호 등을 확인할 수 있다.

여기서 도로명주소와 지번주소, 영문 도로명주소, 우편번호 등을 파이썬으로 크롤링해볼 것이다.

 

일단, 주소(URL)를 살펴보면,

https://www.juso.go.kr/support/AddressMainSearch.do?currentPage=1&countPerPage=10&&searchType=HSTRY&searchKeyword=고양시 아파트&firstSort=none&ablYn=N&synnYn=Y

- 페이지 번호와 페이지당 개수, 그리고 검색 키워드가 보인다.

- 페이지당 개수는 놔두고, 페이지 번호를 변경하면서 주소를 추출하면 된다

 

도로명 주소

 

 

F12로 juso.go.kr의 html 소스를 보면,

juso.go.kr html

- 도로명 주소 등의 추출 데이터는 <ol> 태그 밑에 <li> 태그로 되어있다.

- 각 페이지 내 <li> 태그 전체를 가져와서 하나씩 가져오면 주소 데이터를 추출할 수 있다.

- 도로명 주소는 class="subject1", 지번주소는 class="subject2", 도로명 영문주소는 그 하위 class="addrEngInfo", 우편번호는 class="addrWrap" 밑에 class="zipcode"에서 찾을 수 있다.

 

 

파이썬 크롤링 소스 코드

import time, random, re
import requests
from bs4 import BeautifulSoup
import openpyxl


def apt_juso(keyword, juso_cnt):
    ## 추출한 주소 저장할 엑셀 생성
    workbook_name = 'juso_' + keyword + '.xlsx'
    wb = openpyxl.Workbook()
    ws = wb['Sheet']
    ws.title = '주소추출'
    wb.save(workbook_name)
    theme_list = ['No', '우편번호', '도로명 주소', '도로명 영문주소', '지번 주소']
    idx = 0
    for col in range(1, len(theme_list) + 1):
        ws.cell(1, col).value = theme_list[idx]
        idx += 1

    ## 주소 추출하기
    headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
    }

    ext_cnt = int(juso_cnt//10) + 1
    row = 2
    for page in range(1, ext_cnt + 1):
        url = f'https://www.juso.go.kr/support/AddressMainSearch.do?currentPage={page}&countPerPage=10&&searchType=\
        TOTAL&searchKeyword={keyword}&firstSort=none&ablYn=Y&synnYn=N'

        res = requests.get(url, headers=headers)
        soup = BeautifulSoup(res.text, 'html.parser')
        ol_lis = soup.select('#searchAddress > div.container.support_search_list > div.search_list > ol > li')
        
        for li in ol_lis:
            if juso_cnt == (row - 2):
                break
            try:
                roed_juso = li.find('div', class_='subejct_1').find('span', class_='roadNameText').text
                road = re.sub('&nbsp;|\t|\r|\n', '', roed_juso).strip().replace('  ', ' ')
                print(f'\n[{row-1}] 주소추출:\n{road}')
                
                road_eng = li.find('div', class_='addrEngInfo').find('span', class_='addrEng').text
                eng_roadname = re.sub('&nbsp;|\t|\r|\n', '', road_eng).strip().replace('  ', ' ')
                print(eng_roadname)                
                
                jibeon_juso = li.find('div', class_='subejct_2').find('span', class_='roadNameText').text
                jibeon = re.sub('&nbsp;|\t|\r|\n', '', jibeon_juso).strip().replace('  ', ' ')
                print(jibeon)
                
                zipcode = li.select_one('div.addrWrap > div.zipcode > div > strong').text
                print(zipcode)
                
                btn = li.find('button', class_='btn_dtaddr_on')

                ## 상세주소(동.층.호) 버튼이 있는 경우만 엑셀에 저장 
                if btn:
                    ws.cell(row, 1).value = row - 1
                    ws.cell(row, 2).value = zipcode
                    ws.cell(row, 3).value = road
                    ws.cell(row, 4).value = eng_roadname
                    ws.cell(row, 5).value = jibeon
                    wb.save(workbook_name)
                    row += 1
                else:
                    continue

            except Exception as e:
                print(f'\nError: {e}\n')
                err = f'Error: {keyword} - {e}\n'
                with open('error.txt', 'a') as f:
                    f.write(err)
                continue
        
        time.sleep(random.uniform(0.5, 1))

juso_keyword = '고양시 아파트'
juso_cnt = 4
apt_juso(juso_keyword, juso_cnt)

- 추출할 주소를 저장할 엑셀 파일을 생성하고, 엑셀 각 열의 제목을 세팅했다.

- URL의 페이지는 입력받은 juso_cnt를 정수 나눗셈(몫)을 구하고 +1을 해주고 for 문을 통해 각 페이지를 대입했고,

- URL의 검색 키워드는 입력받은 keyword를 사용했다.

 

good4me.co.kr

 

- juso.go.kr에서 아파트 주소 추출 시 상세주소(동ㆍ층ㆍ호) 보기 버튼이 있는 경우만 추출 대상으로 했다.

- 데이터 추출 중 오류 발생 시에도 멈추지 않고 그대로 추출토록 하고, 오류는 error.txt 파일에 저장되도록 했고,

- 추출 시 서버 영향을 줄이기 위해 time()과 random() 함수를 적용했다.

 

 

추출 결과

[1] 주소추출:
경기도 고양시 일산서구 경의로 867(덕이동, 철산아파트)
867, Gyeongui-ro, Ilsanseo-gu, Goyang-si, Gyeonggi-do 
경기도 고양시 일산서구 덕이동 277-10 철산아파트       
10233

[2] 주소추출:
경기도 고양시 일산서구 고양대로 631(일산동)
631, Goyang-daero, Ilsanseo-gu, Goyang-si, Gyeonggi-do
경기도 고양시 일산서구 일산동 955-2 동양아파트        
10351

[3] 주소추출:
경기도 고양시 일산서구 고양대로 633(일산동, 동양아파트)
633, Goyang-daero, Ilsanseo-gu, Goyang-si, Gyeonggi-do 
경기도 고양시 일산서구 일산동 955-2 동양아파트
10351

[4] 주소추출:
경기도 고양시 일산동구 고풍로 20(풍동, 에이스아파트)   
20, Gopung-ro, Ilsandong-gu, Goyang-si, Gyeonggi-do    
경기도 고양시 일산동구 풍동 385-1 에이스아파트
10308

# juso_cnt를 검색된 총건수인 453으로 할 경우, 고양시 아파트 주소 전체를 추출할 수 있음

 

엑셀 저장

 

 

juso.go.kr에서 "아파트" 검색 시 전체 30,809건인데,

아파트 검색어

이를 한 번에 추출하는 것보다는 juso_cnt를 5,000건씩 나누어서 숫자를 5000, 10000, 15000,...으로 변경하면서 추출하는 것이 좋은데, 주의할 점은 데이터를 저장한 파일명을 변경해줘야 한다는 것임

 

댓글