본문 바로가기

AI

매물을 자동으로 수집하는 파이썬 프로그램 예제

반응형



## 📦 기능 요약

- 네이버 부동산에서 매물 정보 크롤링
- 지역별, 타입별(아파트/오피스텔/빌라 등) 필터링 가능
- 매매/전세/월세 구분 가능
- 매물 제목, 가격, 면적, 층수, 관리비, 주소 등을 수집
- CSV 파일로 저장 (엑셀에서 열 수 있음)

---

## 🔧 사용 라이브러리

```bash
pip install requests beautifulsoup4 pandas openpyxl
```

> `openpyxl`은 엑셀(xlsx) 파일로 저장할 때 필요합니다.

---

## ✅ 전체 코드

```python
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time

# 네이버 부동산 URL 생성 함수
def generate_url(real_estate_type, trade_type, region_code, page=1):
    """
    real_estate_type: 아파트(APT), 오피스텔(OPST), 빌라(VILLA), 상가(SHOP) 등
    trade_type: 매매(A1), 전세(B1), 월세(C1)
    region_code: 지역 코드 ex) 강북구: 11200, 서울 전체: 11000
    """
    base_url = "https://land.naver.com"
    url = f"{base_url}/api/articles?cortarNo={region_code}&realEstateType={real_estate_type}&tradeType={trade_type}&type=list&orderBy=DATE_DESC&priceType=&mss="
    url += f"&page={page}"
    return url

# 매물 데이터 파싱 함수
def parse_articles(url, headers):
    response = requests.get(url, headers=headers)
    if response.status_code != 200:
        print(f"Error fetching data: {response.status_code}")
        return []

    try:
        data = response.json()
        articles = data.get("articles", [])
        result = []
        for item in articles:
            title = item["articleName"]
            price = item["price"]
            try_price = item["tryPrice"]
            area = item["area"]
            floor = item["floorDesc"]
            address = f"{item['addressDetail']} ({item['complexName']})"
            confirm_date = item["confirmedDt"]
            manage_cost = item.get("monthlyManageCost", "N/A")
            detail_link = f"https://land.naver.com/article/articleDetail.nhn?rletNo={item['rletNo']}&articleNo={item['articleNo']}"

            result.append({
                "제목": title,
                "가격": price,
                "시도가격": try_price,
                "면적(㎡)": area,
                "층수": floor,
                "관리비": manage_cost,
                "주소": address,
                "확인일": confirm_date,
                "상세링크": detail_link
            })
        return result
    except Exception as e:
        print("JSON 파싱 오류:", str(e))
        return []

# 메인 실행 함수
def collect_real_estate_data(real_estate_type='APT', trade_type='A1', region_code='11200', max_pages=5):
    headers = {
        "User-Agent": "Mozilla/5.0",
        "Referer": "https://land.naver.com/"
    }

    all_items = []
    for page in range(1, max_pages + 1):
        print(f"[{page}페이지] 데이터 수집 중...")
        url = generate_url(real_estate_type, trade_type, region_code, page)
        items = parse_articles(url, headers)
        if not items:
            print("더 이상의 데이터가 없습니다.")
            break
        all_items.extend(items)
        time.sleep(1)  # 서버 부하 방지를 위해 잠깐 쉬기

    df = pd.DataFrame(all_items)
    return df

# CSV 또는 Excel로 저장
def save_to_file(df, filename="naver_real_estate.csv"):
    df.to_csv(filename, index=False, encoding="utf-8-sig")
    print(f"데이터 저장 완료: {filename}")

# 실행 예시
if __name__ == "__main__":
    # 설정값
    REAL_ESTATE_TYPE = 'APT'      # APT(아파트), OPST(오피스텔), VILLA(빌라), OFFICETEL(사무실)
    TRADE_TYPE = 'A1'             # A1(매매), B1(전세), C1(월세)
    REGION_CODE = '11200'         # 강북구 코드, 다른 지역은 하단 참고
    MAX_PAGES = 5                 # 수집할 페이지 수

    # 데이터 수집
    df_result = collect_real_estate_data(
        real_estate_type=REAL_ESTATE_TYPE,
        trade_type=TRADE_TYPE,
        region_code=REGION_CODE,
        max_pages=MAX_PAGES
    )

    # 결과 출력 및 저장
    print(df_result.head())
    save_to_file(df_result, "naver_강북_매물_정보.csv")
```

---

## 📍 지역 코드 참고 (cortarNo)

| 지역명 | 코드 |
|--------|------|
| 서울 전체 | 11000 |
| 강북구 | 11200 |
| 성북구 | 11300 |
| 노원구 | 11400 |
| 도봉구 | 11500 |

다른 지역 코드는 [네이버 부동산](https://land.naver.com/)에서 F12 개발자 도구 → Network → 검색 시 `cortarNo` 확인

---

## 💡 추가 옵션

필요하다면 다음 기능을 추가할 수 있습니다:

- 가격 범위 필터 (`priceMin`, `priceMax`)
- 면적 필터 (`areaMin`, `areaMax`)
- 특정 단지만 필터 (`complexNo`)
- Telegram 알림 / Email 발송
- GUI 인터페이스(tkinter)
- 매물 사진 다운로드
- 엑셀(.xlsx) 형식 저장

---

## 🚨 크롤링 주의사항

- 네이버는 자동 접근을 차단하기 때문에 너무 빠르게 요청하면 IP 차단될 수 있습니다.
- 최소 1초 간격으로 요청하세요 (`time.sleep(1)` 포함됨)
- 상업용으로 사용 시 공식 API 사용 권장

반응형