본문 바로가기
Portfolio & Toy-Project

프로젝트 : 부산항만공사 서비스 제안관련 데이터분석-2

by Mr.DonyStark 2024. 3. 11.

ㅁ 프로젝트 산출물 :  https://busanportservice.streamlit.app/

 

Abstract

Busan Port

busanportservice.streamlit.app

 

ㅁ부산항 주변 부동산 공실 데이터 크롤링

  ○ 셀레니움 → 크롤링 활용

  ○ 뷰티풀숲 → 크롤링 활용

  ○ re  전처리 활용

  ○ pandas → 전처리 활용

from selenium import webdriver #Selenium의 웹 드라이버를 사용하기 위한 모듈을 임포트
from selenium.webdriver.common.by import By #Selenium에서 사용하는 By 클래스를 임포트합. 웹 요소를 검색하는데 사용.
from selenium.webdriver.common.keys import Keys #키보드 입력 제어를 위해 Keys 클래스 임포트
from selenium.webdriver.chrome.service import Service #Chrome 드라이버 서비스를 사용하기 위한 모듈 임포트
from selenium.webdriver.chrome.options import Options #Chrome 드라이버 옵션을 설정하기 위한 클래스 임포트
from webdriver_manager.chrome import ChromeDriverManager #Chrome 드라이버를 자동으로 설치 및 관리하는데 사용되는 드라이버 매니저 임포트
from bs4 import BeautifulSoup #Beautiful soup 크롤링을위해
import pandas as pd
import requests #request 사용을 위해
import re #정규표현을  
import time #timesleep을 위해 사용

myOption = Options() #옵션객체 변수지정
myOption.add_argument("--start-maximized") #크롬 드라이버 창 최대화
myOption.add_argument("--incognito") #크롬 드라이버 시크릿모드로 진행
myOption.add_experimental_option("excludeSwitches", ["enable-automation"]) #드라이버 시작시 불필요문구 미표시되도록 설정
myOption.add_experimental_option("excludeSwitches", ["enable-logging"]) #터미널상의 불필요문구 미표시되도록 설정
myOption.add_experimental_option("detach", True) #드라이버 자동꺼짐 방지

#드라이버 세팅
myService = Service(ChromeDriverManager().install()) #크롬드라이버 설치
myDriver = webdriver.Chrome(service=myService, options=myOption) #드라이버 서비스 및 옵션 지정

#부산신항 주변 → 경상남도 > 창원시 진해구 > 용원동
targetUrl = "https://new.land.naver.com/offices?ms=35.0920766,128.8153858,15&a=GJCG:TJ:SMS:SG&e=RETAIL&h=165"
myDriver.get(targetUrl) #타겟링크로부터 정보수신
time.sleep(4)
print(f"{myDriver.current_url} 접속완료")

#데이터프레임 필드값으로 활용할 빈리스트 생성
idx_list = list()  #데이터프레임 순번
detailTitle_list = list() #판매제목 
detailPrc_list = list()  #가격 리스트
type_list = list()  #타입 리스트
full_Addr_list = list() #풀 주소 리스트
area_list = list() #면적

number_idx = 1
#좌측바 메뉴 개수를 세어보니 20개임. 따라서 반복문 지정을 20까지로 설정
for i in range(2,21):
    number_idx +=1  #순번
    idx_list.append(number_idx)
    leftMenu = myDriver.find_element(By.XPATH, value ='''//*[@id="listContents1"]/div/div/div[1]/div['''+ str(i) +''']''').click() #좌측바 메뉴별 XPATH
    time.sleep(4)
    #BeautifulSoup4 
    webCurrentStatus = myDriver.page_source   #좌측바 메뉴 클릭후 생성된 사이드 바가 표시된 상태 자체를 변수로 지정
    myParser = BeautifulSoup(webCurrentStatus, "html.parser") #위 코드상태를 html로 파싱
    side_Menu = myParser.select("div.detail_contents.is-article") #크롤링 영역 지정 
    for i in side_Menu: #위 코드에서 Select을 사용하였기에 출력이 리스트 타입이므로 반복문 진행
        #↓추출하고자하는 데이터별 태그+클래스네임을 활용하여 데이터 추출
        detailTitle = i.select_one("div.detail_fixed > div.main_info_area > div.info_title_wrap").text
        detailType = i.select_one("div.detail_fixed > div.main_info_area > div.info_article_price > span.type").text
        detailPrc= i.select_one("div.detail_fixed > div.main_info_area > div.info_article_price > span.price").text
        detailAddr = i.select_one("div.detail_box--summary > table.info_table_wrap > tbody > tr.info_table_item > td.table_td").text
        detailArea = i.select_one("div.main_info_area > div.info_article_feature").text
        full_Addr = detailAddr + " " + detailTitle #주소 + 매물명 합침
        #↓위에서 추출한 데이터를 빈리스트에 추가
        area_list.append(detailArea)
        detailTitle_list.append(detailTitle)
        type_list.append(detailType)
        detailPrc_list.append(detailPrc)
        full_Addr_list.append(full_Addr)
        
