<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	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%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:17:38 +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>네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기</title>
		<link>https://2days.kr/13/10/15/59728/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Sun, 13 Oct 2024 06:05:25 +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>
		<category><![CDATA[크롤링]]></category>
		<category><![CDATA[한번에]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=59728</guid>

					<description><![CDATA[네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기 ㅣ 네이버 카페 유용한 글 및 첨부파일을 보다보면 한번에 자동으로 다운 받고 싶은 경우가 생깁니다. 물론 상업적으로 사용하지 않는다고 해서 이 모든 것이 불법적인 행동이 안된다는 것은 아니지만 몇개의 파일을 다운 받을 때 하나하나 직접 다운 받는 것은 굉장히 피곤한 일입니다. 그래서 오늘은 이 네이버 카페 게시판 글 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기 ㅣ 네이버 카페 유용한 글 및 첨부파일을 보다보면 한번에 자동으로 다운 받고 싶은 경우가 생깁니다. 물론 상업적으로 사용하지 않는다고 해서 이 모든 것이 불법적인 행동이 안된다는 것은 아니지만 몇개의 파일을 다운 받을 때 하나하나 직접 다운 받는 것은 굉장히 피곤한 일입니다. 그래서 오늘은 이 네이버 카페 게시판 글 및 첨부파일을 모두 다운 받는 프로그램을 하나 만들어 볼까 생각했습니다.</p>
<p>어렵지 않으니 하나씩 따라 하시면 여러분도 금방 코드를 짤 수 있을 것 같습니다. 동적 네트워크를 사용해야 하므로 오늘은 코랩이 아니라 직접 로컬 컴퓨터에서 실행하도록 하겠습니다.</p>
<p>제 블로그 글에도 로컬 컴퓨터 세팅하는 글을 작성했었으니 여러분도 아래 글을 읽어 보시고 준비가 되면 다음 단계로 넘어 오시는 것을 추천드립니다.</p>
<h2 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기</h2>
<p><a href="https://aboda.kr/entry/%EB%B6%80%EB%8F%99%EC%82%B0-%ED%86%B5%EA%B3%84-%EC%9E%90%EB%A3%8C-%EB%82%B4%EA%B0%80-%EB%A7%8C%EB%93%A4%EA%B9%8C-%EA%B0%9C%EC%9A%94" target="_blank" rel="noopener">2023.06.30 &#8211; [부동산] &#8211; 부동산 통계 자료 내가 만들까? (개요)</a></p>
<figure data-ke-type="image" data-ke-mobilestyle="widthOrigin" data-ke-style="alignCenter">
<p><figure style="width: 800px" class="wp-caption alignnone"><img post-id="59728" fifu-featured="1" fetchpriority="high" decoding="async" src="https://blog.kakaocdn.net/dn/Efyi4/btsJ3QTviGE/Lz344yLSvhvOnMYdG9gV0k/img.png" alt="네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기" title="네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기" width="800" height="800" data-is-animation="false" data-origin-width="800" data-origin-height="800" data-filename="title_image.png" data-origin- title="네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기 1"><figcaption class="wp-caption-text">네이버카페 게시판 글 첨부파일 크롤링 한번에 다운받기</figcaption></figure><figcaption>네이버 카페 게시판 글 첨부파일 크롤링 한번에 다운받기</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>이번 포스트에서는 웹 스크래핑을 통해 데이터를 수집하고 Google Sheets 및 Google Drive에 저장하는 Python 스크립트를 단계별로 설명하겠습니다. 이 스크립트는 Selenium을 이용하여 네이버 카페에서 정보를 수집하고, Google API를 통해 데이터를 저장하는 기능을 갖추고 있습니다.</p>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">1단계: 필요한 라이브러리 임포트</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">스크립트의 시작 부분에서는 필요한 라이브러리를 임포트합니다. 여기에는 웹 드라이버 제어를 위한 selenium, HTTP 요청을 위한 requests, Google API에 접근하기 위한 라이브러리 등이 포함됩니다.</p>
<pre id="code_1728798404950" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import time
import os
import platform
import subprocess
import requests
import re
import urllib.parse
import traceback
from datetime import datetime
from tqdm import tqdm
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload</pre>
<p>먼저 관련 모듈을 임포트 합니다. 저는 구글 드라이브에 다운을 자동으로 받을 수 있도록 했습니다. 제 로컬 컴퓨터에 저장을 한 후 구글 드라이브에 저장이 되면 제 로컬 컴퓨터에서는 파일이 자동 삭제가 됩니다. 따라서 코드가 조금 지저분하고 길게 되어버렸습니다.</p>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">2단계: 시스템 아키텍처 확인</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">ARM 아키텍처인지 확인합니다. 이 부분은 ChromeDriver의 경로 설정에서 ARM을 지원하기 위한 조건문으로 사용됩니다.</p>
<pre id="code_1728798496108" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">is_arm = platform.machine().startswith(<span class="hljs-string">'arm'</span>)</pre>
<p>저는 개발 환경이 맥북입니다.</p>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">3단계: Google Sheets 및 Drive API 설정</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">Google API를 사용하기 위해 인증 정보를 설정합니다. g1.json 파일을 통해 Google API에 접근할 수 있는 자격증명을 가져옵니다.</p>
<pre id="code_1728798554810" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">SCOPES = [<span class="hljs-string">'https://www.googleapis.com/auth/spreadsheets'</span>, <span class="hljs-string">'https://www.googleapis.com/auth/drive.file'</span>]
creds = Credentials.from_service_account_file(<span class="hljs-string">'g1.json'</span>, scopes=SCOPES)
sheets_service = build(<span class="hljs-string">'sheets'</span>, <span class="hljs-string">'v4'</span>, credentials=creds)
drive_service = build(<span class="hljs-string">'drive'</span>, <span class="hljs-string">'v3'</span>, credentials=creds)</pre>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">또한 구글시트에 내가 다운 받은 목록을 리스트화 할 생각입니다.</p>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">4단계: Chrome WebDriver 옵션 설정</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">Chrome WebDriver를 설정하는 함수입니다. ARM 아키텍처일 경우 추가적인 인자를 설정합니다.</p>
<pre id="code_1728798606276" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def set_chrome_options(is_arm):
    options = webdriver.ChromeOptions()
    options.add_argument(<span class="hljs-string">"--start-maximized"</span>)
    options.add_argument(<span class="hljs-string">"--disable-extensions"</span>)
    options.add_argument(<span class="hljs-string">"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36"</span>)
    
    <span class="hljs-keyword">if</span> is_arm:
        options.add_argument(<span class="hljs-string">'--no-sandbox'</span>)
        options.add_argument(<span class="hljs-string">'--disable-dev-shm-usage'</span>)

    <span class="hljs-built_in">return</span> options</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">5단계: ChromeDriver 서비스 설정</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">ChromeDriver의 경로를 설정하고 서비스를 생성하는 함수입니다. ARM 아키텍처에 맞춰 ChromeDriver를 설치하는 과정을 포함하고 있습니다.</p>
<pre id="code_1728798628659" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def get_chromedriver_service(is_arm):
    try:
        <span class="hljs-keyword">if</span> is_arm:
            home = os.path.expanduser(<span class="hljs-string">"~"</span>)
            chromedriver_path = f<span class="hljs-string">"{home}/chromedriver"</span>
            <span class="hljs-keyword">if</span> not os.path.exists(chromedriver_path):
                <span class="hljs-built_in">print</span>(<span class="hljs-string">"ChromeDriver for ARM Mac not found. Downloading..."</span>)
                subprocess.run([<span class="hljs-string">"brew"</span>, <span class="hljs-string">"install"</span>, <span class="hljs-string">"chromedriver"</span>])
                subprocess.run([<span class="hljs-string">"xattr"</span>, <span class="hljs-string">"-d"</span>, <span class="hljs-string">"com.apple.quarantine"</span>, <span class="hljs-string">"/usr/local/bin/chromedriver"</span>])
            service = Service(<span class="hljs-string">"/opt/homebrew/bin/chromedriver"</span>)
        <span class="hljs-keyword">else</span>:
            service = Service(ChromeDriverManager().install())
        <span class="hljs-built_in">return</span> service
    except Exception as e:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error setting up ChromeDriver: {e}"</span>)
        raise</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">6단계: WebDriver 초기화</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">WebDriver를 초기화하고 Chrome 브라우저를 실행하는 함수입니다.</p>
<pre id="code_1728798647510" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def init_webdriver():
    service = get_chromedriver_service(is_arm)
    options = set_chrome_options(is_arm)
    driver = webdriver.Chrome(service=service, options=options)
    <span class="hljs-built_in">return</span> driver</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">7단계:네이버카페 게시판 첨부파일 다운로드 함수</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">특정 게시물에서 첨부파일을 다운로드하는 함수입니다. 두 가지 방법을 통해 파일을 찾고, 요청을 보내서 다운로드합니다.</p>
<pre id="code_1728798683874" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def download_attachments(driver):
    try:
        files = driver.find_elements(By.CSS_SELECTOR, <span class="hljs-string">"li.AttachFileListItem"</span>)

        <span class="hljs-keyword">if</span> not files:
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"첫 번째 방법으로 첨부파일을 찾지 못했습니다. 두 번째 방법을 시도합니다."</span>)
            <span class="hljs-comment"># 두 번째 방법: 새로운 방식</span>
            file_button = driver.find_element(By.CSS_SELECTOR, <span class="hljs-string">"#app &gt; div &gt; div &gt; div.ArticleContentBox &gt; div.article_container &gt; div.AttachFileList &gt; div.attach_file &gt; a"</span>)
            file_button.click()

            download_link = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, <span class="hljs-string">"a[role='button'][download].file_menu"</span>))
            )
            file_url = download_link.get_attribute(<span class="hljs-string">'href'</span>)

            file_name = os.path.basename(urllib.parse.unquote(file_url.split(<span class="hljs-string">'?'</span>)[0]))

            <span class="hljs-comment"># 다운로드 진행</span>
            cookies = driver.get_cookies()
            session = requests.Session()
            <span class="hljs-keyword">for</span> cookie <span class="hljs-keyword">in</span> cookies:
                session.cookies.set(cookie[<span class="hljs-string">'name'</span>], cookie[<span class="hljs-string">'value'</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/85.0.4183.121 Safari/537.36'</span>
            }

            response = session.get(file_url, headers=headers, allow_redirects=True)
            <span class="hljs-keyword">if</span> response.status_code == 200:
                download_dir = <span class="hljs-string">"/Users/사용자/Downloads"</span>
                <span class="hljs-keyword">if</span> not os.path.exists(download_dir):
                    os.makedirs(download_dir)

                save_path = os.path.join(download_dir, file_name)
                with open(save_path, <span class="hljs-string">'wb'</span>) as f:
                    f.write(response.content)
                <span class="hljs-built_in">print</span>(f<span class="hljs-string">"첨부파일 저장 완료: {save_path}"</span>)
                <span class="hljs-built_in">return</span> save_path
            <span class="hljs-keyword">else</span>:
                <span class="hljs-built_in">print</span>(f<span class="hljs-string">"파일 다운로드 실패: {response.status_code}"</span>)
                <span class="hljs-built_in">return</span> None

        <span class="hljs-comment"># 첫 번째 방법으로 진행</span>
        cookies = driver.get_cookies()
        session = requests.Session()
        <span class="hljs-keyword">for</span> cookie <span class="hljs-keyword">in</span> cookies:
            session.cookies.set(cookie[<span class="hljs-string">'name'</span>], cookie[<span class="hljs-string">'value'</span>])

        download_dir = <span class="hljs-string">"/Users/사용자/Downloads"</span>
        <span class="hljs-keyword">if</span> not os.path.exists(download_dir):
            os.makedirs(download_dir)

        <span class="hljs-keyword">for</span> idx, file <span class="hljs-keyword">in</span> enumerate(files):
            download_link = file.find_element(By.CSS_SELECTOR, <span class="hljs-string">"a.file_menu"</span>)
            file_url = download_link.get_attribute(<span class="hljs-string">'href'</span>)
            <span class="hljs-built_in">print</span>(f<span class="hljs-string">"다운로드 링크: {file_url}"</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/85.0.4183.121 Safari/537.36'</span>
            }

            response = session.get(file_url, headers=headers, allow_redirects=True)
            <span class="hljs-keyword">if</span> response.status_code == 200:
                content_disposition = response.headers.get(<span class="hljs-string">'Content-Disposition'</span>, <span class="hljs-string">''</span>)
                file_name = <span class="hljs-string">''</span>
                <span class="hljs-keyword">if</span> content_disposition:
                    file_name_match = re.search(r<span class="hljs-string">'filename[^;=\n]*=(([\'</span><span class="hljs-string">"]).*?\2|[^;\n]*)', content_disposition)
                    if file_name_match:
                        file_name = file_name_match.group(1).strip('"</span><span class="hljs-string">')

                if not file_name:
                    file_name = os.path.basename(urllib.parse.unquote(file_url.split('</span>?<span class="hljs-string">')[0]))

                if not file_name:
                    file_extension = file_url.split(".")[-1].split("?")[0]
                    file_name = f"attachment_{idx + 1}.{file_extension}"

                save_path = os.path.join(download_dir, file_name)

                with open(save_path, '</span>wb<span class="hljs-string">') as f:
                    f.write(response.content)
                print(f"첨부파일 {idx + 1}번째 저장 완료: {save_path}")

                return save_path
            else:
                print(f"파일 다운로드 실패: {response.status_code}")

    except Exception as e:
        print(f"첨부파일 다운로드 중 오류 발생: {str(e)}")
        traceback.print_exc()

    return None</span></pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">8단계: 네이버카페 게시판 Google Drive에 파일 업로드 함수</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">다운로드한 파일을 Google Drive에 업로드하는 함수입니다. 업로드 후 로컬 파일을 삭제하는 기능도 포함되어 있습니다.</p>
<pre id="code_1728798773987" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def upload_to_google_drive(file_path, file_name):
    folder_id = <span class="hljs-string">'구글시트ID'</span>  <span class="hljs-comment"># bee 폴더의 ID</span>
    file_metadata = {
        <span class="hljs-string">'name'</span>: file_name,
        <span class="hljs-string">'parents'</span>: [folder_id]
    }
    media = MediaFileUpload(file_path, resumable=True)

    file = drive_service.files().create(
        body=file_metadata,
        media_body=media,
        fields=<span class="hljs-string">'id, webViewLink'</span>
    ).execute()
    <span class="hljs-built_in">print</span>(f<span class="hljs-string">"File ID: {file.get('id')}"</span>)

    <span class="hljs-comment"># 업로드가 성공적으로 완료되었을 경우 로컬 파일 삭제</span>
    <span class="hljs-keyword">if</span> file.get(<span class="hljs-string">'id'</span>):
        try:
            os.remove(file_path)
            <span class="hljs-built_in">print</span>(f<span class="hljs-string">"로컬 파일 삭제 완료: {file_path}"</span>)
        except Exception as e:
            <span class="hljs-built_in">print</span>(f<span class="hljs-string">"로컬 파일 삭제 중 오류 발생: {e}"</span>)

    <span class="hljs-built_in">return</span> file</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">9단계: 네이버카페 게시판 데이터 수집 함수</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">웹 스크래핑을 통해 게시물의 제목과 내용을 수집하는 함수입니다. Selenium을 사용하여 특정 요소를 찾고 데이터를 추출합니다.</p>
<pre id="code_1728798804223" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def scrape_post_data(driver):
    post_title = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, <span class="hljs-string">'h3.title'</span>))
    ).text

    post_content = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, <span class="hljs-string">'.article_body'</span>))
    ).text

    <span class="hljs-built_in">return</span> post_title, post_content</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">10단계: Google Sheets에 데이터 저장 함수</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">수집한 게시물 제목과 내용을 Google Sheets에 저장하는 함수입니다. Google Sheets API를 사용하여 데이터를 작성합니다.</p>
