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

안동맛집 완벽 정리: 현지인이 추천하는 로컬 찐맛집과 추천 먹거리 모음

성공적인 안동 여행을 완성하려면 유명한 향토 음식과 로컬 주민들이 자주 찾는 식당 정보를 미리 파악하는…

1시간 ago

안동맛집 현지인 추천 베스트 로컬 밥집과 숨은 먹거리 총정리

안동 여행을 준비하면서 어디서 무엇을 먹어야 할지 고민이라면 전통과 현지의 맛이 어우러진 알짜배기 명소들을 주목해야…

2시간 ago

탁구 안재현 선수 프로필 나이 아시안게임 국가대표 총정리

대한민국 남자 탁구의 차세대 간판이자 세계무대에서 저력을 증명해 온 안재현 선수는 1999년생으로 현재 만 26세를…

2시간 ago

안동맛집 현지인이 추천하는 로컬 찐맛집과 꼭 먹어야 할 먹거리 총정리

안동맛집 여행의 진짜 묘미는 화려한 대도시의 음식과 다른 깊은 역사와 정성이 담긴 전통 음식을 제대로…

3시간 ago

전보람 1억 용돈 이유와 나이 키 티아라 활동 부모님 전영록 이미영 총정리

가수 전보람이 인기 그룹 티아라로 활동하던 시절 어머니인 배우 이미영에게 무려 1억 원이라는 거액을 용돈으로…

4시간 ago

안동맛집 현지인 추천 베스트 로컬 먹거리와 숨은 맛집 총정리

안동에 방문했다면 간고등어와 찜닭 외에도 숨겨진 로컬 맛집들을 놓치지 말아야 합니다. 여행 계획을 세울 때…

4시간 ago