<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:media="http://search.yahoo.com/mrss/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>파이썬 크롤링 &#8211; 투데이즈.kr</title>
	<atom:link href="https://2days.kr/tag/%ed%8c%8c%ec%9d%b4%ec%8d%ac-%ed%81%ac%eb%a1%a4%eb%a7%81/feed/" rel="self" type="application/rss+xml" />
	<link>https://2days.kr</link>
	<description>투데이즈</description>
	<lastBuildDate>Sun, 16 Nov 2025 13:11:35 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8</generator>

<image>
	<url>https://2days.kr/wp-content/uploads/2025/10/cropped-simbol-1-32x32.png</url>
	<title>파이썬 크롤링 &#8211; 투데이즈.kr</title>
	<link>https://2days.kr</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>업체 정보 파이썬 :  대표자, 주소, 매출을 한눈에 살펴보기 with python</title>
		<link>https://2days.kr/19/09/17/56562/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Thu, 19 Sep 2024 08:01:31 +0000</pubDate>
				<category><![CDATA[program]]></category>
		<category><![CDATA[업체 매출 크롤링]]></category>
		<category><![CDATA[업체 정보]]></category>
		<category><![CDATA[업체 정보 파이싼]]></category>
		<category><![CDATA[파이썬]]></category>
		<category><![CDATA[파이썬 크롤링]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=56562</guid>

					<description><![CDATA[업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python l 가끔 업체 조사를 할 때면 각 업체의 대표자, 주소, 설립일, 매출 등을 살펴봅니다. 네이버에서 보면 나이스 신용평가에서 제공하는 서비스가 링크가 걸려있는데 이 링크를 클릭하면 그 회사의 정보를 얻을 수 있습니다. 하지만 여러 업체를 조사하려면 꽤 시간이 많이 걸리죠. 그래서 이 노가다 작업을 쉽게 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python l 가끔 업체 조사를 할 때면 각 업체의 대표자, 주소, 설립일, 매출 등을 살펴봅니다. 네이버에서 보면 나이스 신용평가에서 제공하는 서비스가 링크가 걸려있는데 이 링크를 클릭하면 그 회사의 정보를 얻을 수 있습니다. 하지만 여러 업체를 조사하려면 꽤 시간이 많이 걸리죠. 그래서 이 노가다 작업을 쉽게 하기 위해서 코드를 하나 만들어 보려고합니다.</p>
<h3 data-ke-size="size23">업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python</h3>
<p>먼저 네이버에서 해당 정보를 얻기 위해서 구조를 살펴보면 업체를 검색한 뒤, 주소가 바뀌는 패던을 보면 kiscode 값이 바뀌는 것을 볼 수 있습니다. 업체의 고유 번호 같은 것인데, 이 코드를 받은 후 나이스 평가 사이트에서 이 값을 다시 넣어서 업체를 조회하는 패턴으로 코드를 작성해주려고 합니다.</p>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter"><figure style="width: 2560px" class="wp-caption alignnone"><img fetchpriority="high" decoding="async" src="https://blog.kakaocdn.net/dn/exyHRW/btsJEEsRR4y/uL8u1h25seB6NekPP34Lw0/img.png" alt="업체 정보 파이썬 :  대표자, 주소, 매출을 한눈에 살펴보기 with python" width="2560" height="2560" data-origin-width="2560" data-origin-height="2560" data-is-animation="false" data-filename="[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python.png" data-origin- title="업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python 4"><figcaption class="wp-caption-text">업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python</figcaption></figure><figcaption>[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python</figcaption></figure><div class='code-block code-block-2' style='margin: 8px auto; text-align: center; display: block; clear: both;'>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8940400388075870"
     crossorigin="anonymous"></script>
<!-- 중간 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-8940400388075870"
     data-ad-slot="8794586137"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>

<p><span style="color: #ee2323;">[나이스 평가 사이트에서는 무단 크롤링을 엄격히 금지하고 있으니 공부 목적으로만 사용하시기 바랍니다. 고유 지적 재산에 해당 할 수 있으니 이 코드를 유료로도 판매하지 마시고, 또 공부 외의 목적으로는 절대 남용하지 마십시오]</span></p>
<p>아래 보면 (주)삼성전자 의 KISCODE 를 확인할 수 있습니다.</p>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter"><img decoding="async" src="https://blog.kakaocdn.net/dn/BVI6h/btsJF9FelNb/yQ0gDabOKexZ6x31IKs0t1/img.png" data-is-animation="false" data-origin-width="1606" data-origin-height="1446" data-filename="스크린샷 2024-09-19 오후 3.07.00.png" alt="img" title="업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python 5"><figcaption>[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python</figcaption></figure>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter"><img decoding="async" src="https://blog.kakaocdn.net/dn/bGtTt3/btsJEQGCHLR/86SXs3s9tSqSyeqWQNM2Ik/img.png" data-is-animation="false" data-origin-width="2358" data-origin-height="1076" data-filename="스크린샷 2024-09-19 오후 3.27.03.png" alt="img" title="업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python 6"><figcaption>[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python</figcaption></figure>
<p>이렇게 조회한 정보에서 대표자 ~ 상장일자 정보까지 추출해 보겠습니다.</p>
<pre id="code_1726715543453" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import streamlit as st
import pandas as pd
import requests
from bs4 import BeautifulSoup
import ssl
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
import re
import time

<span class="hljs-comment"># SSL/TLS 설정을 위한 어댑터 클래스</span>
class TLSAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        context = ssl.create_default_context()
        context.set_ciphers(<span class="hljs-string">'DEFAULT:@SECLEVEL=1'</span>)
        kwargs[<span class="hljs-string">'ssl_context'</span>] = context
        <span class="hljs-built_in">return</span> super().init_poolmanager(*args, **kwargs)

<span class="hljs-comment"># 세션 생성 및 어댑터 설정</span>
session = requests.Session()
session.mount(<span class="hljs-string">'https://'</span>, TLSAdapter())

<span class="hljs-comment"># 네이버 검색 결과에서 kiscode 추출 함수</span>
def find_kiscode_from_naver_search(query):
    search_url = <span class="hljs-string">'https://search.naver.com/search.naver'</span>
    headers = {
        <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'</span>
    }
    params = {
        <span class="hljs-string">'where'</span>: <span class="hljs-string">'nexearch'</span>,
        <span class="hljs-string">'sm'</span>: <span class="hljs-string">'top_hty'</span>,
        <span class="hljs-string">'fbm'</span>: <span class="hljs-string">'0'</span>,
        <span class="hljs-string">'ie'</span>: <span class="hljs-string">'utf8'</span>,
        <span class="hljs-string">'query'</span>: query
    }

    try:
        response = session.get(search_url, headers=headers, params=params)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, <span class="hljs-string">'html.parser'</span>)
        
        more_info_link = soup.find(<span class="hljs-string">'a'</span>, class_=<span class="hljs-string">'info_more'</span>, href=True)
        <span class="hljs-keyword">if</span> more_info_link and <span class="hljs-string">'kiscode='</span> <span class="hljs-keyword">in</span> more_info_link[<span class="hljs-string">'href'</span>]:
            kiscode = re.search(r<span class="hljs-string">'kiscode=([A-Za-z0-9]+)'</span>, more_info_link[<span class="hljs-string">'href'</span>])
            <span class="hljs-keyword">if</span> kiscode:
                <span class="hljs-built_in">return</span> kiscode.group(1), more_info_link[<span class="hljs-string">'href'</span>]
        <span class="hljs-built_in">return</span> None, None
    except requests.RequestException as e:
        st.error(f<span class="hljs-string">"Request failed: {e}"</span>)
        <span class="hljs-built_in">return</span> None, None

<span class="hljs-comment"># 나이스 사이트에서 업체 정보를 가져오는 함수</span>
def get_company_info(kiscode):
    url = f<span class="hljs-string">'https://www.nicebizinfo.com/ep/EP0100M002GE.nice?kiscode={kiscode}'</span>
    headers = {
        <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'</span>
    }
    
    try:
        response = session.get(url, headers=headers)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, <span class="hljs-string">'html.parser'</span>)
        
        company_info = {
            <span class="hljs-string">'대표자'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'대표자'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'대표자'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'본사주소'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'본사주소'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'본사주소'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'그룹명'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'그룹명'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'그룹명'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'사업자번호'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'사업자번호'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'사업자번호'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'기업형태'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'기업형태'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'기업형태'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'산업'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'산업'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'산업'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'설립일자'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'설립일자'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'설립일자'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
            <span class="hljs-string">'상장일자'</span>: soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'상장일자'</span>).find_next_sibling(<span class="hljs-string">'strong'</span>).get_text(strip=True) <span class="hljs-keyword">if</span> soup.find(<span class="hljs-string">'p'</span>, string=<span class="hljs-string">'상장일자'</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
        }
        
        revenue_row = soup.find(<span class="hljs-string">'tr'</span>, class_=<span class="hljs-string">'bdBck fwb'</span>)
        <span class="hljs-keyword">if</span> revenue_row:
            revenues = revenue_row.find_all(<span class="hljs-string">'td'</span>, class_=<span class="hljs-string">'tar'</span>)
            revenue_data = []
            <span class="hljs-keyword">for</span> td <span class="hljs-keyword">in</span> revenues:
                text = td.get_text(strip=True).replace(<span class="hljs-string">','</span>, <span class="hljs-string">''</span>).replace(<span class="hljs-string">' '</span>, <span class="hljs-string">''</span>)
                <span class="hljs-keyword">if</span> text.isdigit():
                    revenue_data.append(f<span class="hljs-string">"{int(text):,} 원"</span>)
                <span class="hljs-keyword">else</span>:
                    revenue_data.append(text)
        <span class="hljs-keyword">else</span>:
            revenue_data = [<span class="hljs-string">''</span>, <span class="hljs-string">''</span>, <span class="hljs-string">''</span>]
        
        <span class="hljs-built_in">return</span> company_info, revenue_data
    except requests.RequestException as e:
        st.error(f<span class="hljs-string">"Request failed: {e}"</span>)
        <span class="hljs-built_in">return</span> {}, [<span class="hljs-string">''</span>, <span class="hljs-string">''</span>, <span class="hljs-string">''</span>]

<span class="hljs-comment"># 스트림릿 웹 앱 구성</span>
def main():
    st.title(<span class="hljs-string">"업체 정보 조회기"</span>)
    
    <span class="hljs-comment"># 옵션 선택: 직접 입력 vs 엑셀 업로드</span>
    option = st.radio(<span class="hljs-string">"업체명을 직접 입력하시겠습니까, 아니면 엑셀 파일을 업로드하시겠습니까?"</span>, (<span class="hljs-string">"직접 입력"</span>, <span class="hljs-string">"엑셀 업로드"</span>))

    <span class="hljs-keyword">if</span> option == <span class="hljs-string">"직접 입력"</span>:
        company_name = st.text_input(<span class="hljs-string">"업체명을 입력하세요:"</span>)
        <span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"조회"</span>):
            kiscode, nice_info_url = find_kiscode_from_naver_search(company_name)
            <span class="hljs-keyword">if</span> kiscode:
                company_info, revenue_data = get_company_info(kiscode)
                result = {
                    <span class="hljs-string">'업체명'</span>: company_name,
                    <span class="hljs-string">'kiscode'</span>: kiscode,
                    <span class="hljs-string">'대표자'</span>: company_info.get(<span class="hljs-string">'대표자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'본사주소'</span>: company_info.get(<span class="hljs-string">'본사주소'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'그룹명'</span>: company_info.get(<span class="hljs-string">'그룹명'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'사업자번호'</span>: company_info.get(<span class="hljs-string">'사업자번호'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'기업형태'</span>: company_info.get(<span class="hljs-string">'기업형태'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'산업'</span>: company_info.get(<span class="hljs-string">'산업'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'설립일자'</span>: company_info.get(<span class="hljs-string">'설립일자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'상장일자'</span>: company_info.get(<span class="hljs-string">'상장일자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'2023년 매출'</span>: revenue_data[0],
                    <span class="hljs-string">'2022년 매출'</span>: revenue_data[1],
                    <span class="hljs-string">'2021년 매출'</span>: revenue_data[2]
                }
                st.write(result)
            <span class="hljs-keyword">else</span>:
                st.write(f<span class="hljs-string">"업체 '{company_name}'를 찾을 수 없습니다."</span>)
    
    <span class="hljs-keyword">elif</span> option == <span class="hljs-string">"엑셀 업로드"</span>:
        uploaded_file = st.file_uploader(<span class="hljs-string">"업로드할 엑셀 파일을 선택하세요."</span>, <span class="hljs-built_in">type</span>=[<span class="hljs-string">"xlsx"</span>])
        
        <span class="hljs-keyword">if</span> uploaded_file is not None:
            df = pd.read_excel(uploaded_file)
            <span class="hljs-keyword">if</span> <span class="hljs-string">'업체명'</span> not <span class="hljs-keyword">in</span> df.columns:
                st.error(<span class="hljs-string">"엑셀 파일에 '업체명' 열이 존재하지 않습니다."</span>)
                <span class="hljs-built_in">return</span>
            
            results = []
            total_companies = len(df)
            completed_count = 0
            failed_count = 0
            progress_placeholder = st.empty()
            
            <span class="hljs-keyword">for</span> idx, company_name <span class="hljs-keyword">in</span> enumerate(df[<span class="hljs-string">'업체명'</span>]):
                kiscode, nice_info_url = find_kiscode_from_naver_search(company_name)
                company_info, revenue_data = ({<span class="hljs-string">'대표자'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'본사주소'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'그룹명'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'사업자번호'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'기업형태'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'산업'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'설립일자'</span>: <span class="hljs-string">''</span>, <span class="hljs-string">'상장일자'</span>: <span class="hljs-string">''</span>}, [<span class="hljs-string">''</span>, <span class="hljs-string">''</span>, <span class="hljs-string">''</span>]) <span class="hljs-keyword">if</span> not kiscode <span class="hljs-keyword">else</span> get_company_info(kiscode)
                
                result = {
                    <span class="hljs-string">'업체명'</span>: company_name,
                    <span class="hljs-string">'kiscode'</span>: kiscode <span class="hljs-keyword">if</span> kiscode <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>,
                    <span class="hljs-string">'대표자'</span>: company_info.get(<span class="hljs-string">'대표자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'본사주소'</span>: company_info.get(<span class="hljs-string">'본사주소'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'그룹명'</span>: company_info.get(<span class="hljs-string">'그룹명'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'사업자번호'</span>: company_info.get(<span class="hljs-string">'사업자번호'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'기업형태'</span>: company_info.get(<span class="hljs-string">'기업형태'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'산업'</span>: company_info.get(<span class="hljs-string">'산업'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'설립일자'</span>: company_info.get(<span class="hljs-string">'설립일자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'상장일자'</span>: company_info.get(<span class="hljs-string">'상장일자'</span>, <span class="hljs-string">''</span>),
                    <span class="hljs-string">'2023년 매출'</span>: revenue_data[0],
                    <span class="hljs-string">'2022년 매출'</span>: revenue_data[1],
                    <span class="hljs-string">'2021년 매출'</span>: revenue_data[2]
                }
                results.append(result)
                
                <span class="hljs-keyword">if</span> kiscode:
                    completed_count += 1
                <span class="hljs-keyword">else</span>:
                    failed_count += 1
                
                remaining_count = total_companies - (idx + 1)
                progress = (idx + 1) / total_companies * 100
                progress_placeholder.write(f<span class="hljs-string">"진척율: {progress:.2f}% | 완료: {completed_count}개 | 실패: {failed_count}개 | 남은 작업 수: {remaining_count}개"</span>)
                
                <span class="hljs-comment"># 각 요청 사이에 3초 딜레이 추가</span>
                time.sleep(1.5)
            
            <span class="hljs-comment"># 결과 출력</span>
            results_df = pd.DataFrame(results)
            <span class="hljs-keyword">if</span> not results_df.empty:
                st.write(results_df)
            
            <span class="hljs-keyword">if</span> failed_count &gt; 0:
                st.write(<span class="hljs-string">"다음 업체들은 정보를 찾을 수 없었습니다:"</span>)
                st.write([res[<span class="hljs-string">'업체명'</span>] <span class="hljs-keyword">for</span> res <span class="hljs-keyword">in</span> results <span class="hljs-keyword">if</span> not res[<span class="hljs-string">'kiscode'</span>]])
    
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()</pre>
<p>이렇게 추출한 코드는 streamlit에서 돌리면 아름다운 코드로 바뀌는 것을 볼 수 있습니다.</p>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter"><img decoding="async" src="https://blog.kakaocdn.net/dn/byo7ES/btsJDYkZd0i/u3VxguhrTTgnmFPHESYJhk/img.png" data-is-animation="false" data-origin-width="2366" data-origin-height="1066" data-filename="스크린샷 2024-09-19 오후 4.19.20.png" alt="img" title="업체 정보 파이썬 : 대표자, 주소, 매출을 한눈에 살펴보기 with python 7"><figcaption><a href="https://2days.kr/14/09/14/56529/coding/data/">파이썬 부동산 매매가 조회 프로그램 만들기 4편 (전국 데이터)</a></figcaption></figure>
<!-- CONTENT END 2 -->
]]></content:encoded>
					
		
		
		<media:content url="https://2days.kr/wp-content/uploads/2024/09/업체-정보-대표자-주소-매출을-한눈에-살펴보기-with-python.png" medium="image"></media:content>
            	</item>
		<item>
		<title>[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</title>
		<link>https://2days.kr/18/09/22/56553/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Wed, 18 Sep 2024 13:35:01 +0000</pubDate>
				<category><![CDATA[program]]></category>
		<category><![CDATA[네이버 부동산]]></category>
		<category><![CDATA[네이버 부동산 크롤링]]></category>
		<category><![CDATA[네이버 크롤링]]></category>
		<category><![CDATA[부동산]]></category>
		<category><![CDATA[부동산 정보 크롤링]]></category>
		<category><![CDATA[파이썬]]></category>
		<category><![CDATA[파이썬 부동산]]></category>
		<category><![CDATA[파이썬 크롤링]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=56553</guid>

					<description><![CDATA[[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 편에 이어서 추가적으로 결과 값을 조금 더 디테일하게 정리해보려고 합니다. https://fin.land.naver.com/complexes/106861?tab=complex-info 여기에서 보면 우리 데이터와 일부 맞지 않는 부분을 확인 할 수 있습니다. 바로 공급면적, 전용면적이 실제 매물에 나와 있는 면적과 다르다는 것입니다. [고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2 그 이유는 바로 네이버 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p data-ke-size="size16">[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 편에 이어서 추가적으로 결과 값을 조금 더 디테일하게 정리해보려고 합니다. <a href="https://fin.land.naver.com/complexes/106861?tab=complex-info" target="_blank" rel="noopener noreferrer noopener">https://fin.land.naver.com/complexes/106861?tab=complex-info</a></p>
<p data-ke-size="size16">여기에서 보면 우리 데이터와 일부 맞지 않는 부분을 확인 할 수 있습니다. 바로 공급면적, 전용면적이 실제 매물에 나와 있는 면적과 다르다는 것입니다.</p>
<figure data-ke-type="image" data-ke-style="alignCenter" data-ke-mobilestyle="widthOrigin"><figure style="width: 2544px" class="wp-caption alignnone"><img decoding="async" src="https://blog.kakaocdn.net/dn/kNe8i/btsJFrFyRi2/gcx17BYOkKkh0eWUVLKSK0/img.png" alt="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2" width="2544" height="852" data-origin-width="2544" data-origin-height="852" data-filename="스크린샷 2024-09-18 오전 9.23.47.png" data-is-animation="false" data-origin- title="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2 9"><figcaption class="wp-caption-text">[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</figcaption></figure><figcaption>[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</figcaption></figure><div class='code-block code-block-2' style='margin: 8px auto; text-align: center; display: block; clear: both;'>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8940400388075870"
     crossorigin="anonymous"></script>
<!-- 중간 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-8940400388075870"
     data-ad-slot="8794586137"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>

<p data-ke-size="size16">그 이유는 바로 네이버 면적 정보 부분에서 면적 정보를 각각 클릭해야만 해당 면적에 대한 정보를 가져오게 되는데, 우리가 크롤링했던 공급면적, 전용면적 등의 정보는 가장 처음 나오는 면적에 대한 정보를 끌어 왔기 때문이죠, 따라서 면적이라는 부분의 데이터를 기준으로 맞춰서 해당 공급면적을 찾아내고, 그에 맞는 전용면적 ~ 방/욕실에 대한 정보를 수정해야겠습니다.</p>
<figure data-ke-type="image" data-ke-style="alignCenter" data-ke-mobilestyle="widthOrigin"><img decoding="async" src="https://blog.kakaocdn.net/dn/b6p1RV/btsJDviA0O1/UmxBmwVcZouZlXZ7GdI1zk/img.png" data-origin-width="1488" data-origin-height="1158" data-filename="스크린샷 2024-09-18 오전 9.25.38.png" data-is-animation="false" alt="img" title="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2 10"><figcaption>[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</figcaption></figure>
<h3 data-ke-size="size23"><b>[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</b></h3>
<figure data-ke-type="image" data-ke-style="alignCenter" data-ke-mobilestyle="widthOrigin"><figure style="width: 2560px" class="wp-caption alignnone"><img decoding="async" src="https://blog.kakaocdn.net/dn/sr0e1/btsJDwuPIL5/DERzjgIQ1ykgt3RksCoNp1/img.png" alt="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2" width="2560" height="2560" data-origin-width="2560" data-origin-height="2560" data-filename="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2.png" data-is-animation="false" data-origin- title="[고급] 부동산 정보 필터 고도화 - 네이버 매물 정리하기 2 11"><figcaption class="wp-caption-text">[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</figcaption></figure><figcaption>[고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기 2</figcaption></figure>
<p data-ke-size="size16">오늘 글은 시리즈로 구성된 기본편을 기본으로 하고 있습니다. 아직 기본편을 못 보신 분들이라면 아래 글을 한번 읽어 주세요!</p>
<p data-ke-size="size16"><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-1" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</a></p>
<p data-ke-size="size16"><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-2" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</a></p>
<p data-ke-size="size16"><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-3" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3</a></p>
<p data-ke-size="size16"><a href="https://aboda.kr/entry/%EA%B3%A0%EA%B8%89-%EB%B6%80%EB%8F%99%EC%82%B0-%EC%A0%95%EB%B3%B4-%ED%95%84%ED%84%B0-%EA%B3%A0%EB%8F%84%ED%99%94-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0" target="_blank" rel="noopener">2024.09.17 &#8211; [부동산/자동화 프로젝트] &#8211; [고급] 부동산 정보 필터 고도화 &#8211; 네이버 매물 정리하기</a></p>
<p data-ke-size="size16">이 부분은 동적 네트워크를 사용해야 해서, 현재 데이터에서만 정리해볼까 합니다. 현재 정리되어 있는 전체코드는 아래와 같습니다.</p>

<pre id="code_1726623550100" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">from google.colab import drive
import requests
import json
import pandas as pd
from datetime import datetime
from bs4 import BeautifulSoup

<span class="hljs-comment"># Google Drive 마운트</span>
drive.mount(<span class="hljs-string">'/content/drive'</span>)

<span class="hljs-comment"># 법정동 코드를 가져오는 함수</span>
def get_dong_codes_for_city(city_name, sigungu_name=None, json_path=<span class="hljs-string">'/content/drive/MyDrive/district.json'</span>):
    try:
        with open(json_path, <span class="hljs-string">'r'</span>, encoding=<span class="hljs-string">'utf-8'</span>) as file:
            data = json.load(file)
    except FileNotFoundError:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error: The file at {json_path} was not found."</span>)
        <span class="hljs-built_in">return</span> None, None

    <span class="hljs-keyword">for</span> si_do <span class="hljs-keyword">in</span> data:
        <span class="hljs-keyword">if</span> si_do[<span class="hljs-string">'si_do_name'</span>] == city_name:
            <span class="hljs-keyword">if</span> sigungu_name and sigungu_name != <span class="hljs-string">'전체'</span>:
                <span class="hljs-keyword">for</span> sigungu <span class="hljs-keyword">in</span> si_do[<span class="hljs-string">'sigungu'</span>]:
                    <span class="hljs-keyword">if</span> sigungu[<span class="hljs-string">'sigungu_name'</span>] == sigungu_name:
                        <span class="hljs-built_in">return</span> [sigungu[<span class="hljs-string">'sigungu_code'</span>]], [
                            {<span class="hljs-string">'code'</span>: dong[<span class="hljs-string">'code'</span>], <span class="hljs-string">'name'</span>: dong[<span class="hljs-string">'name'</span>]} <span class="hljs-keyword">for</span> dong <span class="hljs-keyword">in</span> sigungu[<span class="hljs-string">'eup_myeon_dong'</span>]
                        ]
            <span class="hljs-keyword">else</span>:  <span class="hljs-comment"># 시군구 '전체'</span>
                sigungu_codes = [sigungu[<span class="hljs-string">'sigungu_code'</span>] <span class="hljs-keyword">for</span> sigungu <span class="hljs-keyword">in</span> si_do[<span class="hljs-string">'sigungu'</span>]]
                dong_codes = [
                    {<span class="hljs-string">'code'</span>: dong[<span class="hljs-string">'code'</span>], <span class="hljs-string">'name'</span>: dong[<span class="hljs-string">'name'</span>]}
                    <span class="hljs-keyword">for</span> sigungu <span class="hljs-keyword">in</span> si_do[<span class="hljs-string">'sigungu'</span>]
                    <span class="hljs-keyword">for</span> dong <span class="hljs-keyword">in</span> sigungu[<span class="hljs-string">'eup_myeon_dong'</span>]
                ]
                <span class="hljs-built_in">return</span> sigungu_codes, dong_codes
    <span class="hljs-built_in">return</span> None, None

<span class="hljs-comment"># 아파트 코드 리스트 가져오기</span>
def get_apt_list(dong_code):
    down_url = f<span class="hljs-string">'https://new.land.naver.com/api/regions/complexes?cortarNo={dong_code}&amp;realEstateType=APT&amp;order='</span>
    header = {
        <span class="hljs-string">"Accept-Encoding"</span>: <span class="hljs-string">"gzip"</span>,
        <span class="hljs-string">"Host"</span>: <span class="hljs-string">"new.land.naver.com"</span>,
        <span class="hljs-string">"Referer"</span>: <span class="hljs-string">"https://new.land.naver.com/complexes/102378"</span>,
        <span class="hljs-string">"Sec-Fetch-Dest"</span>: <span class="hljs-string">"empty"</span>,
        <span class="hljs-string">"Sec-Fetch-Mode"</span>: <span class="hljs-string">"cors"</span>,
        <span class="hljs-string">"Sec-Fetch-Site"</span>: <span class="hljs-string">"same-origin"</span>,
        <span class="hljs-string">"User-Agent"</span>: <span class="hljs-string">"Mozilla/5.0"</span>
    }

    try:
        r = requests.get(down_url, headers=header)
        r.encoding = <span class="hljs-string">"utf-8-sig"</span>
        data = r.json()

        <span class="hljs-keyword">if</span> <span class="hljs-string">'complexList'</span> <span class="hljs-keyword">in</span> data and isinstance(data[<span class="hljs-string">'complexList'</span>], list):
            df = pd.DataFrame(data[<span class="hljs-string">'complexList'</span>])
            required_columns = [<span class="hljs-string">'complexNo'</span>, <span class="hljs-string">'complexName'</span>, <span class="hljs-string">'buildYear'</span>, <span class="hljs-string">'totalHouseholdCount'</span>, <span class="hljs-string">'areaSize'</span>, <span class="hljs-string">'price'</span>, <span class="hljs-string">'address'</span>, <span class="hljs-string">'floor'</span>]

            <span class="hljs-keyword">for</span> col <span class="hljs-keyword">in</span> required_columns:
                <span class="hljs-keyword">if</span> col not <span class="hljs-keyword">in</span> df.columns:
                    df[col] = None

            <span class="hljs-built_in">return</span> df[required_columns]
        <span class="hljs-keyword">else</span>:
            <span class="hljs-built_in">print</span>(f<span class="hljs-string">"No data found for {dong_code}."</span>)
            <span class="hljs-built_in">return</span> pd.DataFrame(columns=required_columns)

    except Exception as e:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error fetching data for {dong_code}: {e}"</span>)
        <span class="hljs-built_in">return</span> pd.DataFrame(columns=required_columns)

<span class="hljs-comment"># 아파트 코드로 상세 정보를 가져오는 함수 (매매 정보 추가)</span>
def get_apt_details(apt_code):
    details_url = f<span class="hljs-string">'https://fin.land.naver.com/complexes/{apt_code}?tab=complex-info'</span>
    article_url = f<span class="hljs-string">'https://fin.land.naver.com/complexes/{apt_code}?tab=article&amp;tradeTypes=A1'</span>
    
    header = {
        <span class="hljs-string">"Accept-Encoding"</span>: <span class="hljs-string">"gzip"</span>,
        <span class="hljs-string">"Host"</span>: <span class="hljs-string">"fin.land.naver.com"</span>,
        <span class="hljs-string">"Referer"</span>: <span class="hljs-string">"https://fin.land.naver.com/"</span>,
        <span class="hljs-string">"Sec-Fetch-Dest"</span>: <span class="hljs-string">"empty"</span>,
        <span class="hljs-string">"Sec-Fetch-Mode"</span>: <span class="hljs-string">"cors"</span>,
        <span class="hljs-string">"Sec-Fetch-Site"</span>: <span class="hljs-string">"same-origin"</span>,
        <span class="hljs-string">"User-Agent"</span>: <span class="hljs-string">"Mozilla/5.0"</span>
    }
    
    try:
        <span class="hljs-comment"># 기본 정보 가져오기</span>
        r_details = requests.get(details_url, headers=header)
        r_details.encoding = <span class="hljs-string">"utf-8-sig"</span>
        soup_details = BeautifulSoup(r_details.content, <span class="hljs-string">'html.parser'</span>)
        
        <span class="hljs-comment"># 아파트 이름 추출</span>
        apt_name_tag = soup_details.find(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'ComplexSummary_name__vX3IN'</span>)
        apt_name = apt_name_tag.text.strip() <span class="hljs-keyword">if</span> apt_name_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>

        <span class="hljs-comment"># 기본 정보 딕셔너리</span>
        detail_dict = {<span class="hljs-string">'complexNo'</span>: apt_code, <span class="hljs-string">'complexName'</span>: apt_name}
        
        <span class="hljs-comment"># 기본 상세 정보 추출 (공급면적, 전용면적, 방/욕실 등)</span>
        detail_items = soup_details.find_all(<span class="hljs-string">'li'</span>, class_=<span class="hljs-string">'DataList_item__T1hMR'</span>)
        <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> detail_items:
            term = item.find(<span class="hljs-string">'div'</span>, class_=<span class="hljs-string">'DataList_term__Tks7l'</span>).text.strip()
            definition = item.find(<span class="hljs-string">'div'</span>, class_=<span class="hljs-string">'DataList_definition__d9KY1'</span>).text.strip()
            <span class="hljs-keyword">if</span> term <span class="hljs-keyword">in</span> [<span class="hljs-string">'공급면적'</span>, <span class="hljs-string">'전용면적'</span>, <span class="hljs-string">'해당면적 세대수'</span>, <span class="hljs-string">'현관구조'</span>, <span class="hljs-string">'방/욕실'</span>, <span class="hljs-string">'위치'</span>, <span class="hljs-string">'사용승인일'</span>, <span class="hljs-string">'세대수'</span>, <span class="hljs-string">'난방'</span>, <span class="hljs-string">'주차'</span>, <span class="hljs-string">'전기차 충전시설'</span>, <span class="hljs-string">'용적률/건폐율'</span>, <span class="hljs-string">'관리사무소 전화'</span>, <span class="hljs-string">'건설사'</span>]:
                detail_dict[term] = definition
        
        <span class="hljs-comment"># 매물 정보 가져오기</span>
        r_article = requests.get(article_url, headers=header)
        r_article.encoding = <span class="hljs-string">"utf-8-sig"</span>
        soup_article = BeautifulSoup(r_article.content, <span class="hljs-string">'html.parser'</span>)
        
        <span class="hljs-comment"># 매물 리스트</span>
        listings = []
        <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> soup_article.find_all(<span class="hljs-string">'li'</span>, class_=<span class="hljs-string">'ComplexArticleItem_item__L5o7k'</span>):
            listing = {}
            
            <span class="hljs-comment"># 매물 이름</span>
            name_tag = item.find(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'ComplexArticleItem_name__4h3AA'</span>)
            listing[<span class="hljs-string">'매물명'</span>] = name_tag.text.strip() <span class="hljs-keyword">if</span> name_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>
            
            <span class="hljs-comment"># 매매 가격</span>
            price_tag = item.find(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'ComplexArticleItem_price__DFeIb'</span>)
            listing[<span class="hljs-string">'매매가'</span>] = price_tag.text.strip() <span class="hljs-keyword">if</span> price_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>
            
            <span class="hljs-comment"># 면적, 층수, 방향</span>
            summary_items = item.find_all(<span class="hljs-string">'li'</span>, class_=<span class="hljs-string">'ComplexArticleItem_item-summary__oHSwl'</span>)
            <span class="hljs-keyword">if</span> len(summary_items) &gt;= 4:
                listing[<span class="hljs-string">'면적'</span>] = summary_items[1].text.strip() <span class="hljs-keyword">if</span> len(summary_items) &gt; 1 <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>
                listing[<span class="hljs-string">'층수'</span>] = summary_items[2].text.strip() <span class="hljs-keyword">if</span> len(summary_items) &gt; 2 <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>
                listing[<span class="hljs-string">'방향'</span>] = summary_items[3].text.strip() <span class="hljs-keyword">if</span> len(summary_items) &gt; 3 <span class="hljs-keyword">else</span> <span class="hljs-string">'Unknown'</span>
            
            <span class="hljs-comment"># 이미지</span>
            image_tag = item.find(<span class="hljs-string">'img'</span>)
            listing[<span class="hljs-string">'이미지'</span>] = image_tag[<span class="hljs-string">'src'</span>] <span class="hljs-keyword">if</span> image_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'No image'</span>
            
            <span class="hljs-comment"># 코멘트</span>
            comment_tag = item.find(<span class="hljs-string">'p'</span>, class_=<span class="hljs-string">'ComplexArticleItem_comment__zN_dK'</span>)
            listing[<span class="hljs-string">'코멘트'</span>] = comment_tag.text.strip() <span class="hljs-keyword">if</span> comment_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'No comment'</span>
            
            <span class="hljs-comment"># 각 매물마다 기본 상세 정보(공급면적, 방/욕실 등)를 매물에 추가</span>
            combined_listing = {**detail_dict, **listing}
            listings.append(combined_listing)
        
        <span class="hljs-built_in">return</span> listings
    
    except Exception as e:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error fetching details for {apt_code}: {e}"</span>)
        <span class="hljs-built_in">return</span> []

<span class="hljs-comment"># 아파트 정보를 수집하는 함수 (법정동 선택 가능)</span>
def collect_apt_info_for_city(city_name, sigungu_name, dong_name=None, json_path=<span class="hljs-string">'/content/drive/MyDrive/district.json'</span>):
    sigungu_codes, dong_list = get_dong_codes_for_city(city_name, sigungu_name, json_path)

    <span class="hljs-keyword">if</span> dong_list is None:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error: {city_name} not found in JSON."</span>)
        <span class="hljs-built_in">return</span> None

    all_apt_data = []
    dong_code_name_map = {dong[<span class="hljs-string">'code'</span>]: dong[<span class="hljs-string">'name'</span>] <span class="hljs-keyword">for</span> dong <span class="hljs-keyword">in</span> dong_list}

    <span class="hljs-comment"># 법정동 선택</span>
    <span class="hljs-keyword">if</span> dong_name and dong_name != <span class="hljs-string">'전체'</span>:
        dong_code_name_map = {k: v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> dong_code_name_map.items() <span class="hljs-keyword">if</span> v == dong_name}

    <span class="hljs-keyword">for</span> dong_code, dong_name <span class="hljs-keyword">in</span> dong_code_name_map.items():
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Collecting apartment codes for {dong_code} ({dong_name})"</span>)
        apt_codes = get_apt_list(dong_code)

        <span class="hljs-keyword">if</span> not apt_codes.empty:
            <span class="hljs-keyword">for</span> _, apt_info <span class="hljs-keyword">in</span> apt_codes.iterrows():
                apt_code = apt_info[<span class="hljs-string">'complexNo'</span>]
                <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Collecting details for {apt_code}"</span>)
                listings = get_apt_details(apt_code)
                
                <span class="hljs-keyword">if</span> listings:
                    <span class="hljs-keyword">for</span> listing <span class="hljs-keyword">in</span> listings:
                        <span class="hljs-comment"># 모든 매물 정보를 결합</span>
                        listing[<span class="hljs-string">'dong_code'</span>] = dong_code
                        listing[<span class="hljs-string">'dong_name'</span>] = dong_name
                        all_apt_data.append(listing)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-built_in">print</span>(f<span class="hljs-string">"No apartment codes found for {dong_code}"</span>)

    <span class="hljs-keyword">if</span> all_apt_data:
        final_df = pd.DataFrame(all_apt_data)
        final_df[<span class="hljs-string">'si_do_name'</span>] = city_name
        final_df[<span class="hljs-string">'sigungu_name'</span>] = sigungu_name
        final_df[<span class="hljs-string">'dong_name'</span>] = dong_name <span class="hljs-keyword">if</span> dong_name <span class="hljs-keyword">else</span> <span class="hljs-string">'전체'</span>
        
        <span class="hljs-comment"># 엑셀 파일로 저장</span>
        file_path = f<span class="hljs-string">'/content/drive/MyDrive/{city_name}_{sigungu_name}_apartments.xlsx'</span>
        final_df.to_excel(file_path, index=False)
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Data saved to {file_path}"</span>)
    <span class="hljs-keyword">else</span>:
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"No data to save."</span>)

<span class="hljs-comment"># 함수 호출 예시</span>
collect_apt_info_for_city(<span class="hljs-string">"서울특별시"</span>, <span class="hljs-string">"강남구"</span>, <span class="hljs-string">"개포동"</span>)</pre>
<p>자 다음편에서는 이 서비스를 스트림릿으로 연계해서 실제 사용자가 편하게 웹에서 선택하여 사용할 수 있도록 정리해보겠습니다.</p>
<p>&nbsp;</p>
<!-- CONTENT END 4 -->
]]></content:encoded>
					
		
		
		<media:content url="https://2days.kr/wp-content/uploads/2024/09/고급-부동산-정보-필터-고도화-네이버-매물-정리하기-2.png" medium="image"></media:content>
            	</item>
		<item>
		<title>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3</title>
		<link>https://2days.kr/15/09/10/56542/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Sun, 15 Sep 2024 01:01:12 +0000</pubDate>
				<category><![CDATA[program]]></category>
		<category><![CDATA[네이버]]></category>
		<category><![CDATA[네이버 부동산]]></category>
		<category><![CDATA[네이버 부동산 크롤링]]></category>
		<category><![CDATA[부동산]]></category>
		<category><![CDATA[크롤링]]></category>
		<category><![CDATA[파이썬]]></category>
		<category><![CDATA[파이썬 크롤링]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=56542</guid>

					<description><![CDATA[부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3 ㅣ 부동산 시장에서 아파트 단지에 대한 정보는 투자자와 구매자에게 매우 중요한 요소입니다. 특히, 특정 지역의 아파트 단지 정보를 효율적으로 수집하는 방법은 데이터 기반의 의사결정을 가능하게 합니다. 이번 포스트에서는 네이버 부동산 API를 활용하여 특정 법정동에 위치한 아파트 단지의 이름과 고유 코드를 조회하는 방법에 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p style="background-color: #ffffff; color: #000000; text-align: start;">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3 ㅣ 부동산 시장에서 아파트 단지에 대한 정보는 투자자와 구매자에게 매우 중요한 요소입니다. 특히, 특정 지역의 아파트 단지 정보를 효율적으로 수집하는 방법은 데이터 기반의 의사결정을 가능하게 합니다. 이번 포스트에서는 네이버 부동산 API를 활용하여 특정 법정동에 위치한 아파트 단지의 이름과 고유 코드를 조회하는 방법에 대해 자세히 알아보겠습니다.</p>
<h3 style="background-color: #ffffff; color: #000000; text-align: start;" data-ke-size="size23">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3</h3>
<p><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-1" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</a></p>
<p><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-2" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</a></p>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter">
<p><figure style="width: 2560px" class="wp-caption alignnone"><img loading="lazy" decoding="async" src="https://blog.kakaocdn.net/dn/rJJDc/btsJEjVhkPo/2kZUECtqYCLHX9Hz4SCBxK/img.png" alt="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #3" width="2560" height="2560" data-origin-width="2560" data-origin-height="2560" data-is-animation="false" data-filename="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #3.png" data-origin- title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #3 12"><figcaption class="wp-caption-text">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3</figcaption></figure><figcaption>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #3</figcaption></figure><div class='code-block code-block-2' style='margin: 8px auto; text-align: center; display: block; clear: both;'>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8940400388075870"
     crossorigin="anonymous"></script>
<!-- 중간 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-8940400388075870"
     data-ad-slot="8794586137"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>

<h2 style="background-color: #ffffff; color: #000000; text-align: start;">1. 법정동과 행정동의 이해</h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;">법정동은 정부에서 정한 공식적인 동의 기준으로, 부동산 관련 데이터에서 주로 사용됩니다. 행정동은 행정 구역을 기준으로 하며, 법정동과 행정동의 코드는 정부에서 사용하는 동일한 체계를 따릅니다. 예를 들어, 마포구 상암동의 법정동 코드는 &#8220;1144012700&#8221;입니다. 이 코드를 사용하여 해당 지역의 아파트 단지 정보를 조회할 수 있습니다.</p>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;">2. 법정동 코드 조회</h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;">법정동 코드는 정부의 행정표준코드관리시스템에서 확인할 수 있습니다. 이 시스템에서는 각 지역의 법정동 코드와 이름을 조회할 수 있으며, 필요한 정보를 쉽게 찾을 수 있습니다. 예를 들어, 마포구 상암동의 법정동 코드는 다음과 같이 확인할 수 있습니다:</p>
<ul style="list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;" data-ke-list-type="disc">
<li style="color: #000000;"><b>법정동 코드</b>: 1144012700</li>
<li style="color: #000000;"><b>법정동명</b>: 상암동</li>
</ul>
<p style="background-color: #ffffff; color: #000000; text-align: start;">이 정보를 바탕으로 아파트 단지 정보를 조회할 수 있습니다.</p>

<h2 style="background-color: #ffffff; color: #000000; text-align: start;">3. 필요한 라이브러리 설치</h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;">Python을 사용하여 네이버 부동산 API에 접근하기 위해서는 requests, json, pandas 라이브러리를 설치해야 합니다. 아래의 명령어를 사용하여 필요한 라이브러리를 설치할 수 있습니다.</p>
<div>
<pre class="hljs cmake" style="background-color: #1e1e1e; color: #dcdcdc;" contenteditable="false">pip <span class="hljs-keyword">install</span> requests pandas
</pre>
</div>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;">4. 아파트 단지 정보 조회 코드</h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;">이제 법정동 코드를 사용하여 아파트 단지 정보를 조회하는 코드를 작성해 보겠습니다. 아래는 마포구 상암동의 아파트 단지 정보를 조회하는 코드입니다.</p>
<div>
<pre class="hljs python" style="background-color: #1e1e1e; color: #dcdcdc;" contenteditable="false"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_apt_list</span><span class="hljs-params">(dong_code)</span>:</span>
    down_url = <span class="hljs-string">'https://new.land.naver.com/api/regions/complexes?cortarNo='</span> + dong_code + <span class="hljs-string">'&amp;realEstateType=APT&amp;order='</span>
    header = {
        <span class="hljs-string">"Accept-Encoding"</span>: <span class="hljs-string">"gzip"</span>,
        <span class="hljs-string">"Host"</span>: <span class="hljs-string">"new.land.naver.com"</span>,
        <span class="hljs-string">"Referer"</span>: <span class="hljs-string">"https://new.land.naver.com/complexes/102378?ms=37.5018495,127.0438028,16&amp;a=APT&amp;b=A1&amp;e=RETAIL"</span>,
        <span class="hljs-string">"Sec-Fetch-Dest"</span>: <span class="hljs-string">"empty"</span>,
        <span class="hljs-string">"Sec-Fetch-Mode"</span>: <span class="hljs-string">"cors"</span>,
        <span class="hljs-string">"Sec-Fetch-Site"</span>: <span class="hljs-string">"same-origin"</span>,
        <span class="hljs-string">"User-Agent"</span>: <span class="hljs-string">"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"</span>
    }
    r = requests.get(down_url, data={<span class="hljs-string">"sameAddressGroup"</span>: <span class="hljs-string">"false"</span>}, headers=header)

    r.encoding = <span class="hljs-string">"utf-8-sig"</span>
    temp = json.loads(r.text)
    <span class="hljs-keyword">try</span>:
        temp = pd.DataFrame(temp[<span class="hljs-string">'complexList'</span>])[[<span class="hljs-string">'complexNo'</span>, <span class="hljs-string">'complexName'</span>]]
    <span class="hljs-keyword">except</span>:
        temp = []
    <span class="hljs-keyword">return</span> temp

apt_list = get_apt_list(<span class="hljs-string">'1144012700'</span>)
print(apt_list)
</pre>
</div>
<h3 style="background-color: #ffffff; color: #000000; text-align: start;">코드 설명</h3>
<ol style="list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;" data-ke-list-type="decimal">
<li style="color: #000000;"><b>라이브러리 임포트</b>: requests, json, pandas 라이브러리를 임포트합니다.</li>
<li style="color: #000000;"><b>get_apt_list 함수 정의</b>: 이 함수는 법정동 코드를 입력받아 해당 지역의 아파트 단지 정보를 조회합니다.</li>
<li style="color: #000000;"><b>API 요청 URL 설정</b>: down_url 변수에 API 요청 URL을 설정합니다. 이 URL은 법정동 코드와 아파트 유형을 포함합니다.</li>
<li style="color: #000000;"><b>헤더 설정</b>: API 요청에 필요한 헤더를 설정합니다. 이 헤더는 요청의 출처를 명시하고, 브라우저에서 요청한 것처럼 보이게 합니다.</li>
<li style="color: #000000;"><b>API 요청 및 응답 처리</b>: requests.get 메서드를 사용하여 API에 GET 요청을 보냅니다. 응답을 JSON 형식으로 파싱하고, 아파트 단지 정보를 DataFrame으로 변환합니다.</li>
<li style="color: #000000;"><b>결과 출력</b>: apt_list 변수에 저장된 아파트 단지 정보를 출력합니다.</li>
</ol>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;">5. 실행 결과</h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;">위 코드를 실행하면 마포구 상암동에 위치한 아파트 단지의 이름과 고유 코드가 출력됩니다. 예를 들어, 다음과 같은 결과를 얻을 수 있습니다.</p>
<div>
<pre class="hljs angelscript" style="background-color: #1e1e1e; color: #dcdcdc;" contenteditable="false">   complexNo          complexName
<span class="hljs-number">0</span>   <span class="hljs-number">12345678</span>         상암동 아파트 <span class="hljs-number">1</span>단지
<span class="hljs-number">1</span>   <span class="hljs-number">23456789</span>         상암동 아파트 <span class="hljs-number">2</span>단지
...
</pre>
</div>
<p style="background-color: #ffffff; color: #000000; text-align: start;">이 결과는 상암동에 위치한 아파트 단지의 고유 코드와 이름을 포함하고 있습니다. 이를 통해 사용자는 특정 지역의 아파트 단지 정보를 쉽게 확인할 수 있습니다.</p>
<p><a href="https://2days.kr/15/09/07/56533/coding/data/">부동산 매물 정보 수집하기 &amp;#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</a></p>
<p><a href="https://2days.kr/15/09/08/56538/coding/data/">부동산 매물 정보 수집하기 &amp;#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</a></p>
<!-- CONTENT END 6 -->
]]></content:encoded>
					
		
		
		<media:content url="https://2days.kr/wp-content/uploads/2024/09/부동산-매물-정보-수집하기-부동산-데이터-네이버-부동산-크롤링-및-가공-3.png" medium="image"></media:content>
            	</item>
		<item>
		<title>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</title>
		<link>https://2days.kr/15/09/08/56538/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Sat, 14 Sep 2024 23:09:46 +0000</pubDate>
				<category><![CDATA[program]]></category>
		<category><![CDATA[부동산]]></category>
		<category><![CDATA[부동산 크롤링]]></category>
		<category><![CDATA[크롤링]]></category>
		<category><![CDATA[파이썬]]></category>
		<category><![CDATA[파이썬 크롤링]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=56538</guid>

					<description><![CDATA[부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2 ㅣ 현대 사회에서 데이터는 매우 중요한 자산입니다. 특히 부동산 시장에서는 아파트 단지에 대한 정보가 투자 결정에 큰 영향을 미치기 때문에, 이를 효율적으로 수집하는 방법이 필요합니다. 이번 포스트에서는 Python을 사용하여 아파트 단지 정보를 크롤링하는 방법에 대해 자세히 알아보겠습니다. 이 과정에서는 Naver의 부동산 API를 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2 ㅣ 현대 사회에서 데이터는 매우 중요한 자산입니다. 특히 부동산 시장에서는 아파트 단지에 대한 정보가 투자 결정에 큰 영향을 미치기 때문에, 이를 효율적으로 수집하는 방법이 필요합니다. 이번 포스트에서는 Python을 사용하여 아파트 단지 정보를 크롤링하는 방법에 대해 자세히 알아보겠습니다. 이 과정에서는 Naver의 부동산 API를 활용하여 세대수, 사용승인일, 평형별 면적 정보 등을 수집할 것입니다.</span></p>
<h3 style="background-color: #ffffff; color: #000000; text-align: start;" data-ke-size="size23"><span style="color: #000000;"><b>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</b></span></h3>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter">
<p><figure style="width: 2560px" class="wp-caption alignnone"><img loading="lazy" decoding="async" src="https://blog.kakaocdn.net/dn/bHLFUO/btsJDRrpjuV/2IEGJMM9ZuuOlAuuSAgdK1/img.png" alt="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #2" width="2560" height="2560" data-origin-width="2560" data-origin-height="2560" data-is-animation="false" data-filename="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공.png" data-origin- title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #2 15"><figcaption class="wp-caption-text">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #2</figcaption></figure><figcaption>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공</figcaption></figure><div class='code-block code-block-2' style='margin: 8px auto; text-align: center; display: block; clear: both;'>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8940400388075870"
     crossorigin="anonymous"></script>
<!-- 중간 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-8940400388075870"
     data-ad-slot="8794586137"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>

<p>&nbsp;</p>
<p><span style="background-color: #ffffff; color: #000000; text-align: start;">오늘 시리즈는 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 편입니다. 아직 1편을 못 보신 분들이라면 1편을 먼저 읽고 오시는게 도움이 되실 수 있습니다.</span></p>
<p><span style="color: #000000;"><a style="color: #000000;" href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%EB%A7%A4%EB%AC%BC-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91%ED%95%98%EA%B8%B0-%EB%B6%80%EB%8F%99%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EB%8F%99%EC%82%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EB%B0%8F-%EA%B0%80%EA%B3%B5-1" target="_blank" rel="noopener">2024.09.15 &#8211; [부동산/자동화 프로젝트] &#8211; 부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</a></span></p>
<p>&nbsp;</p>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">1. 크롤링의 필요성</span></h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">부동산 시장은 끊임없이 변화하고 있으며, 이에 따라 아파트 단지에 대한 정보도 지속적으로 업데이트됩니다. 투자자, 구매자, 임대인 등 다양한 이해관계자들은 이러한 정보를 신속하게 파악해야 합니다. 하지만 수작업으로 정보를 수집하는 것은 시간과 노력이 많이 소요되므로, 자동화된 방법이 필요합니다. Python은 이러한 작업을 수행하기에 적합한 언어로, 다양한 라이브러리를 통해 웹 크롤링을 쉽게 구현할 수 있습니다.</span></p>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">2. 필요한 라이브러리 설치</span></h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">Python을 사용하여 웹 크롤링을 수행하기 위해서는 몇 가지 라이브러리를 설치해야 합니다. 주로 사용되는 라이브러리는 requests, BeautifulSoup, 그리고 json입니다. 아래의 명령어를 사용하여 필요한 라이브러리를 설치할 수 있습니다.</span></p>
<div>
<pre class="hljs mipsasm" style="background-color: #1e1e1e; color: #dcdcdc;" contenteditable="false">pip <span class="hljs-keyword">install </span>requests <span class="hljs-keyword">beautifulsoup4 </span>pandas
</pre>
</div>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">3. API 요청을 위한 기본 설정</span></h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">Naver의 부동산 API를 사용하여 아파트 단지 정보를 요청하기 위해서는 API의 URL과 요청 헤더를 설정해야 합니다. 아래는 기본적인 설정 코드입니다.</span></p>
<div>
<pre class="hljs pgsql" style="background-color: #1e1e1e; color: #dcdcdc;" contenteditable="false"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> <span class="hljs-type">json</span>
<span class="hljs-keyword">from</span> bs4 <span class="hljs-keyword">import</span> BeautifulSoup

url = "https://new.land.naver.com/api/complexes/overview/"
param = {
    <span class="hljs-string">'complexNo'</span>: <span class="hljs-string">'23620'</span>  # 조회할 아파트 단지 번호
}
<span class="hljs-keyword">header</span> = {
    <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.220 Whale/1.3.51.7 Safari/537.36'</span>,
    <span class="hljs-string">'Referer'</span>: <span class="hljs-string">'https://m.land.naver.com/'</span>
}
</pre>
</div>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">위 코드에서 complexNo는 조회하고자 하는 아파트 단지의 고유 번호입니다. 이 번호는 Naver 부동산 사이트에서 각 단지의 URL을 통해 확인할 수 있습니다.</span></p>
<h2 style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">4. 아파트 단지 정보 요청</span></h2>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">이제 설정한 URL과 헤더를 사용하여 API에 GET 요청을 보내고, 응답을 받아 아파트 단지 정보를 추출해 보겠습니다.</span></p>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;">먼저 단지를 추출할 수 있는 request 주소를 한번 살펴 보겠습니다.</span></p>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000; text-align: left;">아래 캡쳐 화면은 단지 정보를 보여주는 링크를 Postman으로 Request 문과 호출 결과를 조회한 화면입니다. 화면에서 붉은색 상자는 링크를 입력하는 곳이며, 파란색 상자는 Python Request문을 생성해 줍니다. 그리고 초록색 상자는 해당 Requst 호출의 결과를 보기쉽게 보여줍니다. 주의할 점은 생성된 Request 문의 header 값을 추가해주어야지 Naver 사이트에서 원하는 결과값을 얻을 수 있습니다. 아래 코드에 해당 header 값이 있습니다.</span></p>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000; text-align: left;">먼저 Postman을 접속해서 해당 주소를 검색해보겠습니다.</span></p>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000; text-align: left;"><a style="color: #000000;" href="https://www.postman.com/" target="_blank" rel="noopener noreferrer noopener">https://www.postman.com/</a></span></p>
<p style="background-color: #ffffff; color: #000000; text-align: start;"><span style="color: #000000;"><a style="color: #000000;" href="https://new.land.naver.com/api/complexes/overview/23620?complexNo=23620" target="_blank" rel="noopener">https://new.land.naver.com/api/complexes/overview/23620?complexNo=23620</a></span></p>
<div id="SE-737c04ad-8844-4600-9ed2-b5c89df5c568" style="background-color: #f7f7f7; color: #777777; text-align: left;">
<div>
<div>
<div>
<figure data-ke-type="image" data-ke-style="alignCenter" data-ke-mobilestyle="widthOrigin"><img decoding="async" src="https://blog.kakaocdn.net/dn/bmdd7n/btsJEo3g7M8/VDP8LBLhLaf3HemQ9k37dk/img.png" data-height="736" data-width="886" data-lazy-src="" data-origin-width="966" data-origin-height="804" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #2 16"></figure>
</div>
</div>
</div>
</div>
<p><span style="background-color: #ffffff; color: #000000; text-align: left;">Postman을 통해 보여지는 단지 정보의 key와 value입니다.</span></p>
<figure data-ke-type="image" data-ke-style="alignLeft" data-ke-mobilestyle="widthOrigin"><img decoding="async" src="https://blog.kakaocdn.net/dn/bCQ9LM/btsJDWMPD4W/a0ojq1Eta45UlWpihBsRwK/img.jpg" data-height="640" data-width="298" data-lazy-src="" data-origin-width="298" data-origin-height="640" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #2 17"></figure>
<p><span style="color: #000000;">Request 정보를 토대로 아래와 같이 코드를 작성해봅니다.</span></p>
<pre id="code_1726353123879" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import requests
import json
import pandas as pd
import requests
from bs4 import BeautifulSoup

url = <span class="hljs-string">"https://new.land.naver.com/api/complexes/overview/"</span>

param = {
    <span class="hljs-string">'complexNo'</span>: <span class="hljs-string">'23620'</span>
}
header = {
    <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.220 Whale/1.3.51.7 Safari/537.36'</span>,
    <span class="hljs-string">'Referer'</span>: <span class="hljs-string">'https://m.land.naver.com/'</span>
}
payload = {}

response = requests.request(<span class="hljs-string">"GET"</span>, url+param[<span class="hljs-string">'complexNo'</span>], params=param, headers=header, data=payload)
u = response.url
temp = json.loads(response.text)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"\n\n단지명: %s 사용승인일: %s  세대수: %s \n"</span> \
      %(temp[<span class="hljs-string">'complexName'</span>], temp[<span class="hljs-string">'useApproveYmd'</span>], temp[<span class="hljs-string">'totalHouseHoldCount'</span>]))

<span class="hljs-comment"># 추가 정보 조회</span>
url2 = <span class="hljs-string">"https://m.land.naver.com/complex/info/"</span>+ param[<span class="hljs-string">'complexNo'</span>] + <span class="hljs-string">"?ptpNo=1"</span>
response2 = requests.request(<span class="hljs-string">"GET"</span>, url2, headers=header, data=payload)
doc = BeautifulSoup(response2.text, <span class="hljs-string">'html.parser'</span>)

titles = doc.find_all(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'tit'</span>)
datas = doc.find_all(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'data'</span>)
tmp = dict()
<span class="hljs-keyword">for</span> title, data <span class="hljs-keyword">in</span> zip(titles, datas):
       tmp.setdefault(title.text, data.text.replace(<span class="hljs-string">"\n"</span>, <span class="hljs-string">""</span>).strip())
<span class="hljs-built_in">print</span>(<span class="hljs-string">"용적률: "</span> + tmp[<span class="hljs-string">'용적률'</span>] + <span class="hljs-string">" 건폐율: "</span> + tmp[<span class="hljs-string">'건폐율'</span>])

<span class="hljs-comment"># 평형 별 정보 조회</span>
temp2 = temp[<span class="hljs-string">'pyeongs'</span>]
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> temp2:
     <span class="hljs-built_in">print</span>(<span class="hljs-string">"분양: %6s m^2 [ %-5s] 전용: %5s m^2(%5s 평)"</span> \
           %(item[<span class="hljs-string">'supplyArea'</span>], item[<span class="hljs-string">'pyeongName2'</span>], item[<span class="hljs-string">'exclusiveArea'</span>], item[<span class="hljs-string">'exclusivePyeong'</span>]))</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">필요한 라이브러리 불러오기</span></h3>
<pre id="code_1726353680744" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import requests
import json
import pandas as pd
from bs4 import BeautifulSoup</pre>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">requests: HTTP 요청을 보내고 응답을 받기 위해 사용됩니다.</span></li>
<li><span style="color: #000000;">json: API에서 받은 JSON 데이터를 처리하는 데 사용됩니다.</span></li>
<li><span style="color: #000000;">pandas: 데이터 처리를 용이하게 하기 위한 라이브러리. 현재 코드에서는 사용되지 않았지만 나중에 데이터를 처리할 때 유용합니다.</span></li>
<li><span style="color: #000000;">BeautifulSoup: HTML을 파싱하고 필요한 정보를 추출하기 위해 사용됩니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">API URL과 요청 매개변수 설정</span></h3>
<pre id="code_1726353700028" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">url = <span class="hljs-string">"https://new.land.naver.com/api/complexes/overview/"</span>

param = {
    <span class="hljs-string">'complexNo'</span>: <span class="hljs-string">'23620'</span>
}</pre>
<div style="background-color: #000000;"></div>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">url: 네이버 부동산 API의 단지 정보에 접근하는 URL입니다.</span></li>
<li><span style="color: #000000;">param: 조회하려는 특정 아파트 단지의 고유번호가 담긴 파라미터로, &#8216;23620&#8217;은 &#8220;상암월드컵파크 4단지&#8221;를 나타냅니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">요청 헤더 설정</span></h3>
<pre id="code_1726353742027" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">header = {
    <span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.220 Whale/1.3.51.7 Safari/537.36'</span>,
    <span class="hljs-string">'Referer'</span>: <span class="hljs-string">'https://m.land.naver.com/'</span>
}</pre>
<div style="background-color: #000000;"></div>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">User-Agent: 웹사이트에서 요청을 받을 때 어떤 브라우저로 접근하는지 인식하는 값입니다. 웹 서버에서 비정상적인 접근을 차단하는 경우가 있어, 이 값을 설정하여 사람처럼 보이도록 합니다.</span></li>
<li><span style="color: #000000;">Referer: API 요청을 네이버 모바일 부동산 사이트에서 온 것처럼 보이게 만듭니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">단지 정보 요청 및 출력</span></h3>
<pre id="code_1726353760546" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">response = requests.request(<span class="hljs-string">"GET"</span>, url + param[<span class="hljs-string">'complexNo'</span>], params=param, headers=header, data={})
temp = json.loads(response.text)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"\n\n단지명: %s 사용승인일: %s  세대수: %s \n"</span> \
      %(temp[<span class="hljs-string">'complexName'</span>], temp[<span class="hljs-string">'useApproveYmd'</span>], temp[<span class="hljs-string">'totalHouseHoldCount'</span>]))</pre>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">requests.request(&#8220;GET&#8221;, &#8230;): GET 요청을 통해 API로부터 데이터를 가져옵니다.</span></li>
<li><span style="color: #000000;">json.loads(response.text): API 응답을 JSON 형식으로 변환합니다.</span></li>
<li><span style="color: #000000;">print: 단지명, 사용승인일, 세대수를 출력합니다. 각각 temp에서 추출된 정보입니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">추가 단지 정보 요청</span></h3>
<pre id="code_1726353790947" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">url2 = <span class="hljs-string">"https://m.land.naver.com/complex/info/"</span>+ param[<span class="hljs-string">'complexNo'</span>] + <span class="hljs-string">"?ptpNo=1"</span>
response2 = requests.request(<span class="hljs-string">"GET"</span>, url2, headers=header, data={})
doc = BeautifulSoup(response2.text, <span class="hljs-string">'html.parser'</span>)</pre>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">url2: 네이버 모바일 부동산 웹페이지에서 해당 단지에 대한 추가 정보를 가져오는 URL입니다.</span></li>
<li><span style="color: #000000;">BeautifulSoup: HTML 응답을 파싱하여 필요한 정보를 쉽게 추출할 수 있도록 합니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">용적률, 건폐율 추출</span></h3>
<pre id="code_1726353811914" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">titles = doc.find_all(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'tit'</span>)
datas = doc.find_all(<span class="hljs-string">'span'</span>, class_=<span class="hljs-string">'data'</span>)
tmp = dict()
<span class="hljs-keyword">for</span> title, data <span class="hljs-keyword">in</span> zip(titles, datas):
    tmp.setdefault(title.text, data.text.replace(<span class="hljs-string">"\n"</span>, <span class="hljs-string">""</span>).strip())
<span class="hljs-built_in">print</span>(<span class="hljs-string">"용적률: "</span> + tmp[<span class="hljs-string">'용적률'</span>] + <span class="hljs-string">" 건폐율: "</span> + tmp[<span class="hljs-string">'건폐율'</span>])</pre>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">doc.find_all(&#8216;span&#8217;, class_=&#8217;tit&#8217;): HTML에서 &#8216;span&#8217; 태그 중 클래스가 &#8216;tit&#8217;인 모든 요소를 찾습니다. 이는 제목(용적률, 건폐율 등)에 해당합니다.</span></li>
<li><span style="color: #000000;">zip: titles와 datas를 한 쌍으로 묶어 딕셔너리에 저장합니다.</span></li>
<li><span style="color: #000000;">print: 용적률과 건폐율을 출력합니다.</span></li>
</ul>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;"><span style="color: #000000;">7. 평형별 정보 조회</span></h3>
<pre id="code_1726353824243" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">temp2 = temp[<span class="hljs-string">'pyeongs'</span>]
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> temp2:
     <span class="hljs-built_in">print</span>(<span class="hljs-string">"분양: %6s m^2 [ %-5s] 전용: %5s m^2(%5s 평)"</span> \
           %(item[<span class="hljs-string">'supplyArea'</span>], item[<span class="hljs-string">'pyeongName2'</span>], item[<span class="hljs-string">'exclusiveArea'</span>], item[<span class="hljs-string">'exclusivePyeong'</span>]))</pre>
<ul style="list-style-type: disc; background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-list-type="disc">
<li><span style="color: #000000;">temp2 = temp[&#8216;pyeongs&#8217;]: 단지 정보에서 평형별 데이터를 추출합니다.</span></li>
<li><span style="color: #000000;">for item in temp2: 각 평형의 정보를 순회하며 분양 면적과 전용 면적을 출력합니다.</span></li>
</ul>
<p><a href="https://2days.kr/15/09/07/56533/coding/data/">부동산 매물 정보 수집하기 &amp;#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</a></p>
<!-- CONTENT END 8 -->
]]></content:encoded>
					
		
		
		<media:content url="https://2days.kr/wp-content/uploads/2024/09/부동산-매물-정보-수집하기-부동산-데이터-네이버-부동산-크롤링-및-가공.png" medium="image"></media:content>
            	</item>
	</channel>
</rss>