<pre id="code_1728798828073" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def save_to_google_sheets(post_title, post_content):
    spreadsheet_id = <span class="hljs-string">'YOUR_SPREADSHEET_ID'</span>  <span class="hljs-comment"># 스프레드시트 ID</span>
    range_name = <span class="hljs-string">'Sheet1!A1:B1'</span>  <span class="hljs-comment"># 데이터를 입력할 범위</span>
    values = [[post_title, post_content]]  <span class="hljs-comment"># 입력할 데이터</span>

    body = {
        <span class="hljs-string">'values'</span>: values
    }

    result = sheets_service.spreadsheets().values().append(
        spreadsheetId=spreadsheet_id,
        range=range_name,
        valueInputOption=<span class="hljs-string">'RAW'</span>,
        body=body
    ).execute()

    <span class="hljs-built_in">print</span>(f<span class="hljs-string">"{result.get('updates').get('updatedCells')} cells appended."</span>)</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">11단계: 스크래핑 및 데이터 저장 메인 함수</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">전체 프로세스를 실행하는 메인 함수입니다. 게시물 URL을 통해 게시물 데이터를 수집하고, 첨부파일을 다운로드하며, 최종적으로 Google Sheets에 저장합니다.</p>
<pre id="code_1728798848760" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def main(post_url):
    driver = init_webdriver()
    try:
        driver.get(post_url)
        time.sleep(2)  <span class="hljs-comment"># 페이지 로딩 대기</span>

        <span class="hljs-comment"># 게시물 데이터 수집</span>
        post_title, post_content = scrape_post_data(driver)
        
        <span class="hljs-comment"># 첨부파일 다운로드</span>
        file_path = download_attachments(driver)
        <span class="hljs-keyword">if</span> file_path:
            <span class="hljs-comment"># 파일을 Google Drive에 업로드</span>
            upload_to_google_drive(file_path, os.path.basename(file_path))

        <span class="hljs-comment"># 수집한 데이터 Google Sheets에 저장</span>
        save_to_google_sheets(post_title, post_content)

    except Exception as e:
        <span class="hljs-built_in">print</span>(f<span class="hljs-string">"메인 함수에서 오류 발생: {str(e)}"</span>)
        traceback.print_exc()
    finally:
        driver.quit()</pre>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;">12단계: 네이버카페 게시판 스크립트 실행</h3>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">스크립트를 실행하기 위해 필요한 게시물 URL을 제공하고, 메인 함수를 호출합니다.</p>
<pre id="code_1728798869358" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock"><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    post_url = <span class="hljs-string">"https://cafe.naver.com/your_post_url"</span>  <span class="hljs-comment"># 게시물 URL</span>
    main(post_url)</pre>