#데이터프레임 생성
storagePlace = pd.DataFrame(
    {
     "순번" : idx_list,
     "명칭" : detailTitle_list,
     "타입" : type_list,
     "가격" : detailPrc_list,
     "주소" : full_Addr_list,
     "면적(㎡)" : area_list
    } 
)

#전처리를 위해 빈리스트 생성
deposit_list = list()
monthly_fee_list = list()

storagePlace["보증금"] = " " #신규 필드 생성
storagePlace["월세"] = " " #신규 필드 생성
storagePlace["계약면적(㎡)"] = " " #신규 필드 생성
storagePlace["전용면적(㎡)"] = " " #신규 필드 생성
storagePlace["대지면적(㎡)"] = " " #신규 필드 생성
storagePlace = storagePlace[['순번', '명칭', '타입', '면적(㎡)', '계약면적(㎡)', '전용면적(㎡)', '대지면적(㎡)','가격', '보증금', '월세', '주소']]  #필드순번지정

storagePlace

for i in range(0,19):
    if "/" in storagePlace.loc[i,"가격"]:
        storagePlace.loc[i,"보증금"] = storagePlace.loc[i,"가격"].split('/')[0].replace(',','').replace('억','')
        storagePlace.loc[i,"월세"] = storagePlace.loc[i,"가격"].split('/')[1].replace(',','').replace('억','')
    else:
        storagePlace.loc[i,"보증금"] = 0
        storagePlace.loc[i,"월세"] = 0
    
    if storagePlace.loc[i,"주소"][-1] == "층":
        storagePlace.loc[i,"주소"] = storagePlace.loc[i,"주소"][:-2]
    elif storagePlace.loc[i,"주소"][-1] == "대":
        storagePlace.loc[i,"주소"] = storagePlace.loc[i,"주소"][:-2]
    
    if storagePlace.loc[i,"면적(㎡)"].split(":"):
       storagePlace.loc[i,"면적(㎡)"] = storagePlace.loc[i,"면적(㎡)"].split(":")[2]
    
    if "/" in storagePlace.loc[i,"면적(㎡)"]: 
        storagePlace.loc[i,"계약면적(㎡)"] = storagePlace.loc[i,"면적(㎡)"].split('/')[0].replace("㎡","")
        storagePlace.loc[i,"전용면적(㎡)"] = storagePlace.loc[i,"면적(㎡)"].split('/')[1].replace("㎡","")
        storagePlace.loc[i,"대지면적(㎡)"] = "-"
    else:
        storagePlace.loc[i,"계약면적(㎡)"] = "-"
        storagePlace.loc[i,"전용면적(㎡)"] = "-"
        storagePlace.loc[i,"대지면적(㎡)"] = storagePlace.loc[i,"면적(㎡)"].replace("㎡","")


storagePlace['보증금'] = storagePlace['보증금'].astype(int)
storagePlace['월세'] = storagePlace['월세'].astype(int)
storagePlace['월세'] = storagePlace['월세'] * 10000

storagePlace        

for i in range(0,19):
    if storagePlace.loc[i,"보증금"] == 4:
        storagePlace.loc[i,"보증금"] = storagePlace.loc[i,"보증금"] * 100000000

storagePlace