-
네이버 부동산 아파트 세대별 면적 추출하는 방법(selenium 활용)코딩 연습 2023. 2. 9. 07:55
네이버 부동산 아파트 정보를 통해 단지 내 동별 세대별 호수를 찾는 방법이 있는지 알아봤는데, 공공데이터 포털과 달리 좋은 정보가 많았고, 인테리어나 창호 샷시 등의 홍보용 DM을 보낼 때 상당히 유용할 것 같다.
네이버 부동산 아파트 세대 호수와 면적 정보 추출해보기
1. 네이버 부동산 URL 분석하기
네이버 부동산 URL(https://land.naver.com)에서 검색 부분에 아파트명(예로, 현대)을 입력하면,
- i) 찾는 아파트 리스트 웹 페이지로 이동하거나
- ii) 해당 아파트 정보 웹 페이지로 바로 이동을 하게 된다.
네이버 부동산 검색 결과 i)의 경우, 웹 페이지 URL은
https://new.land.naver.com/search?ms=37.48224,126.757,17&a=APT:ABYG:JGC&e=RETAIL
처럼 검색 결과로 파라미터가 몇 개 붙는 URL로 이동되고, 그 리스트를 살펴보면 "현대"가 들어간 유사한 명칭이 있는 아파트명과 주소, 아파트 총 세대수, 총 동수, 사용승인월(준공연월), 면적 정보(이하 "기본정보"라 함) 등을 볼 수 있다. 아마도, 아파트 문자를 뺀 나머지 단어("현대")로 유사 검색을 하여 결과를 표시해주는 것으로 보인다.만일, 아파트 명칭이 유일한 경우(예로, "송내자이")
https://new.land.naver.com/complexes/26987?ms=37.48224,126.757,17&a=APT:ABYG:JGC&e=RETAIL
처럼 아파트 기본정보 웹 페이지(본 포스팅의 세번째 이미지 참조) 바로 이동하게 되어있다.※ 참고) URL 파라미터 의미 추측
URL의 파라미터를 유심히 살펴보면 ms=좌표값, a=APT:ABYG:JGC, e=RETAIL 등이 보이고, 그 아래 부분을 보면 "아파트", "아파트분양권", "재건축" 버튼이 체크되어 있는 것을 알 수 있다.
아마도, APT:ABYG:JGC 부분이 각각을 의미하는 파라미터 값들인 것 같다.
(체크를 해제하면 APT:ABYG:JGC 부분에 영향을 줌)"아파트", "아파트분양권", "재건축" 첫번째 이미지의 웹 페이지 좌측 "검색결과"에서, 찾고자 하는 아파트명과 주소 부분(예로, 현대
서울시 구로구 개봉동 ~ )을 클릭하면 페이지가 전환되고 아래처럼 아파트의 기본정보와 최근 매매 실거래가와 매매가, 전세가 등이 보인다.네이버 부동산 아파트 정보 이 포스팅의 목적은 아파트 동별 세대 호수와 면적을 구하는 것이니 위 이미지에서 "단지정보"를 클릭한다. 그러면 아래 이미지처럼 단지정보부터 시세/실거래가, 동호수/공시가격, 학군정보, 사진 등의 탭이 보이는데, 동별 정보(이름)과 해당 동의 세대(호수)와 면적 정보를 보려면 "동호수/공시가격"을 클릭한다.
네이버 부동산 동호수/공시가격 위 이미지의 동별 세대별 호수와 면적 정보를 추출하기 위해 개발자도구(F12)를 펼쳐본다. 아래 이미지는 추출할 위치만을 잘라서 게재한 이미지이며, 그 아래 코드를 보면 추출할 각 요소를 확인할 수 있다.
네이버 부동산 개발자도구 2. 네이버 부동산 아파트 세대 추출 파이썬 코드
import time from bs4 import BeautifulSoup from selenium.webdriver.common.by import By import mychrome_driver as chromedriver def ext_apt_ho(aptnum): driver = chromedriver.chrome_driver() url = f'https://new.land.naver.com/complexes/{aptnum}' driver.get(url) driver.implicitly_wait(5) time.sleep(1) # 아파트 버튼 옆 건물명칭 bld_title = driver.find_element(By.ID, 'complexTitle').text.strip() # 좌측 단지정보 버튼 클릭 driver.find_elements(By.CLASS_NAME, 'complex_link')[0].click() time.sleep(0.5) # 세대별 평형정보 추출하는 부분 ## dongs = driver.find_element(By.CLASS_NAME, 'detail_contents_inner').find_elements(By.CLASS_NAME, 'tab_item') for dong in dongs: # print(dong.text[:3]) if dong.text.strip()[:3] == '동호수': dong.click() time.sleep(0.5) # 동 이름이 많은 경우 꺽쇠가 있음. 꺽쇠를 찾아 클릭하는 코드이며 class="btn_moretab_inner" 없는 경우를 대비하여 예외 처리함 try: btn_moretab = driver.find_element(By.CSS_SELECTOR, '#detailContents4 > div.detail_sorting_tabs > div > div.btn_moretab_box > button > span > i') time.sleep(0.5) btn_moretab.click() except: pass time.sleep(0.5) # 동 이름 클릭 dongs_a = driver.find_elements(By.CSS_SELECTOR, '#detailContents4 > div > div > div.detail_sorting_tablist > span > a') for dong in dongs_a: try: dong.click() # 동 이름 클릭 시 하단 '아파트 세대' 변경시킴 except: driver.execute_script('arguments[0].click();', dong) time.sleep(0.5) # 개발자도구에서 동이름 클릭하면 나오는 호수 부분의 class 속성인 detail_tabpanel_inner 클릭 page_src = driver.find_element(By.CLASS_NAME, 'detail_tabpanel_inner') page_src.click() time.sleep(0.5) # page_src html 소스코드를 변수에 저장 # 해당 소스코드 대상으로 bs4와 requests 사용하여 세대별 면적 추출함 html_src = page_src.get_attribute('innerHTML') # print(html_src) soup = BeautifulSoup(html_src, 'html.parser') house_floors = soup.select('div.detail_box--housenumber div.table_inner div.house_floor') # 층 print(f'\n{bld_title} 아파트 {dong.text} (전체 층수: {len(house_floors)})') for floor in house_floors: # 층별로 구분하고 있음. # 해당 동의 라인별 같은 층의 호(세대)를 span으로 분리하고 그 하위에 input과 div로 호와 면적을 구분하고 있음 ho_spans = floor.find_all('span') for span in ho_spans: # 빈 span <span class="house_number is-blank"></span> 으로 인해 TypeError: 'NoneType' 발생 예외 처리 try: ho = span.find('input')['value'] # 호 추출 py = span.find('div', class_='tooltip_wrap').text.split(' ')[1].strip().replace('㎡','') #공급 106.51㎡ 형태에서 ㎡ 제거 print(f'{ho}호 {py}') except: continue # break driver.quit() if __name__ == '__main__': apt_no = 45 ext_apt_ho(apt_no)
- 본 소스 코드는 위 네이버 부동산의 URL중 ~ complexes/26987 ~ 부분에서 숫자로 된 값을 apt_no로 함수에 전달하면 실행이 된다.
- 위 소스코드 import 부분에서 import mychrome_driver as chromedriver 모듈에 대한 것은 "파이썬 크롬드라이버 자동설치 (chromedriver_autoinstaller)" 포스팅의 "크롬 드라이버 자동 다운로드 코드" 부분의 내용을 참고한다.
- 셀레니움 크롤링 특성상 브라우저 내 실행하는 interval을 설정해야 에러가 안 나기 때문에 time을 주어야 한다.
- 동 이름이 많아서 꺽쇠를 클릭해야 하는 경우가 있고, 해당 css 속성값이 없는 경우가 있어서 예외 처리도 필요한다.
- 동 이름을 클릭했을 때 반응이 느리거나 가끔 반응이 없어서 에러가 나는 경우도 있다. 이를 해결하기 위해서 자바스크립트를 실행하는 코드도 삽입했다.
- 그리고, 소스코드 중에서 각 세대별 호수와 면적을 추출하는 부분을 서버에 무리를 주지 않고, 보다 용이하게 크롤링하도록 html 코드(아래 이미지 참조)를 변수에 저장하고 requests와 BeautifulSoup 모듈을 활용하여 추출했다.
세대별 호수와 면적 크롤링 html 코드 위 html 코드를 실행하면 아래와 같은 형태로 보인다.
세대별 호수와 면적 html 실행 ▶ 위 소스 코드를 실행한 결과,
'코딩 연습' 카테고리의 다른 글
파이썬 판다스(pandas) 활용한 엑셀 데이터 분리 (0) 2023.03.26 유튜브 영상 저장 - 한 번에 여러 영상 저장하는 방법 (0) 2023.02.09 chatGPT에서 유튜브 영상 다운로드 파이썬 코드 물어보니... (0) 2023.02.08 용량이 큰 엑셀 자료를 텍스트로 변환하는 방법 (0) 2023.02.06 파이썬에서 이메일 보내기 (4) 2023.01.02