<p>위 스크립트는 네이버 카페에서 게시물 데이터를 수집하고, 첨부파일을 다운로드한 후, Google Sheets와 Google Drive에 저장하는 전체 프로세스를 보여줍니다. 각 단계에서 데이터 수집과 저장을 위한 다양한 라이브러리를 활용하여 효율적인 작업 흐름을 구축했습니다. Python을 활용한 웹 스크래핑과 <a href="https://2days.kr/30/11/12/70250/aboda/">API</a> 연동을 통해 보다 자동화된 데이터 관리가 가능해지며, 이러한 방식은 업무의 효율성을 높이고 시간과 노력을 절약하는 데 기여할 수 있습니다</p>
<p><a href="https://2days.kr/01/10/14/59333/coding/python-coding/">파이썬 다나와 크롤링 제품 정보 모으기</a></p>
<p>전체 코드가 궁금하신가요?  전체 코드가 궁금하신 분들은 아래 다운링크를 열면 받으실 수 있습니다!</p>
<p style="text-align: center;"><strong><a href="https://colab.research.google.com/drive/15FxL-j-PfbXRqWNeVkzd69DGtqnyPGXs?usp=sharing" target="_blank" rel="noopener">전체코드 다운받기</a></strong></p>
<p>&nbsp;</p>
<!-- AI CONTENT END 2 -->
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>파이썬 다나와 크롤링 제품 정보 모으기</title>
		<link>https://2days.kr/01/10/14/59333/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 05:09:29 +0000</pubDate>
				<category><![CDATA[program]]></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=59333</guid>

					<description><![CDATA[파이썬 다나와 크롤링 하여 제품 정보를 모아보도록 하겠습니다. 파이썬 스크립트를 쓰고 스트림릿으로 올려서 쉽게 웹페이지에서 조회를 하면 쉽게 페이지 정보를 모을 수 있습니다. [주의] 해당 스크립트는 공부를 위한 학습 목적이므로 불법으로 사이트 정보를 모으거나 이용하는 행위는 불법 행동이 될 수 있습니다. 파이썬 다나와 크롤링 제품 정보 모으기 이 스크립트는 Streamlit을 이용해 웹페이지를 통해 제품 정보를 검색하고, 결과를 크롤링하여 보여주는 애플리케이션을 구현한 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p data-ke-size="size16">파이썬 다나와 크롤링 하여 제품 정보를 모아보도록 하겠습니다. 파이썬 스크립트를 쓰고 스트림릿으로 올려서 쉽게 웹페이지에서 조회를 하면 쉽게 페이지 정보를 모을 수 있습니다.</p>
<p data-ke-size="size16">[주의] 해당 스크립트는 공부를 위한 학습 목적이므로 불법으로 사이트 정보를 모으거나 이용하는 행위는 불법 행동이 될 수 있습니다.</p>
<h3 data-ke-size="size23">파이썬 다나와 크롤링 제품 정보 모으기</h3>
<figure data-ke-type="image" data-ke-style="alignCenter" data-ke-mobilestyle="widthOrigin"><img post-id="59333" fifu-featured="1" decoding="async" src="https://blog.kakaocdn.net/dn/wvxNz/btsJRdWjZkk/OXgzKkxNHFBx276xlOhEA0/img.png" alt="파이썬 다나와 크롤링 제품 정보 모으기" title="파이썬 다나와 크롤링 제품 정보 모으기" data-origin-width="2560" data-origin-height="2560" data-filename="파이썬 다나와 크롤링 제품 정보 모으기.png" data-is-animation="false" title="파이썬 다나와 크롤링 제품 정보 모으기 3"></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">이 스크립트는 <b>Streamlit</b>을 이용해 웹페이지를 통해 제품 정보를 검색하고, 결과를 크롤링하여 보여주는 애플리케이션을 구현한 것입니다. 스크립트의 주요 동작은 아래와 같습니다:</p>
<p data-ke-size="size16"><b>1. 필요한 모듈 임포트</b></p>
<pre id="code_1727758646354" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import streamlit as st
import requests
from bs4 import BeautifulSoup
import pandas as pd
import re
import time</pre>
<p data-ke-size="size16">• <b>Streamlit</b>: 웹 애플리케이션을 쉽게 만들 수 있는 프레임워크.</p>
<p data-ke-size="size16">• <b>requests</b>: 웹페이지에 HTTP 요청을 보내는 라이브러리.</p>
<p data-ke-size="size16">• <b>BeautifulSoup</b>: HTML 및 XML 데이터를 파싱하는 라이브러리.</p>
<p data-ke-size="size16">• <b>pandas</b>: 데이터 처리 및 분석을 위한 라이브러리.</p>
<p data-ke-size="size16">• <b>re, time</b>: 정규 표현식과 시간 관련 모듈.</p>
<p data-ke-size="size16"><b>2. get_page_content() 함수</b></p>
<pre id="code_1727758679522" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def get_page_content(search_query, page_num):
    url = f<span class="hljs-string">"https://search.danawa.com/dsearch.php?query={search_query}&amp;page={page_num}"</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/91.0.4472.124 Safari/537.36'</span>
    }
    response = requests.get(url, headers=headers)
    <span class="hljs-built_in">return</span> BeautifulSoup(response.content, <span class="hljs-string">'html.parser'</span>)</pre>
<p data-ke-size="size16">• <b>URL 생성</b>: 검색어와 페이지 번호를 기반으로 danawa.com의 검색 결과 페이지 URL을 생성합니다.</p>
<p data-ke-size="size16">• <b>HTTP 요청</b>: requests를 이용해 해당 페이지의 HTML을 요청합니다.</p>
<p data-ke-size="size16">• <b>BeautifulSoup 파싱</b>: 받은 HTML을 BeautifulSoup 객체로 변환하여 HTML 구조를 쉽게 탐색할 수 있도록 합니다.</p>
<p data-ke-size="size16"><b>3. crawl_product_info() 함수</b></p>
<pre id="code_1727758699552" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">def crawl_product_info(search_query):
    product_list = []
    <span class="hljs-comment"># 페이지 수 자동 계산</span>
    soup = get_page_content(search_query, 1)
    max_pages = int(soup.select_one(<span class="hljs-string">'div.paging_number_wrap'</span>).find_all(<span class="hljs-string">'a'</span>)[-1][<span class="hljs-string">'data-page'</span>])</pre>
<p data-ke-size="size16">• <b>페이지 수 자동 계산</b>: 첫 페이지를 가져와서 페이지네이션 정보를 확인하고, 최대 페이지 수를 계산합니다.</p>
<pre id="code_1727758730220" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">    <span class="hljs-comment"># 각 페이지에서 제품 정보 크롤링</span>
    <span class="hljs-keyword">for</span> page_num <span class="hljs-keyword">in</span> range(1, max_pages + 1):
        st.session_state.progress_bar.progress(page_num / max_pages)  <span class="hljs-comment"># 진행률 표시</span>
        soup = get_page_content(search_query, page_num)
        products = soup.select(<span class="hljs-string">'li.prod_item'</span>)</pre>
<p data-ke-size="size16">• <b>진행률 표시</b>: 각 페이지를 크롤링할 때마다 진행률 바를 업데이트합니다.</p>
<p data-ke-size="size16">• <b>제품 정보 탐색</b>: 각 페이지에서 li.prod_item 요소를 찾아서 제품 목록을 가져옵니다.</p>
<pre id="code_1727758751617" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">        <span class="hljs-keyword">for</span> product <span class="hljs-keyword">in</span> products:
            try:
                <span class="hljs-comment"># 업체명과 제품명 가져오기</span>
                name_tag = product.select_one(<span class="hljs-string">'p.prod_name a'</span>)
                full_name = name_tag.text.strip() <span class="hljs-keyword">if</span> name_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>
                업체명 = full_name.split()[0]  <span class="hljs-comment"># 공백 전까지 업체명 추출</span>
                제품명 = <span class="hljs-string">' '</span>.join(full_name.split()[1:])  <span class="hljs-comment"># 첫 공백 이후 제품명 추출</span></pre>
<p data-ke-size="size16">• <b>업체명과 제품명</b>: p.prod_name에서 제품명을 추출하고, 첫 단어는 업체명으로, 나머지는 제품명으로 저장합니다.</p>
<pre id="code_1727758779301" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">                <span class="hljs-comment"># 가격, 이미지, 링크, 추가 정보 등 가져오기</span>
                price_tag = product.select_one(<span class="hljs-string">'p.price_sect a strong'</span>)
                가격 = price_tag.text.strip() <span class="hljs-keyword">if</span> price_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                img_tag = product.select_one(<span class="hljs-string">'div.thumb_image a img'</span>)
                이미지_URL = img_tag[<span class="hljs-string">'src'</span>] <span class="hljs-keyword">if</span> img_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                link_tag = product.select_one(<span class="hljs-string">'div.thumb_image a'</span>)
                링크 = link_tag[<span class="hljs-string">'href'</span>] <span class="hljs-keyword">if</span> link_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                추가정보_tag = product.select_one(<span class="hljs-string">'div.spec_list'</span>)
                추가정보 = 추가정보_tag.text.strip() <span class="hljs-keyword">if</span> 추가정보_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                등록월_tag = product.select_one(<span class="hljs-string">'div.prod_sub_meta dl.meta_item.mt_date dd'</span>)
                등록월 = 등록월_tag.text.strip() <span class="hljs-keyword">if</span> 등록월_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                평점_tag = product.select_one(<span class="hljs-string">'div.star-single span.text__score'</span>)
                평점 = 평점_tag.text.strip() <span class="hljs-keyword">if</span> 평점_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                리뷰수_tag = product.select_one(<span class="hljs-string">'div.text__review span.text__number'</span>)
                리뷰수 = 리뷰수_tag.text.strip() <span class="hljs-keyword">if</span> 리뷰수_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span></pre>
<p data-ke-size="size16">• <b>가격, 이미지, 링크</b>: 각 요소에서 제품의 가격, 이미지 URL, 구매 링크를 가져옵니다.</p>
<p data-ke-size="size16">• <b>추가 정보, 등록월, 평점, 리뷰수</b>: 제품의 부가 정보, 등록 월, 사용자 평점, 리뷰 수를 추출합니다.</p>
<p data-ke-size="size16">아래 스크립트는 전체 스크립트입니다.</p>
<pre id="code_1727758537549" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import streamlit as st
import requests
from bs4 import BeautifulSoup
import pandas as pd
import re
import time

<span class="hljs-comment"># 페이지 컨텐츠를 받아오는 함수</span>
def get_page_content(search_query, page_num):
    url = f<span class="hljs-string">"https://search.danawa.com/dsearch.php?query={search_query}&amp;page={page_num}"</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/91.0.4472.124 Safari/537.36'</span>
    }
    response = requests.get(url, headers=headers)
    <span class="hljs-built_in">return</span> BeautifulSoup(response.content, <span class="hljs-string">'html.parser'</span>)

