부동산/자동화 프로젝트

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

아보다 2024. 9. 30.
반응형

[고급] 부동산 정보 필터 고도화 ㅣ 그 동안 부동산 정보 크롤링 코드를 모아서 좀 더 고도화 하는 작업을 하도록 해볼게요. 우선 네이버에서 "서울특별시" 를 입력할 경우 모든 법정동을 조회하여 법정동에 헤당하는 아파트를 먼저 모아 오도록 하겠습니다. 법정동에 포함된 아파트 정보를 수집하여 분석할 수 있는 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.")
ㅁ

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

728x90
반응형

댓글

💲 추천 글