Categories: '교육'

[고급] 부동산 정보 필터 고도화 – 네이버 매물 정리하기

[고급] 부동산 정보 필터 고도화 ㅣ 그 동안 부동산 정보 크롤링 코드를 모아서 좀 더 고도화 하는 작업을 하도록 해볼게요. 우선 네이버에서 “서울특별시” 를 입력할 경우 모든 법정동을 조회하여 법정동에 헤당하는 아파트를 먼저 모아 오도록 하겠습니다. 법정동에 포함된 아파트 정보를 수집하여 분석할 수 있는 raw data를 만들고 제 기준에 따라 매물을 정리해보도록 하겠습니다.

[고급] 부동산 정보 필터 고도화 – 네이버 매물 정리하기

[고급] 부동산 정보 필터 고도화 – 네이버 매물 정리하기

2024.09.14 – [부동산/자동화 프로젝트] – 파이썬 부동산 매매가 조회 프로그램 만들기 2편 (지역코드)

2024.09.15 – [부동산/자동화 프로젝트] – 부동산 매물 정보 수집하기 – 부동산 데이터 네이버 부동산 크롤링 및 가공 #2

부동산 매매가 조회편과 부동산 매물 정보 수집 편을 확인하면, 아래 코드를 수정하는데 어려움이 없으 실 겁니다.

import requests
import json
import pandas as pd
from datetime import datetime