<span class="hljs-comment"># 제품 정보 크롤링 함수</span>
def crawl_product_info(search_query):
    product_list = []
    <span class="hljs-comment"># 페이지 수 자동 계산</span>
    soup = get_page_content(search_query, 1)
    max_pages = int(soup.select_one(<span class="hljs-string">'div.paging_number_wrap'</span>).find_all(<span class="hljs-string">'a'</span>)[-1][<span class="hljs-string">'data-page'</span>])

    <span class="hljs-comment"># 각 페이지에서 제품 정보 크롤링</span>
    <span class="hljs-keyword">for</span> page_num <span class="hljs-keyword">in</span> range(1, max_pages + 1):
        st.session_state.progress_bar.progress(page_num / max_pages)  <span class="hljs-comment"># 진행률 표시</span>
        soup = get_page_content(search_query, page_num)
        products = soup.select(<span class="hljs-string">'li.prod_item'</span>)

        <span class="hljs-keyword">for</span> product <span class="hljs-keyword">in</span> products:
            try:
                <span class="hljs-comment"># 업체명과 제품명 가져오기</span>
                name_tag = product.select_one(<span class="hljs-string">'p.prod_name a'</span>)
                full_name = name_tag.text.strip() <span class="hljs-keyword">if</span> name_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>
                업체명 = full_name.split()[0]  <span class="hljs-comment"># 공백 전까지 업체명 추출</span>
                제품명 = <span class="hljs-string">' '</span>.join(full_name.split()[1:])  <span class="hljs-comment"># 첫 공백 이후 제품명 추출</span>

                <span class="hljs-comment"># 가격 가져오기</span>
                price_tag = product.select_one(<span class="hljs-string">'p.price_sect a strong'</span>)
                가격 = price_tag.text.strip() <span class="hljs-keyword">if</span> price_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 이미지 URL 가져오기</span>
                img_tag = product.select_one(<span class="hljs-string">'div.thumb_image a img'</span>)
                이미지_URL = img_tag[<span class="hljs-string">'src'</span>] <span class="hljs-keyword">if</span> img_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 링크 가져오기</span>
                link_tag = product.select_one(<span class="hljs-string">'div.thumb_image a'</span>)
                링크 = link_tag[<span class="hljs-string">'href'</span>] <span class="hljs-keyword">if</span> link_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 추가 정보 가져오기</span>
                추가정보_tag = product.select_one(<span class="hljs-string">'div.spec_list'</span>)
                추가정보 = 추가정보_tag.text.strip() <span class="hljs-keyword">if</span> 추가정보_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 등록월 가져오기</span>
                등록월_tag = product.select_one(<span class="hljs-string">'div.prod_sub_meta dl.meta_item.mt_date dd'</span>)
                등록월 = 등록월_tag.text.strip() <span class="hljs-keyword">if</span> 등록월_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 평점 가져오기</span>
                평점_tag = product.select_one(<span class="hljs-string">'div.star-single span.text__score'</span>)
                평점 = 평점_tag.text.strip() <span class="hljs-keyword">if</span> 평점_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 리뷰 수 가져오기</span>
                리뷰수_tag = product.select_one(<span class="hljs-string">'div.text__review span.text__number'</span>)
                리뷰수 = 리뷰수_tag.text.strip() <span class="hljs-keyword">if</span> 리뷰수_tag <span class="hljs-keyword">else</span> <span class="hljs-string">'정보 없음'</span>

                <span class="hljs-comment"># 데이터 저장</span>
                product_list.append({
                    <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>: 이미지_URL,
                    <span class="hljs-string">'링크'</span>: 링크,
                    <span class="hljs-string">'평점'</span>: 평점,
                    <span class="hljs-string">'리뷰수'</span>: 리뷰수,
                    <span class="hljs-string">'등록월'</span>: 등록월
                })

            except Exception as e:
                <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Error processing product: {e}"</span>)

    <span class="hljs-built_in">return</span> product_list

<span class="hljs-comment"># Streamlit 애플리케이션 설정</span>
st.set_page_config(layout=<span class="hljs-string">"wide"</span>)

<span class="hljs-comment"># 왼쪽 옵션 패널 만들기</span>
with st.sidebar:
    st.title(<span class="hljs-string">"검색 옵션"</span>)
    search_query = st.text_input(<span class="hljs-string">"검색어 입력"</span>, <span class="hljs-string">"노트북"</span>)
    search_button = st.button(<span class="hljs-string">"검색"</span>)
    <span class="hljs-comment"># 진행률 바 초기화</span>
    <span class="hljs-keyword">if</span> <span class="hljs-string">'progress_bar'</span> not <span class="hljs-keyword">in</span> st.session_state:
        st.session_state.progress_bar = st.progress(0)

<span class="hljs-comment"># 검색 버튼이 눌렸을 때</span>
<span class="hljs-keyword">if</span> search_button:
    st.write(f<span class="hljs-string">"'{search_query}' 검색 결과:"</span>)
    
    <span class="hljs-comment"># 크롤링 시작</span>
    product_list = crawl_product_info(search_query)
    
    <span class="hljs-comment"># 결과를 데이터프레임으로 변환 후 출력</span>
    df = pd.DataFrame(product_list)
    st.dataframe(df)

    <span class="hljs-comment"># CSV 파일 다운로드 버튼</span>
    csv = df.to_csv(index=False, encoding=<span class="hljs-string">'utf-8-sig'</span>)
    st.download_button(
        label=<span class="hljs-string">"CSV 다운로드"</span>,
        data=csv,
        file_name=f<span class="hljs-string">'{search_query}_검색결과.csv'</span>,
        mime=<span class="hljs-string">'text/csv'</span>
    )</pre>
<h3 style="color: #000000; text-align: start;" data-ke-size="size23">파이썬 다나와 크롤링 제품 정보 모으기 &#8211; 스트림릿</h3>
<p data-ke-size="size16"><span style="color: #333333; text-align: start;">이 스크립트는 </span><b>Streamlit</b>을 이용해 웹페이지를 통해 제품 정보를 검색하고, 결과를 크롤링하여 보여주는 애플리케이션을 위해 코드를 업로드 합니다. 아래 코드도 공유 드릴게요</p>
<figure contenteditable="false" data-ke-type="file" data-ke-align="alignCenter">
<div class="image"></div>
<div class="desc">
<p class="filename"><span class="name">미확인 478311</span><span class="type">.crdownload</span></p>
<p class="size">0.00MB</p>
</div>
</figure>
<p>&nbsp;</p>
<!-- AI CONTENT END 4 -->
]]></content:encoded>
					
		
		
			</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 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 4"><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><a href="https://2days.kr/30/11/12/70250/aboda/">API</a> 요청 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>
<!-- AI CONTENT END 6 -->
]]></content:encoded>
					
		
		
			</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 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 7"><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;">먼저 단지를 추출할 수 있는 <a href="https://2days.kr/12/12/08/70405/english/">request</a> 주소를 한번 살펴 보겠습니다.</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 8"></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 9"></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: <a href="https://2days.kr/30/11/12/70250/aboda/">API</a> 요청을 네이버 모바일 부동산 사이트에서 온 것처럼 보이게 만듭니다.</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>
