goodthings4me.tistory.com
네이버 부동산 아파트 정보를 통해 단지 내 동별 세대별 호수를 찾는 방법이 있는지 알아봤는데, 공공데이터 포털과 달리 좋은 정보가 많았고, 인테리어나 창호 샷시 등의 홍보용 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 코드를 실행하면 아래와 같은 형태로 보인다.
▶ 위 소스 코드를 실행한 결과,
'코딩 연습' 카테고리의 다른 글
파이썬 판다스(pandas) 활용한 엑셀 데이터 분리 (0) | 2023.03.26 |
---|---|
유튜브 영상 저장 - 한 번에 여러 영상 저장하는 방법 (0) | 2023.02.09 |
chatGPT에서 유튜브 영상 다운로드 파이썬 코드 물어보니... (0) | 2023.02.08 |
용량이 큰 엑셀 자료를 텍스트로 변환하는 방법 (0) | 2023.02.06 |
파이썬에서 이메일 보내기 (4) | 2023.01.02 |
댓글