def get_dong_codes_for_city(city_name, json_path):
    try:
        with open(json_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except FileNotFoundError:
        print(f"Error: The file at {json_path} was not found.")
        return None, None
    
    for si_do in data:
        if si_do['si_do_name'] == city_name:
            sigungu_codes = [sigungu['sigungu_code'] for sigungu in si_do['sigungu']]
            dong_codes = [
                {
                    'code': dong['code'],
                    'name': dong['name']
                }
                for sigungu in si_do['sigungu']
                for dong in sigungu['eup_myeon_dong']
            ]
            return sigungu_codes, dong_codes
    return None, None

def get_apt_list(dong_code):
    down_url = f'https://new.land.naver.com/api/regions/complexes?cortarNo={dong_code}&realEstateType=APT&order='
    header = {
        "Accept-Encoding": "gzip",
        "Host": "new.land.naver.com",
        "Referer": "https://new.land.naver.com/complexes/102378?ms=37.5018495,127.0438028,16&a=APT&b=A1&e=RETAIL",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(down_url, headers=header)
        r.encoding = "utf-8-sig"
        data = r.json()
        
        if 'complexList' in data and isinstance(data['complexList'], list):
            df = pd.DataFrame(data['complexList'])
            
            # 추가 정보 포함 (예: 건축년도, 세대수, 평수 등)
            required_columns = ['complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor']
            
            # 필요한 컬럼만 추출 (없으면 기본값 설정)
            for col in required_columns:
                if col not in df.columns:
                    df[col] = None
            
            return df[required_columns]
        else:
            print(f"No data found for {dong_code}.")
            return pd.DataFrame(columns=['complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor'])
    
    except Exception as e:
        print(f"Error fetching data for {dong_code}: {e}")
        return pd.DataFrame(columns=['complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor'])

def collect_apt_info_for_city(city_name, json_path):
    sigungu_codes, dong_list = get_dong_codes_for_city(city_name, json_path)
    
    if dong_list is None:
        print(f"Error: {city_name} not found in JSON.")
        return None
    
    all_apt_data = []
    dong_code_name_map = {dong['code']: dong['name'] for dong in dong_list}

    for dong_code, dong_name in dong_code_name_map.items():
        print(f"Collecting data for {dong_code} ({dong_name})")
        apt_data = get_apt_list(dong_code)
        
        if not apt_data.empty:
            apt_data = apt_data.copy()  # 데이터프레임 복사본을 생성
            apt_data['dong_code'] = dong_code
            apt_data['dong_name'] = dong_name
            all_apt_data.append(apt_data)
        else:
            print(f"No data found for {dong_code}")
    
    if all_apt_data:
        final_df = pd.concat(all_apt_data, ignore_index=True)
        final_df['si_do_name'] = city_name
        final_df['sigungu_name'] = final_df['dong_code'].apply(lambda x: x[:5])  # sigungu_name 추출
        final_df['dong_name'] = final_df['dong_name'].apply(lambda x: x)  # 동 이름 적용
        final_df = final_df[['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor']]
        return final_df
    else:
        return pd.DataFrame(columns=['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor'])

def save_to_excel(df, city_name):
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    file_name = f"{city_name}_{now}.xlsx"
    file_path = f'/content/drive/MyDrive/{file_name}'
    
    df.to_excel(file_path, index=False)
    print(f"Data saved to {file_path}")

# 사용자 입력 받기
city_name = input("Enter the city or province name: ")
json_path = '/content/drive/MyDrive/district.json'  # 올바른 JSON 파일 경로로 수정하십시오.

# 아파트 정보 수집
apt_data = collect_apt_info_for_city(city_name, json_path)

if apt_data is not None:
    print(apt_data)
    save_to_excel(apt_data, city_name)
else:
    print("No data collected.")

이제 이 코드를 실행해서 어떻게 나오는지 확인해볼까요? 서울특별시 각 구에 속해 있는 아파트 리스트를 아래와 같이 잘 출력하는 것을 확인했습니다. 이제 각 아파트 정보를 옆에 추가적으로 넣어 보도록하겠습니다.

[고급] 부동산 정보 필터 고도화

이 데이터에 아파트별 정보를 추가로 넣는 작업을 하면 아래 코드와 같습니다

import requests
import json
import pandas as pd
from datetime import datetime
from bs4 import BeautifulSoup

def get_dong_codes_for_city(city_name, json_path):
    try:
        with open(json_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except FileNotFoundError:
        print(f"Error: The file at {json_path} was not found.")
        return None, None
    
    for si_do in data:
        if si_do['si_do_name'] == city_name:
            sigungu_codes = [sigungu['sigungu_code'] for sigungu in si_do['sigungu']]
            dong_codes = [
                {
                    'code': dong['code'],
                    'name': dong['name']
                }
                for sigungu in si_do['sigungu']
                for dong in sigungu['eup_myeon_dong']
            ]
            return sigungu_codes, dong_codes
    return None, None

def get_apt_codes(dong_code):
    down_url = f'https://new.land.naver.com/api/regions/complexes?cortarNo={dong_code}&realEstateType=APT&order='
    header = {
        "Accept-Encoding": "gzip",
        "Host": "new.land.naver.com",
        "Referer": "https://new.land.naver.com/complexes/102378?ms=37.5018495,127.0438028,16&a=APT&b=A1&e=RETAIL",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(down_url, headers=header)
        r.encoding = "utf-8-sig"
        data = r.json()
        
        if 'complexList' in data and isinstance(data['complexList'], list):
            apt_codes = [complex_info['complexNo'] for complex_info in data['complexList']]
            return apt_codes
        else:
            print(f"No data found for {dong_code}.")
            return []
    
    except Exception as e:
        print(f"Error fetching apartment codes for {dong_code}: {e}")
        return []

def get_apt_details(apt_code):
    details_url = f'https://fin.land.naver.com/complexes/{apt_code}?tab=complex-info'
    header = {
        "Accept-Encoding": "gzip",
        "Host": "fin.land.naver.com",
        "Referer": "https://fin.land.naver.com/",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(details_url, headers=header)
        r.encoding = "utf-8-sig"
        soup = BeautifulSoup(r.content, 'html.parser')
        
        # Extract complex details
        detail_dict = {'complexNo': apt_code}
        
        detail_items = soup.find_all('li', class_='DataList_item__T1hMR')
        for item in detail_items:
            term = item.find('div', class_='DataList_term__Tks7l').text.strip()
            definition = item.find('div', class_='DataList_definition__d9KY1').text.strip()
            if term in ['공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실']:
                detail_dict[term] = definition
        
        return detail_dict
    
    except Exception as e:
        print(f"Error fetching details for {apt_code}: {e}")
        return {}

def collect_apt_info_for_city(city_name, json_path):
    sigungu_codes, dong_list = get_dong_codes_for_city(city_name, json_path)
    
    if dong_list is None:
        print(f"Error: {city_name} not found in JSON.")
        return None
    
    all_apt_data = []
    dong_code_name_map = {dong['code']: dong['name'] for dong in dong_list}

    for dong_code, dong_name in dong_code_name_map.items():
        print(f"Collecting apartment codes for {dong_code} ({dong_name})")
        apt_codes = get_apt_codes(dong_code)
        
        if apt_codes:
            for apt_code in apt_codes:
                print(f"Collecting details for {apt_code}")
                apt_details = get_apt_details(apt_code)
                
                if apt_details:
                    apt_details['dong_code'] = dong_code
                    apt_details['dong_name'] = dong_name
                    all_apt_data.append(apt_details)
        else:
            print(f"No apartment codes found for {dong_code}")
    
    if all_apt_data:
        final_df = pd.DataFrame(all_apt_data)
        final_df['si_do_name'] = city_name
        final_df['sigungu_name'] = final_df['dong_code'].apply(lambda x: x[:5])  # sigungu_name 추출
        final_df['dong_name'] = final_df['dong_name'].apply(lambda x: x)  # 동 이름 적용
        final_df = final_df[['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실']]
        return final_df
    else:
        return pd.DataFrame(columns=['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실'])

def save_to_excel(df, city_name):
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    file_name = f"{city_name}_{now}.xlsx"
    file_path = f'/content/drive/MyDrive/{file_name}'
    
    df.to_excel(file_path, index=False)
    print(f"Data saved to {file_path}")

# 사용자 입력 받기
city_name = input("Enter the city or province name: ")
json_path = '/content/drive/MyDrive/district.json'  # 올바른 JSON 파일 경로로 수정하십시오.

# 아파트 정보 수집
apt_data = collect_apt_info_for_city(city_name, json_path)

if apt_data is not None:
    print(apt_data)
    save_to_excel(apt_data, city_name)
else:
    print("No data collected.")

서울특별시 전체 동에 대한 정보를 수집하는 것은 꽤 시간이 오래 걸립니다. 서울특별시 전체 동에 대한 정보가 아닌 특정 구까지 입력받아서 조사하도록 수정해보겠습니다. 그리고 만약 전체 구를 조사하고 싶으면 전체 라고 입력할 경우 전체 구에 포함된 법정동을 조사하도록 수정합니다.

import requests
import json
import pandas as pd
from datetime import datetime
from bs4 import BeautifulSoup

# 시/도와 구 정보를 JSON 파일에서 불러오는 함수
def get_dong_codes_for_city(city_name, json_path, sigungu_name=None):
    try:
        with open(json_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except FileNotFoundError:
        print(f"Error: The file at {json_path} was not found.")
        return None, None
    
    for si_do in data:
        if si_do['si_do_name'] == city_name:
            all_sigungu = si_do['sigungu']
            if sigungu_name and sigungu_name != "전체":
                for sigungu in all_sigungu:
                    if sigungu['sigungu_name'] == sigungu_name:
                        dong_codes = [
                            {
                                'code': dong['code'],
                                'name': dong['name']
                            }
                            for dong in sigungu['eup_myeon_dong']
                        ]
                        return [sigungu['sigungu_code']], dong_codes
            else:  # 전체 구를 선택한 경우
                sigungu_codes = [sigungu['sigungu_code'] for sigungu in all_sigungu]
                dong_codes = [
                    {
                        'code': dong['code'],
                        'name': dong['name']
                    }
                    for sigungu in all_sigungu
                    for dong in sigungu['eup_myeon_dong']
                ]
                return sigungu_codes, dong_codes
    return None, None

# 법정동 코드로 아파트 코드를 가져오는 함수
def get_apt_codes(dong_code):
    down_url = f'https://new.land.naver.com/api/regions/complexes?cortarNo={dong_code}&realEstateType=APT&order='
    header = {
        "Accept-Encoding": "gzip",
        "Host": "new.land.naver.com",
        "Referer": "https://new.land.naver.com/complexes/102378?ms=37.5018495,127.0438028,16&a=APT&b=A1&e=RETAIL",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(down_url, headers=header)
        r.encoding = "utf-8-sig"
        data = r.json()
        
        if 'complexList' in data and isinstance(data['complexList'], list):
            apt_codes = [complex_info['complexNo'] for complex_info in data['complexList']]
            return apt_codes
        else:
            print(f"No data found for {dong_code}.")
            return []
    
    except Exception as e:
        print(f"Error fetching apartment codes for {dong_code}: {e}")
        return []

# 아파트 코드로 상세 정보를 가져오는 함수
def get_apt_details(apt_code):
    details_url = f'https://fin.land.naver.com/complexes/{apt_code}?tab=complex-info'
    header = {
        "Accept-Encoding": "gzip",
        "Host": "fin.land.naver.com",
        "Referer": "https://fin.land.naver.com/",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(details_url, headers=header)
        r.encoding = "utf-8-sig"
        soup = BeautifulSoup(r.content, 'html.parser')
        
        # Extract complex details
        detail_dict = {'complexNo': apt_code}
        
        detail_items = soup.find_all('li', class_='DataList_item__T1hMR')
        for item in detail_items:
            term = item.find('div', class_='DataList_term__Tks7l').text.strip()
            definition = item.find('div', class_='DataList_definition__d9KY1').text.strip()
            if term in ['공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실']:
                detail_dict[term] = definition
        
        return detail_dict
    
    except Exception as e:
        print(f"Error fetching details for {apt_code}: {e}")
        return {}

# 도시와 구별로 아파트 정보를 수집하는 함수
def collect_apt_info_for_city(city_name, json_path, sigungu_name=None):
    sigungu_codes, dong_list = get_dong_codes_for_city(city_name, json_path, sigungu_name)
    
    if dong_list is None:
        print(f"Error: {city_name} or {sigungu_name} not found in JSON.")
        return None
    
    all_apt_data = []
    dong_code_name_map = {dong['code']: dong['name'] for dong in dong_list}

    for dong_code, dong_name in dong_code_name_map.items():
        print(f"Collecting apartment codes for {dong_code} ({dong_name})")
        apt_codes = get_apt_codes(dong_code)
        
        if apt_codes:
            for apt_code in apt_codes:
                print(f"Collecting details for {apt_code}")
                apt_details = get_apt_details(apt_code)
                
                if apt_details:
                    apt_details['dong_code'] = dong_code
                    apt_details['dong_name'] = dong_name
                    all_apt_data.append(apt_details)
        else:
            print(f"No apartment codes found for {dong_code}")
    
    if all_apt_data:
        final_df = pd.DataFrame(all_apt_data)
        final_df['si_do_name'] = city_name
        final_df['sigungu_name'] = final_df['dong_code'].apply(lambda x: x[:5])  # sigungu_name 추출
        final_df['dong_name'] = final_df['dong_name'].apply(lambda x: x)  # 동 이름 적용
        final_df = final_df[['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실']]
        return final_df
    else:
        return pd.DataFrame(columns=['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실'])

# 엑셀 파일로 저장하는 함수
def save_to_excel(df, city_name, sigungu_name=None):
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    if sigungu_name and sigungu_name != "전체":
        file_name = f"{city_name}_{sigungu_name}_{now}.xlsx"
    else:
        file_name = f"{city_name}_전체_{now}.xlsx"
    
    file_path = f'/content/drive/MyDrive/{file_name}'
    
    df.to_excel(file_path, index=False)
    print(f"Data saved to {file_path}")

# 사용자 입력 받기
city_name = input("Enter the city or province name (e.g., 서울특별시): ")
sigungu_name = input("Enter the district (gu) name or type '전체' for all districts: ")
json_path = '/content/drive/MyDrive/district.json'  # 올바른 JSON 파일 경로로 수정하십시오.

# 아파트 정보 수집
apt_data = collect_apt_info_for_city(city_name, json_path, sigungu_name)

if apt_data is not None:
    print(apt_data)
    save_to_excel(apt_data, city_name, sigungu_name)
else:
    print("No data collected.")

잘 동작은 합니다만, 여전히 구에 포함된 아파트도 너무 많죠? 시간이 많이 걸리네요, 이제는 특정 시, 구, 동까지 선택할 수 있도록 더 수정해봅니다.

수정을 하면서, 아파트명이 누락되어 있기 때문에 아파트명도 포함시키도록 하겠습니다. 즉 법정동도 선택할 수 있도록 할 예정인데

예를 들어, 서울특별시, 마포구, 아현동까지 법정동을 선택하면 법정동만 조사하고, 전체 라고 선택하면 전체를 조사하게 되는 것입니다. 시/군, 법정동 각각 전체를 입력으면서 만약 시군구를 전체라고 입력하면 법정동은 자동으로 입력 받을 필요 없이 전체를 조사하게 됩니다. 그리고 조사자료에 아파트명이 빠져 있는데 아파트 코드명 옆 열에 아파트 명을 넣을 예정입니다.

from google.colab import drive
import requests
import json
import pandas as pd
from datetime import datetime
from bs4 import BeautifulSoup

# Google Drive 마운트
drive.mount('/content/drive')

# 법정동 코드를 가져오는 함수
def get_dong_codes_for_city(city_name, sigungu_name=None, json_path='/content/drive/MyDrive/district.json'):
    try:
        with open(json_path, 'r', encoding='utf-8') as file:
            data = json.load(file)
    except FileNotFoundError:
        print(f"Error: The file at {json_path} was not found.")
        return None, None

    for si_do in data:
        if si_do['si_do_name'] == city_name:
            if sigungu_name and sigungu_name != '전체':
                for sigungu in si_do['sigungu']:
                    if sigungu['sigungu_name'] == sigungu_name:
                        return [sigungu['sigungu_code']], [
                            {'code': dong['code'], 'name': dong['name']} for dong in sigungu['eup_myeon_dong']
                        ]
            else:  # 시군구 '전체'
                sigungu_codes = [sigungu['sigungu_code'] for sigungu in si_do['sigungu']]
                dong_codes = [
                    {'code': dong['code'], 'name': dong['name']}
                    for sigungu in si_do['sigungu']
                    for dong in sigungu['eup_myeon_dong']
                ]
                return sigungu_codes, dong_codes
    return None, None

# 아파트 코드 리스트 가져오기
def get_apt_list(dong_code):
    down_url = f'https://new.land.naver.com/api/regions/complexes?cortarNo={dong_code}&realEstateType=APT&order='
    header = {
        "Accept-Encoding": "gzip",
        "Host": "new.land.naver.com",
        "Referer": "https://new.land.naver.com/complexes/102378",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0"
    }

    try:
        r = requests.get(down_url, headers=header)
        r.encoding = "utf-8-sig"
        data = r.json()

        if 'complexList' in data and isinstance(data['complexList'], list):
            df = pd.DataFrame(data['complexList'])
            required_columns = ['complexNo', 'complexName', 'buildYear', 'totalHouseholdCount', 'areaSize', 'price', 'address', 'floor']

            for col in required_columns:
                if col not in df.columns:
                    df[col] = None

            return df[required_columns]
        else:
            print(f"No data found for {dong_code}.")
            return pd.DataFrame(columns=required_columns)

    except Exception as e:
        print(f"Error fetching data for {dong_code}: {e}")
        return pd.DataFrame(columns=required_columns)

# 아파트 코드로 상세 정보를 가져오는 함수
def get_apt_details(apt_code):
    details_url = f'https://fin.land.naver.com/complexes/{apt_code}?tab=complex-info'
    header = {
        "Accept-Encoding": "gzip",
        "Host": "fin.land.naver.com",
        "Referer": "https://fin.land.naver.com/",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
    }
    
    try:
        r = requests.get(details_url, headers=header)
        r.encoding = "utf-8-sig"
        soup = BeautifulSoup(r.content, 'html.parser')
        
        # 아파트 이름 추출
        apt_name_tag = soup.find('span', class_='ComplexSummary_name__vX3IN')
        apt_name = apt_name_tag.text.strip() if apt_name_tag else 'Unknown'

        # 상세 정보 추출
        detail_dict = {'complexNo': apt_code, 'complexName': apt_name}

        detail_items = soup.find_all('li', class_='DataList_item__T1hMR')
        for item in detail_items:
            term = item.find('div', class_='DataList_term__Tks7l').text.strip()
            definition = item.find('div', class_='DataList_definition__d9KY1').text.strip()
            if term in ['공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실', '위치', '사용승인일', '세대수', '난방', '주차', '전기차 충전시설', '용적률/건폐율', '관리사무소 전화', '건설사']:
                detail_dict[term] = definition
        
        return detail_dict
    
    except Exception as e:
        print(f"Error fetching details for {apt_code}: {e}")
        return {}

# 아파트 정보를 수집하는 함수 (법정동 선택 가능)
def collect_apt_info_for_city(city_name, sigungu_name, dong_name=None, json_path='/content/drive/MyDrive/district.json'):
    sigungu_codes, dong_list = get_dong_codes_for_city(city_name, sigungu_name, json_path)

    if dong_list is None:
        print(f"Error: {city_name} not found in JSON.")
        return None

    all_apt_data = []
    dong_code_name_map = {dong['code']: dong['name'] for dong in dong_list}

    # 법정동 선택
    if dong_name and dong_name != '전체':
        dong_code_name_map = {k: v for k, v in dong_code_name_map.items() if v == dong_name}

    for dong_code, dong_name in dong_code_name_map.items():
        print(f"Collecting apartment codes for {dong_code} ({dong_name})")
        apt_codes = get_apt_list(dong_code)

        if not apt_codes.empty:
            for _, apt_info in apt_codes.iterrows():
                apt_code = apt_info['complexNo']
                print(f"Collecting details for {apt_code}")
                apt_details = get_apt_details(apt_code)
                
                if apt_details:
                    apt_details['dong_code'] = dong_code
                    apt_details['dong_name'] = dong_name
                    all_apt_data.append(apt_details)
        else:
            print(f"No apartment codes found for {dong_code}")

    if all_apt_data:
        final_df = pd.DataFrame(all_apt_data)
        final_df['si_do_name'] = city_name
        final_df['sigungu_name'] = sigungu_name
        final_df['dong_name'] = final_df['dong_name'].apply(lambda x: x)
        
        # 필요한 모든 열을 포함하도록 설정
        columns = ['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', 'complexName', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실', '위치', '사용승인일', '세대수', '난방', '주차', '전기차 충전시설', '용적률/건폐율', '관리사무소 전화', '건설사']
        for col in columns:
            if col not in final_df.columns:
                final_df[col] = None
        
        final_df = final_df[columns]
        return final_df
    else:
        return pd.DataFrame(columns=['si_do_name', 'sigungu_name', 'dong_name', 'complexNo', 'complexName', '공급면적', '전용면적', '해당면적 세대수', '현관구조', '방/욕실', '위치', '사용승인일', '세대수', '난방', '주차', '전기차 충전시설', '용적률/건폐율', '관리사무소 전화', '건설사'])

# 엑셀 저장 함수
def save_to_excel(df, city_name, sigungu_name):
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    file_name = f"{city_name}_{sigungu_name}_{now}.xlsx"
    file_path = f'/content/drive/MyDrive/{file_name}'
    
    df.to_excel(file_path, index=False)
    print(f"Data saved to {file_path}")

# 사용자 입력 받기
city_name = input("Enter the city or province name: ")
sigungu_name = input(f"Enter the district name in {city_name} (or '전체' for all districts): ")
dong_name = None

if sigungu_name != '전체':
    dong_name = input(f"Enter the dong name in {sigungu_name} (or '전체' for all dongs): ")

# 아파트 정보 수집
apt_data = collect_apt_info_for_city(city_name, sigungu_name, dong_name)

if apt_data is not None and not apt_data.empty:
    print(apt_data)
    save_to_excel(apt_data, city_name, sigungu_name)
else:
    print("No data collected.")
ㅁ

오늘 추가된 정보를 보면 아파트의 정보까지 모두 크롤링할 수 있는 것을 확인 할 수 있습니다. 이제 여기에서 각 아파트의 평형별 정보를 추가하는 것과, 평형대별 아파트의 가격을 조회하면 될 것 같습니다. 다음 편에서 소개할게요! 감사합니다.

urjent

Share
Published by
urjent

Recent Posts

2026 대하축제 일정 및 주차 꿀팁: 홍성 남당항 제철 맛집과 바가지 요금 피하는 법

지금 가을 바다의 진수를 느끼고 싶다면 충남 서해안에서 열리는 대하축제를 찾는 것이 가장 확실한 선택입니다.…

11분 ago

장항석 교수 프로필 강남세브란스병원 갑상선암센터 아침마당 목요특강 총정리

강남세브란스병원 갑상선암센터를 이끌어온 장항석 교수는 국내에서 손꼽히는 난치성 및 진행성 갑상선암 수술 분야의 최고 권위자입니다.…

15분 ago

신천지 이만희 나이 프로필 구속집행정지 정당법 위반 사과 총정리

신천지예수교 증거장막성전의 이만희 총회장이 신도들의 국민의힘 집단 가입을 지시한 혐의로 구속기소된 가운데 건강 문제로 인한…

55분 ago

유해진 유퀴즈 출연 천만 영화 대상 왕과 사는 남자 비하인드 총정리

배우 유해진이 무려 4년 만에 예능 프로그램 유 퀴즈 온 더 블럭에 다시 출연하여 대중의…

2시간 ago

2026 대하축제 일정과 남당항 안면도 시세 비교 및 주차 꿀팁

올해 가을에도 어김없이 찾아온 제철 대하축제는 통통하게 살이 오른 싱싱한 새우를 가장 저렴하고 맛있게 즐길…

2시간 ago

채수빈 프로필 몸매 나이 드라마 영화 구자욱 열애설 총정리

배우 채수빈은 1994년생으로 만 32세를 맞이하며 탄탄한 연기력과 청순한 매력으로 대중의 사랑을 꾸준히 받고 있는…

3시간 ago