<!-- AI CONTENT END 8 -->
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</title>
		<link>https://2days.kr/15/09/07/56533/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Sat, 14 Sep 2024 22:19:38 +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=56533</guid>

					<description><![CDATA[부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 ㅣ 네이버 부동산 데이터는 매우 유용하게 활용할 수 있지만, 원하는 형태로 변환된 자료를 얻는 것은 상당히 어렵습니다. Excel의 VBA를 사용하여 데이터를 변환하는 방법이 소개되곤 하지만, Python의 뛰어난 기능을 통해 실시간 부동산 매물 정보를 크롤링하는 구체적인 방법을 공부하고 있습니다. 이제 네이버 부동산에서 방대한 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 ㅣ 네이버 부동산 데이터는 매우 유용하게 활용할 수 있지만, 원하는 형태로 변환된 자료를 얻는 것은 상당히 어렵습니다. Excel의 VBA를 사용하여 데이터를 변환하는 방법이 소개되곤 하지만, Python의 뛰어난 기능을 통해 실시간 부동산 매물 정보를 크롤링하는 구체적인 방법을 공부하고 있습니다.</p>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">이제 네이버 부동산에서 방대한 데이터를 Python을 활용해 필요한 정보를 직접 수집해 보겠습니다.</p>
<h3 style="background-color: #ffffff; color: #0d0d0d; text-align: start;" data-ke-size="size23">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</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/YBEvR/btsJEUU24W5/T4wrGkk09jkMFBxAF1jitK/img.png" alt="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1" width="2560" height="2560" data-origin-width="2560" data-origin-height="2560" data-is-animation="false" data-filename="부동산 매물 정보 수집하기 - 부동산 데이터 크롤링 및 가공 #1.png" data-origin- title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 14"><figcaption class="wp-caption-text">부동산 매물 정보 수집하기 &#8211; 부동산 데이터 네이버 부동산 크롤링 및 가공 #1</figcaption></figure><figcaption>부동산 매물 정보 수집하기 &#8211; 부동산 데이터 크롤링 및 가공 #1</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>

<div id="SE-8f4a9d36-5aac-471b-9959-953aee3f8c53" style="background-color: #f7f7f7; color: #777777; text-align: left;">
<div>
<div>
<div>
<p id="SE-D957264E-4CFD-40F9-A4BD-D27C04709E52" style="color: #000000; text-align: var(--se-text-default-value-text-align);">네이버 부동산은 PC 환경과 모바일 환경으로 나누어져 서비스 되어지고 있으며,각각의 환경을 크롤링하는 방식도 차이가 있습니다. 두 방식 중에서 모바일 환경을 크롤링하는 방식이 보여지는 정보가 적어서 보다 유리합니다.</p>
</div>
</div>
</div>
</div>
<div id="SE-d184a622-947d-4abe-99fd-b636b3c39475" 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/piDAn/btsJEjVgagn/4I4snJQCRLpWL10yi1OBXk/img.jpg" data-height="563" data-width="886" data-lazy-src="" data-origin-width="966" data-origin-height="615" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 15"></figure>
</div>
<div>
<p id="SE-F5057863-6C9B-467E-A914-7954491FE61E" style="color: #000000; text-align: var(--se-image-default-caption-text-align);"><span style="color: #555555;">PC환경</span></p>
</div>
</div>
</div>
</div>
<div id="SE-a55f1b6b-e89f-465c-a428-6bafdab2e902" 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/b9T632/btsJDcb3WhG/Gvbudr4UH8bpHxiYGufkJ0/img.jpg" data-height="632" data-width="886" data-lazy-src="" data-origin-width="966" data-origin-height="691" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 16"></figure>
</div>
<div>
<p id="SE-86964DA9-18AE-417C-940E-E5A8420DD101" style="color: #000000; text-align: var(--se-image-default-caption-text-align);"><span style="color: #555555;">모바일환경</span></p>
</div>
</div>
</div>
</div>
<p>특정 아파트 단지의 매물 정보 가져오기</p>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">아래 이미지에서는 <a href="http://m.land.naver.com에" target="_blank">http://m.land.naver.com에</a> 접속하여 &#8216;상암월드컵파크4단지&#8217;의 매물과 관련된 정보를 보여준다. 여기서 중요한 요소는 아파트 단지의 고유 식별자인 &#8216;23620&#8217;과 거래 방식을 나타내는 코드 &#8216;A1:B1:B2 &#8216;입니다. 각 코드의 의미는 A1은 매매, B1은 전세, B2는 월세, 그리고 B3는 단기임대에 해당합니다.</p>
<p style="background-color: #ffffff; color: #0d0d0d; text-align: start;">예를 들어, 다음 주소에서 매물 정보를 확인할 수 있습니다.다<a href="https://m.land.naver.com/complex/info/23620?tradTpCd=A1:B1:B2:B3&amp;ptpNo=1&amp;bildNo=&amp;articleListYN=Y" target="_blank" rel="noopener">https://m.land.naver.com/complex/info/23620?tradTpCd=A1:B1:B2:B3&amp;ptpNo=1&amp;bildNo=&amp;articleListYN=Y</a></p>
<p>특정단지의 매물값을 가져오는 코드를 다시 작성해보면 아래와 같습니다.</p>
<pre id="code_1726351819860" class="bash hljs" contenteditable="false" data-ke-language="bash" data-ke-type="codeblock">import requests
import json
import pandas as pd

URL = <span class="hljs-string">"https://m.land.naver.com/complex/getComplexArticleList"</span>

parameter = {
    <span class="hljs-string">'hscpNo'</span>: <span class="hljs-string">'23620'</span>, <span class="hljs-comment"># 상암월드컵파크4단지 고유번호</span>
    <span class="hljs-string">'tradTpCd'</span>: <span class="hljs-string">'A1:B1:B2'</span>, <span class="hljs-comment"># 거래방식 3가지</span>
    <span class="hljs-string">'order'</span>: <span class="hljs-string">'spc_'</span>, <span class="hljs-comment"># 면적별 정열</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/112.0.0.0 Safari/537.36 Edg/112.0.1722.39'</span>,
    <span class="hljs-string">'Referer'</span>: <span class="hljs-string">'https://m.land.naver.com/'</span>
}

page = 0
lands = []

<span class="hljs-keyword">while</span> True:
    page = page + 1
    parameter[<span class="hljs-string">'page'</span>] = page

    response = requests.get(URL, params=parameter, headers=header)
    <span class="hljs-keyword">if</span> response.status_code != 200:
        <span class="hljs-built_in">print</span>(<span class="hljs-string">'invalid status: %d'</span> % response.status_code)
        <span class="hljs-built_in">break</span>

    data = json.loads(response.text)
    result = data[<span class="hljs-string">'result'</span>]
    <span class="hljs-keyword">if</span> result is None:
        <span class="hljs-built_in">print</span>(<span class="hljs-string">'no result'</span>)
        <span class="hljs-built_in">break</span>
    
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> result[<span class="hljs-string">'list'</span>]:
        lands.append([item[<span class="hljs-string">'tradTpNm'</span>], item[<span class="hljs-string">'bildNm'</span>], item[<span class="hljs-string">'flrInfo'</span>], item[<span class="hljs-string">'prcInfo'</span>], item[<span class="hljs-string">'spc1'</span>]])
    
    <span class="hljs-keyword">if</span> result[<span class="hljs-string">'moreDataYn'</span>] == <span class="hljs-string">'N'</span>:
        <span class="hljs-built_in">break</span>
<span class="hljs-built_in">print</span>(pd.DataFrame(lands))</pre>
<div id="SE-75bc509e-e497-4245-9e4c-e9b932f1248d" 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/nhjI8/btsJDv92amU/Y1GwjB0SlVeUmAAkjCmBB0/img.jpg" data-height="1001" data-width="886" data-lazy-src="" data-origin-width="792" data-origin-height="895" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 17"></figure>
</div>
</div>
</div>
</div>
<div id="SE-71890684-4379-48e9-ac90-9757a8b0f2d5" 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/2QTjm/btsJDopKzg8/fpaGyMkpsBo2FhV7ueKNvk/img.jpg" data-height="820" data-width="641" data-lazy-src="" data-origin-width="641" data-origin-height="820" data-is-animation="false" alt="img" title="부동산 매물 정보 수집하기 - 부동산 데이터 네이버 부동산 크롤링 및 가공 #1 18"></figure>
</div>
</div>
</div>
</div>
<p>다음편에서는 각 아파트별 정보를 얻을 수 있는 파이썬 코드를 알아보도록 하겠습니다.</p>
<!-- AI CONTENT END 10 -->
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>네이버 뉴스 크롤링 텔레그램  실시간 파이썬 코딩</title>
		<link>https://2days.kr/17/10/14/7776/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Tue, 17 Oct 2023 05:02:32 +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>
		<category><![CDATA[파이썬]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=7776</guid>

					<description><![CDATA[네이버 뉴스 크롤링 하여 텔레그램으로 전송하는 방법에 대해서 알아 봅니다. 크롤링 원하는 네이버 뉴스의 키워드 값을 받아 키워드가 포함된 뉴스 URL을 가지고, 텔레그램 봇을 통해 채팅방에 전송하는 파이썬 Python 스크립트를 만들어 봅니다.]]></description>
										<content:encoded><![CDATA[<div class="separator"></div>
<p>네이버 뉴스 크롤링 하여 텔레그램으로 전송하는 방법에 대해서 알아 봅니다. 크롤링 원하는 네이버 뉴스의 키워드 값을 받아 키워드가 포함된 뉴스 URL을 가지고, 텔레그램 봇을 통해 채팅방에 전송하는 파이썬 Python 스크립트를 만들어 봅니다.</p>
<figure style="width: 640px" class="wp-caption alignnone"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGaokcmUiOucjheXg3C0aRDbJiOgLYnkO7Mp1yx669Z9yOdp_U_Oyv-SCuZGB8K7h2Qrs9x2youLARcPEunN0MgT6CnWeo3ihNoOk1mEOVZhJ7VTCnH3mD2Sply-WmTDpSlhKrlOLT__bmAI_g9wM-MUv7mmRkGs6-TXrzNL7Fv_4qIu10acpCwDRksUIM/s2560/%EC%A0%9C%EB%AA%A9%EC%9D%84%20%EC%9E%85%EB%A0%A5%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94_-008.jpg" target="_blank" rel="noopener"><img post-id="7776" fifu-featured="1" loading="lazy" decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGaokcmUiOucjheXg3C0aRDbJiOgLYnkO7Mp1yx669Z9yOdp_U_Oyv-SCuZGB8K7h2Qrs9x2youLARcPEunN0MgT6CnWeo3ihNoOk1mEOVZhJ7VTCnH3mD2Sply-WmTDpSlhKrlOLT__bmAI_g9wM-MUv7mmRkGs6-TXrzNL7Fv_4qIu10acpCwDRksUIM/w640-h640/%EC%A0%9C%EB%AA%A9%EC%9D%84%20%EC%9E%85%EB%A0%A5%ED%95%B4%EC%A3%BC%EC%84%B8%EC%9A%94_-008.jpg" alt="네이버 뉴스 크롤링 텔레그램  실시간 파이썬 코딩" title="네이버 뉴스 크롤링 텔레그램  실시간 파이썬 코딩" width="640" height="640" border="0" data-original-height="2560" data-original-width="2560" title="네이버 뉴스 크롤링 텔레그램 실시간 파이썬 코딩 19"></a><figcaption class="wp-caption-text">네이버 뉴스 크롤링 텔레그램 실시간 파이썬 코딩</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>파이썬에 대해 관련 글도 확인해보세요</p>
<p><a href="https://2days.kr/05/10/12/7207/coding/">파이썬 주식 분석 보고서 만들기 Python stock</a></p>
<h1 id="1">1. 네이버 뉴스 크롤링 프로그램 컨셉</h1>
<p><img decoding="async" src="https://blog.kakaocdn.net/dn/b7w8jh/btrm2o5VSCn/D4qcWydC2PbPHsMBboeLLk/img.png" alt="img" title="네이버 뉴스 크롤링 텔레그램 실시간 파이썬 코딩 20"></p>
<h1 id="2">2. 네이버 뉴스 크롤링 사용 라이브러리 정보</h1>
<ul>
<li>requests (특정 url의 html 문서 받기)</li>
<li>BeautifulSoup (html 문서에서 원하는 요소 선택적 추출)</li>
<li>python-telegram-bot (뉴스 링크를 텔레그램 봇으로 채팅방에 전송)</li>
</ul>
<h1 id="3">3. 네이버 뉴스 크롤링 전체 코드</h1>
<p>이해하기 쉽도록 자세하게 주석을 달아두었으니 어렵지 않을거예요.</p>
<p>참고로 이 코드가 담긴 파이썬 파일(.py)을 pyinstaller를 이용해서 exe 파일로 만들어서 윈도우 시작 시, 기본 프로그램으로 설정해 놓으면 나만의 알리미 프로그램을 만드실 수 있어요!</p>
<p>&nbsp;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#step1.라이브러리 불러오기
import  requests
from  bs4  import  BeautifulSoup  as  bs
import  telegram
import  schedule
import  time

#step2.새로운 네이버 뉴스 기사 링크를 받아오는 함수
def  get_new_links(old_links=[]):

    # (주의) 네이버에서 키워드 검색 - 뉴스 탭 클릭 - 최신순 클릭 상태의 url
    url  = f'https://search.naver.com/search.naver?where=news&amp;query={query}&amp;sm=tab_opt&amp;sort=1&amp;photo=0&amp;field=0&amp;pd=0&amp;ds=&amp;de=&amp;docid=&amp;related=0&amp;mynews=0&amp;office_type=0&amp;office_section_code=0&amp;news_office_checked=&amp;nso=so%3Add%2Cp%3Aall&amp;is_sug_officeid=0'

    # html 문서 받아서 파싱(parsing)
    response  =  requests.get(url)
    soup  =  bs(response.text , 'html.parser')

    # 해당 페이지의 뉴스기사 링크가 포함된 html 요소 추출
    news_titles  =  soup.select('a.news_tit')

    # 요소에서 링크만 추출해서 리스트로 저장
    list_links  = [i.attrs['href'] for  i  in  news_titles]

    # 기존의 링크와 신규 링크를 비교해서 새로운 링크만 저장
    new_links  = [link  for  link  in  list_links  if  link  not  in  old_links]

    return  new_links


#step3.새로운 네이버 뉴스 기사가 있을 때 텔레그램으로 전송하는 함수
def  send_links():
    # 함수 내에서 처리된 리스트를 함수 외부에서 참조하기 위함
    global old_links

    # 위에서 정의했던 함수 실행
    new_links  =  get_new_links(old_links)

    # 새로운 메시지가 있으면 링크 전송
    if  new_links:
        for  link  in  new_links:
            bot.sendMessage(chat_id=chat_id, text=link)

    # 없으면 패스
    else:
        pass

    # 기존 링크를 계속 축적하기 위함

    old_links +=  new_links.copy()


# 실제 프로그램 구동
if  __name__  ==  '__main__':

    #토큰을 변수에 저장
    bot_token  ='자신이 발급받은 봇의 토큰'
    bot  =  telegram.Bot(token  =  bot_token)

    #가장 최근에 온 메세지의 정보 중, chat id만 가져옴 (이 chat id는 사용자(나)의 계정 id임)
    chat_id  =  bot.getUpdates()[-1].message.chat.id

    #step4.검색할 키워드 설정
    query  =  input('크롤링 할 뉴스기사 키워드를 입력하세요: ')

    #위에서 얻은 chat id로 bot이 메세지를 보냄.
    bot.sendMessage(chat_id  =  chat_id, text=f"{query}를 주제로 뉴스 기사 크롤링이 시작 되었습니다")

    #step5.기존에 보냈던 링크를 담아둘 리스트 만들기
    old_links  = []

    # 주기적 실행과 관련된 코드 (hours는 시, minutes는 분, seconds는 초)
    job  =  schedule.every(10).seconds.do(send_links)

    while  True:
        schedule.run_pending()
        time.sleep(1)
</pre>
<p>&nbsp;</p>
<h2 id="4">네이버 뉴스 크롤링 여러 검색어 크롤링</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#step1.라이브러리 불러오기
import  requests
from  bs4  import  BeautifulSoup  as  bs
import  telegram
import  schedule
import  time

# step2.새로운 네이버 뉴스 기사 링크를 받아오는 함수

def get_new_links(query, old_links=[]):

    # (주의) 네이버에서 키워드 검색 - 뉴스 탭 클릭 - 최신순 클릭 상태의 url
    url = f'https://search.naver.com/search.naver?where=news&amp;query={query}&amp;sm=tab_opt&amp;sort=1&amp;photo=0&amp;field=0&amp;pd=0&amp;ds=&amp;de=&amp;docid=&amp;related=0&amp;mynews=0&amp;office_type=0&amp;office_section_code=0&amp;news_office_checked=&amp;nso=so%3Add%2Cp%3Aall&amp;is_sug_officeid=0'

    # html 문서 받아서 파싱(parsing)
    response = requests.get(url)
    soup = bs(response.text, 'html.parser')

    # 해당 페이지의 뉴스기사 링크가 포함된 html 요소 추출
    news_titles = soup.select('a.news_tit')

    # 요소에서 링크만 추출해서 리스트로 저장
    list_links = [i.attrs['href'] for i in news_titles]

    # 기존의 링크와 신규 링크를 비교해서 새로운 링크만 저장
    new_links = [link for link in list_links if link not in old_links]

    return new_links


# step3.새로운 네이버 뉴스 기사가 있을 때 텔레그램으로 전송하는 함수
def send_links(query):
    # 함수 내에서 처리된 리스트를 함수 외부에서 참조하기 위함
    global old_links

    # 위에서 정의했던 함수 실행
    new_links = get_new_links(query, old_links)

    # 새로운 메시지가 있으면 링크 전송
    if new_links:
        bot.sendMessage(chat_id=chat_id, text='방금 업데이트 된 ' + f"{query} 주제의 크롤링입니다.")
        for link in new_links:
            bot.sendMessage(chat_id=chat_id, text=link)

    # 없으면 패스
    else:
        pass

    # 기존 링크를 계속 축적하기 위함

    old_links += new_links.copy()


# 실제 프로그램 구동
if __name__ == '__main__':

    # 토큰을 변수에 저장
    bot_token = '자신이 발급받은 봇의 토큰'
    bot = telegram.Bot(token=bot_token)

    # 가장 최근에 온 메세지의 정보 중, chat id만 가져옴 (이 chat id는 사용자(나)의 계정 id임)
    chat_id = bot.getUpdates()[-1].message.chat.id


    # #step4.검색할 키워드 설정
    # query  =  input('크롤링 할 뉴스기사 키워드를 입력하세요: ')
    queries = ["부동산", "경제", "날씨"]

    for query in queries:

        # 위에서 얻은 chat id로 bot이 메세지를 보냄.
        bot.sendMessage(chat_id=chat_id,
                        text=f"{query}를 주제로 뉴스 기사 크롤링이 시작 되었습니다")

        # step5.기존에 보냈던 링크를 담아둘 리스트 만들기
        old_links = []

        # 주기적 실행과 관련된 코드 (hours는 시, minutes는 분, seconds는 초)
        job = schedule.every(10).seconds.do(send_links, query)

    while True:
        schedule.run_pending()
        time.sleep(1)

</pre>
<p>&nbsp;</p>
<p>해당 코드를 복사한 후 비주얼베이직이나 파이참에 넣고 실행하면 실행이 됩니다.</p>
<p>&nbsp;</p>
<!-- AI CONTENT END 11 -->
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>티스토리 파이썬 포스팅 글, 이미지 백업하기</title>
		<link>https://2days.kr/27/09/22/6738/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Wed, 27 Sep 2023 13:37:43 +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=6738</guid>

					<description><![CDATA[티스토리(tistory) 백업이 필요해서 파이썬(스크래핑)으로 블로그 포스팅 글과 이미지를 PC 에 저장 하려는 분들이 계실거라고 생각이 듭니다.

오늘은 파이썬으로 티스토리를 백업하는 방법에 대해서 알아봅니다.]]></description>
										<content:encoded><![CDATA[<p data-ke-size="size16">티스토리(tistory) 백업이 필요해서 파이썬(스크래핑)으로 블로그 포스팅 글과 이미지를 PC 에 저장 하려는 분들이 계실거라고 생각이 듭니다.</p>
<p data-ke-size="size16">오늘은 파이썬으로 티스토리를 백업하는 방법에 대해서 알아봅니다.</p>
<h4 data-ke-size="size20"><b>일단 코딩한 것이 동작하는 환경과 그 내역을 살펴보면,</b></h4>
<p data-ke-size="size16">-북클럽(Book Club) 스킨에서 카테고리 7~8개 만들고 포스팅 중입니다.</p>
<p data-ke-size="size16">-포스트 주소는 숫자로 설정해서 사용 중입니다.</p>
<p data-ke-size="size16">개발자도구(F12)에서 html 코드를 보고</p>
<p data-ke-size="size16">-requests, BeautifulSoup를 통해 스크래핑 진행했으며,</p>
<p data-ke-size="size16">&#8211;<a href="https://ko.wikipedia.org/wiki/Python_Imaging_Library" target="_blank" rel="noopener">PIL Image </a>를 통해 이미지 다운로드 시 안보이는 확장자 문제를 해결하였습니다.</p>
<p data-ke-size="size16">이미지는 src에 확장자(.jpg .png)까지 정확하게 된 것도 있었지만, 다음과 같은 형태로 포함된 URL을 가지고 있는 것도 있었습니다.</p>
<pre id="code_1630939194313" class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs">&lt;img srcset=<span class="hljs-string">"https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=http%3A%2F%2Fcfile1.uf.tistory.com%2Fimage%2F993693465F20BB0F1FAFB6"</span> src=<span class="hljs-string">"https://t1.daumcdn.net/cfile/tistory/993693465F20BB0F1F"</span> 

//i1.daumcdn.net/thumb/C176x120/?fname=https://t1.daumcdn.net/cfile/tistory/<span class="hljs-number">99400</span>A3F5F21057413</code></pre>
<p data-ke-size="size16">PIL Image로 이미지 정보를 찾으면</p>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs">img_url: https://t1.daumcdn.net/cfile/tistory/<span class="hljs-number">992895395</span>F2040A804
img_format: PNG
imge_size: (<span class="hljs-number">830</span>, <span class="hljs-number">1019</span>)
<span class="hljs-built_in">len</span>(이미지): <span class="hljs-number">41568</span></code></pre>
<h4 data-ke-size="size20"><b>소스 코드는</b></h4>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<pre id="code_1630939263129" class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"><span class="hljs-keyword">from</span> bs4 <span class="hljs-keyword">import</span> BeautifulSoup
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">tistory_backup</span><span class="hljs-params">(post_num)</span>:</span>

    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, post_num + <span class="hljs-number">1</span>):
        url = <span class="hljs-string">'https://본인의 티스토리 URL/'</span> + <span class="hljs-built_in">str</span>(num)
        response = requests.get(url)
        soup = BeautifulSoup(response.text, <span class="hljs-string">'lxml'</span>)
        
        <span class="hljs-comment">### 포스팅 글 제목</span>
        titles = soup.select_one(<span class="hljs-string">'#content &gt; div.inner &gt; div.post-cover &gt; div &gt; h1'</span>)
        
        <span class="hljs-comment">### 등록일</span>
        date = soup.select_one(<span class="hljs-string">'#content &gt; div.inner &gt; div.post-cover &gt; div &gt; span.meta &gt; span.date'</span>)
        
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> titles <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> date:
            <span class="hljs-keyword">continue</span>
        
        <span class="hljs-built_in">print</span>(titles.text)    
        <span class="hljs-built_in">print</span>(date.text)
        
        <span class="hljs-comment">### 포스팅 내용</span>
        entry_content = soup.find(<span class="hljs-string">'div'</span>, {<span class="hljs-string">'class'</span>:<span class="hljs-string">'entry-content'</span>})
        <span class="hljs-built_in">print</span>(entry_content.get_text())
        
        res = requests.get(url)
        soup_img = BeautifulSoup(res.content, <span class="hljs-string">'lxml'</span>)
        imgs = soup_img.select(<span class="hljs-string">'img[src^=https]'</span>)  <span class="hljs-comment"># https 로 시작하는 src, '//'로 시작하는 src 제외시킴</span>
        <span class="hljs-built_in">print</span>(<span class="hljs-string">f'이미지 수 : <span class="hljs-subst">{<span class="hljs-built_in">len</span>(imgs)}</span>'</span>)
        <span class="hljs-comment"># print(imgs)</span>
        
        <span class="hljs-comment"># 저장 디렉토리 만들기</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(<span class="hljs-string">'tistoryBackup'</span>):
            os.mkdir(<span class="hljs-string">'tistoryBackup'</span>)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(<span class="hljs-string">'tistoryBackup/post_'</span> + <span class="hljs-built_in">str</span>(num)):
            os.makedirs(<span class="hljs-string">'tistoryBackup/post_'</span> + <span class="hljs-built_in">str</span>(num))
        
        cnt = <span class="hljs-number">1</span>
        <span class="hljs-keyword">for</span> img <span class="hljs-keyword">in</span> imgs:
            img_url = img[<span class="hljs-string">'src'</span>]
            
            <span class="hljs-comment">## pillow.Image로 이미지 format 알아내기</span>
            imageObj = Image.<span class="hljs-built_in">open</span>(requests.get(img_url, stream=<span class="hljs-keyword"><span class="hljs-literal">True</span></span>).raw)
            img_format = imageObj.<span class="hljs-built_in">format</span>
            imge_size = imageObj.size
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f'img_url: <span class="hljs-subst">{img_url}</span>'</span>)
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f'img_format: <span class="hljs-subst">{img_format}</span>'</span>)
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f'imge_size: <span class="hljs-subst">{imge_size}</span>'</span>)
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f'os.path.basename(img_url): <span class="hljs-subst">{os.path.basename(img_url)}</span>'</span>)
            
            res_img = requests.get(img_url).content
            <span class="hljs-built_in">print</span>(<span class="hljs-string">f'len(이미지): <span class="hljs-subst">{<span class="hljs-built_in">len</span>(res_img)}</span>'</span>)  <span class="hljs-comment"># requests의 .content는 bytes 타입을 리턴함</span>
            
            <span class="hljs-keyword">if</span> img_url.split(<span class="hljs-string">'.'</span>)[<span class="hljs-number">-1</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'png'</span>, <span class="hljs-string">'jpg'</span>]:
                img_name = <span class="hljs-built_in">str</span>(num) + <span class="hljs-string">'_'</span> + <span class="hljs-built_in">str</span>(cnt) + <span class="hljs-string">'_'</span> + os.path.basename(img_url)
            <span class="hljs-keyword">else</span>:
                img_name = <span class="hljs-built_in">str</span>(num) + <span class="hljs-string">'_'</span> + <span class="hljs-built_in">str</span>(cnt) + <span class="hljs-string">'_'</span> + <span class="hljs-string">'no_filename_img.'</span> + img_format
            
            <span class="hljs-built_in">print</span>(img_name)
            
            <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(res_img) &gt; <span class="hljs-number">100</span>:  <span class="hljs-comment"># 이미지 용량이 00 bytes 이상인 것만</span>
                <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">'./tistoryBackup/post_'</span> + <span class="hljs-built_in">str</span>(num) + <span class="hljs-string">'/'</span> + img_name, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> f:
                    f.write(res_img)
                cnt += <span class="hljs-number">1</span>
        
        title_content = titles.text + <span class="hljs-string">'\n'</span> + date.text +  <span class="hljs-string">'\n'</span> + entry_content.get_text()
        filename = <span class="hljs-built_in">str</span>(num) + <span class="hljs-string">'_tistory_title_content.txt'</span>
        <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">'./tistoryBackup/post_'</span> + <span class="hljs-built_in">str</span>(num) + <span class="hljs-string">'/'</span> + filename, <span class="hljs-string">'w'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> f:
            f.write(title_content)
        
tistory_backup(<span class="hljs-number">20</span>)</code></pre>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<p data-ke-size="size16">tistory_backup(20) 실행 시, 20은 포스트 주소의 숫자.<br />
즉, https://abc4u.tistory.com/1 ~ https://abc4u.tistory.com/20 까지의 포스트 url을 대상으로 추출한다는 의미이며, 본인의 최근 포스팅 번호를 넣으면 1번 부터 최근 번호까지 전체가 추출됨</p>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<p>&nbsp;</p>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<figure class="imageblock alignLeft" data-ke-mobilestyle="widthOrigin" data-filename="tistory_backup2.JPG" data-origin-width="1095" data-origin-height="480"><span data-url="https://blog.kakaocdn.net/dn/XAcpk/btrec5uIPJw/6pa3ixI8zMWmcNKcRnVtf1/img.jpg" data-lightbox="lightbox" data-alt="티스토리 백업"><img decoding="async" src="https://blog.kakaocdn.net/dn/XAcpk/btrec5uIPJw/6pa3ixI8zMWmcNKcRnVtf1/img.jpg" srcset="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXAcpk%2Fbtrec5uIPJw%2F6pa3ixI8zMWmcNKcRnVtf1%2Fimg.jpg" data-filename="tistory_backup2.JPG" data-origin-width="1095" data-origin-height="480" alt="img" title="티스토리 파이썬 포스팅 글, 이미지 백업하기 21"></span><figcaption>티스토리 백업</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>

<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<p>&nbsp;</p>
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<p data-ke-size="size16">
<pre class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"></code></pre>
<p data-ke-size="size16">소스코드를 실행하면 위 탐색기 이미지처럼 폴더를 생성하고, 글은 .txt 파일로 저장하고 해당 포스트에 있는 이미지전체는 이름을 다시 만들어져서 저장됩니다.</p>
<pre id="code_1630939216243" class="python" data-ke-language="python" data-ke-type="codeblock"><code class="hljs"><span class="hljs-number"> </span></code></pre>
<!-- AI CONTENT END 12 -->
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편)</title>
		<link>https://2days.kr/05/09/09/6136/it/program/</link>
		
		<dc:creator><![CDATA[urjent]]></dc:creator>
		<pubDate>Tue, 05 Sep 2023 00:36:38 +0000</pubDate>
				<category><![CDATA[program]]></category>
		<category><![CDATA[부동산]]></category>
		<category><![CDATA[크롤링]]></category>
		<category><![CDATA[파이썬]]></category>
		<category><![CDATA[파이참]]></category>
		<guid isPermaLink="false">https://2days.kr/?p=6136</guid>

					<description><![CDATA[부동산 상승과 하락 시장 구분이 명확하지 않은 시점에서 정확한 판단을 위해서 정보를 수집, 가공하여 판단 자료로 활용하시는 분들이 많아진 이유라고 생각합니다.
다양한 부동산 정보가 넘쳐나는 시점에서 어떻게 많은 정보를 가져오고 가공 할 수 있을까 하는 것이 핵심인데요 그래서 오늘부터 몇차례에 걸쳐서 부동산 정보 크롤링 하는 법에 대해서 포스팅 하려고 합니다]]></description>
										<content:encoded><![CDATA[<p>요즘 &#8216;부동산&#8217; 에 대한 정보를 가공하고자 하는 분들이 많이 있으신 것 같습니다.</p>
<p>부동산 상승과 하락 시장 구분이 명확하지 않은 시점에서 정확한 판단을 위해서 정보를 수집, 가공하여 판단 자료로 활용하시는 분들이 많아진 이유라고 생각합니다.</p>
<p>다양한 부동산 정보가 넘쳐나는 시점에서 어떻게 많은 정보를 가져오고 가공 할 수 있을까 하는 것이 핵심인데요 그래서 오늘부터 몇차례에 걸쳐서 부동산 정보 크롤링 하는 법에 대해서 포스팅 하려고 합니다.</p>
<p>오늘은 부동산 지인이라는 사이트에서 미분양 정보 데이터를 수집해보려고 합니다.</p>
<p><span style="background-color: #ff0000; color: #ffffff;">(중요) 부동산 크롤링은 고유 사이트의 지적 재산을 침해할 수 있으므로 해당 포스팅은 크롤링을 장려 하는 글이 아니며 단순히 크롤링에 대한 학습 정보라고만 생각해주세요.</span></p>
<h2><em><strong>부동산 지인 사이트를 알아보자.</strong></em></h2>
<hr />
<p>부동산 지인 사이트에서 미분양 정보를 가져올때 몇가지 제한 사항이 있습니다.</p>
<ol>
<li>아이디와 비밀번호를 입력해서 로그인을 해야합니다.</li>
<li>부동산 지인 사이트는 개발자모드(F12)를 금지 스크립트가 적용되어 있어, 개발자모드를 켜는 순간 웹사이트가 정상적으로 동작하지 않습니다.</li>
<li>따라서 크롤링 하기에는 난해한 사이트 입니다.</li>
</ol>
<p>어쨌든, 해당 사이트에서 미분양 정보만 수집해보겠습니다. 먼저 부동산 지인 사이트에 접속해 봅니다.</p>
<p><img post-id="6136" fifu-featured="1" loading="lazy" decoding="async" class="aligncenter size-full wp-image-6132" src="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2.png" alt="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편)" title="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편)" width="2560" height="1265" title="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편) 22" srcset="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2.png 2560w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-300x148.png 300w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-1024x506.png 1024w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-768x380.png 768w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-1536x759.png 1536w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-2048x1012.png 2048w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-150x74.png 150w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-696x344.png 696w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-1068x528.png 1068w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-1920x949.png 1920w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-850x420.png 850w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.26.59-2-324x160.png 324w" sizes="(max-width: 2560px) 100vw, 2560px" /><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>
<p>부동산 지인 사이트에 접속하면 기간별 미분양 현황 그래프로 나와 있는데, 이 그래프에서 숫자만 뽑아오는 것이 이번에 할 일입니다.</p>
<p>부동산 지인 사이트는 네이버에 부동사 지인이라고 검색 하시거나 아래 링크를 클릭하여 이동하세요.</p>
<h2><em><strong>파이참 (Pycharm)을 실행하자</strong></em></h2>
<hr />
<p>파이썬 (Python)을 활용하는데 다양한 비쥬얼 에디터 (Visual editor) 가 존재하는데, 비쥬얼스튜디오나 파이참을 많은 사람들이 이용하고 있습니다. 개인적으로 파이참을 주로 사용하는데, 파이참에서 제공하는 플러그인 중에 마음에 드는 것이 있기 때문입니다.</p>
<p>먼저 파이참을 실행하고, 새로운 프로젝트를 설정합니다. 새로운 프로젝트명은 마음대로 정하세요</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-6133" src="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1.png" alt="스크린샷 2023 09 04 오후 9.29.33 1" width="1556" height="1264" title="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편) 23" srcset="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1.png 1556w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-300x244.png 300w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-1024x832.png 1024w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-768x624.png 768w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-1536x1248.png 1536w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-150x122.png 150w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-696x565.png 696w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-1068x868.png 1068w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.29.33-1-517x420.png 517w" sizes="(max-width: 1556px) 100vw, 1556px" /></p>
<p>설정환경에서 가상환경 (Virtualenv)를 설정하는 것을 추천합니다. 파이참에서는 각 코드별로 실행할 수 있는 단축키를 제공하는데, 가끔 코드를 단계별로 실행해서 에러를 추적할 때 메우 유용한 코드입니다.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-6134" src="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48.png" alt="스크린샷 2023 09 04 오후 9.50.48" width="2458" height="1142" title="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편) 24" srcset="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48.png 2458w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-300x139.png 300w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-1024x476.png 1024w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-768x357.png 768w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-1536x714.png 1536w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-2048x952.png 2048w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-150x70.png 150w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-696x323.png 696w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-1068x496.png 1068w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-1920x892.png 1920w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-04-오후-9.50.48-904x420.png 904w" sizes="(max-width: 2458px) 100vw, 2458px" /></p>
<p>단축키는 Alt+Shift+E 키를 활용하시면 됩니다. 블럭으로 묶거나 한 코드만을 감싸서 실행하면 해당 되는 코드만 실행을 하기 때문에 매우 편하게 사용할 수 있습니다.</p>
<p>이제 사용환경을 맞추기 위해서 몇가지 플러그인을 자동으로 다운받도록 하겠습니다.</p>
<h2><em><strong>코드 실행 환경을 만들자</strong></em></h2>
<hr />
<p>코드를 만들기 전에 터미널을 엽니다. 좌측 하단에 여러가지 아이콘이 존재하는데 아이콘에 터미널이라고 존재합니다. 터미널을 클릭하여 아래 코드를 붙여 넣어 실행합니다.</p>
<p>셀레니움은 크롤링을 하기 위한 것이고, 크롬드라이브는 크롬 웹브라우저를 컨트롤할 때 크롬 버전에 맞게 자동으로 버전을 맞춰주는 툴이며, 마지막으로 판다스는 크롤링을 한 데이터는 우리가 원하는 형태로 가공해서 쉽게 추출 할 수 있도록 도와주는 툴이라고 생각하시면 쉽습니다.</p>
<p>아래 코드를 실행합니다</p>
<p><code> pip install selenium chromedriver_autoinstaller pandas<br />
</code></p>
<p>실행하면 자동으로 웹에서 다운로드가 이루어지고 설치가 완료가 됩니다.</p>
<h2><em><strong>코드 만들기</strong></em></h2>
<hr />
<p>우선 아래 코드를 미분양.py 이라는 새로운 파이썬 파일을 만든 후 붙여 넣습니다. 해당 파이썬 코드는 크롬 드라이버에 상관없이 크롬을 조정할 수 있는 기본 코드입니다. 해당 코드를 실행하면 아래와 같이 크롬이 제어되는 것을 볼 수 있습니다.</p>
<div>
<pre># 외우는거 아님. 그냥 필요할 때 복붙
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time

# 크롬 드라이버 자동 업데이트
from webdriver_manager.chrome import ChromeDriverManager

#브라우저 꺼짐 방지
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)

# 불필요한 에러 메시지 없애기
chrome_options.add_experimental_option("excludeSwitches", ["enable-logging"])
browser = webdriver.Chrome(options=chrome_options)</pre>
</div>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-6143" src="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30.png" alt="스크린샷 2023 09 05 오전 12.01.30" width="2560" height="1325" title="부동산 파이썬 Python 크롤링 미분양 정보 가져오기 (1편) 25" srcset="https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30.png 2560w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-300x155.png 300w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-1024x530.png 1024w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-768x397.png 768w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-1536x795.png 1536w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-2048x1060.png 2048w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-150x78.png 150w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-696x360.png 696w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-1068x553.png 1068w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-1920x993.png 1920w, https://2days.kr/wp-content/uploads/2023/09/스크린샷-2023-09-05-오전-12.01.30-812x420.png 812w" sizes="(max-width: 2560px) 100vw, 2560px" /></p>
<p>&nbsp;</p>
<p>이렇게 작성하면 크롤링을 위한 준비는 되었습니다. 이제 크롬 브라우저를 자동으로 조정할 수 있으니, 본격적인 크롤링은 다음편에서 자세하게 다루도록 하겠습니다.</p>
<p>감사합니다.</p>
<!-- AI CONTENT END 13 -->
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
