티스토리 뷰

반응형

앞선 포스팅에서 python을 이용하여 네이버 부동산 상가 매물 크롤링을 하기 위한 두번째 단계로 개발자도구를 활용하여 PC가 아닌 모바일 웹 페이지에 접근하여 PC에서 요청 시 발생하는 정보보다 간소화 된 데이터를 확인하면서 실제 필요 데이터를 확인하기 위한 요청메시지를 구성하는 단계까지 확인하였다. 

https://cocoabba.tistory.com/57

 

[PYTHON] 네이버 부동산 상가 매물 크롤링하기(1/6)

앞선 포스팅에 이어 약 1년이 지난 시점에 관련 질문이 있는 듯 하여 각 과정을 아래와 같은 단계로 포스팅하려고 합니다. https://cocoabba.tistory.com/42 [PYTHON] 네이버 부동산 상가 매물 크롤링하기 개

cocoabba.tistory.com

1. 개발자 도구를 활용한 웹페이지에 대한 분석 -> PC 웹 페이지에 대한 분석
2. 개발자 도구를 활용한 웹페이지에 대한 분석 -> 모바일 페이지에 대한 분석

3. 분석한 데이터를 활용한 페이지 요청 : 그룹(단지) 정보 / 물건정보 추출
4. Tkinter 를 활용한 GUI 프로그램 제작

 

이번 포스팅에서는 python 의 requests, beautifulsoup 라이브러리를 이용하여 앞선 포스팅에서 살펴 보았던 각 요청 메시지를 구성하여 진행한다.

 

전체 요청 절차는 아래와 같다.

  1. 모바일 네이버 부동산 사이트에서 검색어(지역명) 입력 : https://m.land.naver.com/search/result/검색어

  2. 응답 메시지 내에서 필요 데이터 추출 및 요청 데이터 구성: lat, lon, z, cortarNo, rletTpCds, tradTpCds

  3. 재구성한 URL로 상가 물건 그룹 데이터 요청 : https://m.land.naver.com/cluster/clusterList

      : 상가 물건 그룹?
      - 앞선 포스팅에서 보았던 것처럼 상가를 처음 검색하면 매물 목록이 아니라 원형 형태의 데이터 그룹이 생기고,

        각 그룹으로 접근하여, 물건 별 데이터를 확인 할 수 있다. 

  4. 각 물건 별 데이터 요청 : https://m.land.naver.com/cluster/ajax/articleList 

  5. JSON 형태 데이터 파싱을 통한 원하는 데이터 추출 : Excel 형태

 


 

 1. 모바일 네이버 부동산 사이트에서 검색어(지역명) 입력 : https://m.land.naver.com/search/result/검색어 

import requests
from bs4 import BeautifulSoup
import json

keyword = "원하는 지역명"

url = "https://m.land.naver.com/search/result/{}".format(keyword)
res = requests.get(url)
res.raise_for_status()


soup = (str)(BeautifulSoup(res.text, "lxml"))

첫 번째 단계는 아주 간단하다. 검색할 지역명을 넣어주고, 다음 데이터 파싱을 위해 soup 객체에 할당하는 과정이 전부다.

 

2. 응답 메시지 내에서 필요 데이터 추출 및 요청 데이터 구성: lat, lon, z, cortarNo, rletTpCds, tradTpCds

#응답 메시지 속에서 원하는 데이터 얻기
#  filter: {
#             lat: '37.550985',
#             lon: '126.849534',
#             z: '12',
#             cortarNo: '1150000000',
#             cortarNm: '강서구',
#             rletTpCds: '*',
#             tradTpCds: 'A1:B1:B2'
#         },

value = soup.split("filter: {")[1].split("}")[0].replace(" ","").replace("'","")

lat = value.split("lat:")[1].split(",")[0]
lon = value.split("lon:")[1].split(",")[0]
z = value.split("z:")[1].split(",")[0]
cortarNo = value.split("cortarNo:")[1].split(",")[0]
rletTpCds = value.split("rletTpCds:")[1].split(",")[0]
tradTpCds = value.split("tradTpCds:")[1].split()[0]

# lat - btm : 37.550985 - 37.4331698 = 0.1178152
# top - lat : 37.6686142 - 37.550985 = 0.1176292
lat_margin = 0.118

# lon - lft : 126.849534 - 126.7389841 = 0.1105499
# rgt - lon : 126.9600839 - 126.849534 = 0.1105499
lon_margin = 0.111

btm=float(lat)-lat_margin
lft=float(lon)-lon_margin
top=float(lat)+lat_margin
rgt=float(lon)+lon_margin

# 최초 요청 시 디폴트 값으로 설정되어 있으나, 원하는 값으로 구성
rletTpCds="SG" #상가
tradTpCds="A1:B1:B2" #매매/전세/월세 매물 확인

응답메시지 속에 필요한 데이터인 filter: {} 값을 파싱하여 다음 요청에 필요한 각 필드 데이터를 추출하였다. 

검색 시, 조건에 해당하는 rletTpCds (상가 구분), tradTpCds (거래 유형) 에 대해서도 응답 메시지 내 데이터를 통해 아래와 같이 디테일한 정보를 확인 할 수 있다.

최초 요청 메시지에서 각 속성값 확인 가능

_tradTpCd = [{tagCd: 'A1', uiTagNm: '매매'}, 
             {tagCd: 'B1', uiTagNm: '전세'},  
             {tagCd: 'B2', uiTagNm: '월세'},
             {tagCd: 'B3', uiTagNm: '단기임대'}];
_rletTpCd = [{tagCd: 'APT', uiTagNm: '아파트'}, {tagCd: 'OPST', uiTagNm: '오피스텔'}, {tagCd: 'VL', uiTagNm: '빌라'},
             {tagCd: 'ABYG', uiTagNm: '아파트분양권'}, {tagCd: 'OBYG', uiTagNm: '오피스텔분양권'}, {tagCd: 'JGC', uiTagNm: '재건축'},
             {tagCd: 'JWJT', uiTagNm: '전원주택'}, {tagCd: 'DDDGG', uiTagNm: '단독/다가구'}, {tagCd: 'SGJT', uiTagNm: '상가주택'},
             {tagCd: 'HOJT', uiTagNm: '한옥주택'}, {tagCd: 'JGB', uiTagNm: '재개발'}, {tagCd: 'OR', uiTagNm: '원룸'},
             {tagCd: 'GSW', uiTagNm: '고시원'}, {tagCd: 'SG', uiTagNm: '상가'}, {tagCd: 'SMS', uiTagNm: '사무실'},
             {tagCd: 'GJCG', uiTagNm: '공장/창고'}, {tagCd: 'GM', uiTagNm: '건물'}, {tagCd: 'TJ', uiTagNm: '토지'},
             {tagCd: 'APTHGJ', uiTagNm: '지식산업센터'}];

 

  3. 재구성한 URL로 상가 물건 그룹 데이터 요청 : https://m.land.naver.com/cluster/clusterList

      : 상가 물건 그룹?
      - 앞선 포스팅에서 보았던 것처럼 상가를 처음 검색하면 매물 목록이 아니라 원형 형태의 데이터 그룹이 생기고,

        각 그룹으로 접근하여, 물건 별 데이터를 확인 할 수 있다

 

# clusterList?view 를 통한 그룹(단지)의 데이터를 가져온다.
remaked_URL = "https://m.land.naver.com/cluster/clusterList?view=atcl&cortarNo={}&rletTpCd={}&tradTpCd={}&z={}&lat={}&lon={}&btm={}&lft={}&top={}&rgt={}"\
     .format(cortarNo, rletTpCds, tradTpCds, z, lat, lon,btm,lft,top,rgt)

res2 = requests.get(remaked_URL)
json_str = json.loads(json.dumps(res2.json()))

 2번에서 구성한 데이터를 활용하여 상가 물건 그룹 데이터를 요청할 수 있다.

[그림 1] clusterList 요청으로 원형 형태의 물건 그룹 정보 확인 가능

응답 메시지 속 JSON 형태의 데이터를 확인해보면 JSON 의 ['data']['ARTICLE'] 값을 통해 상가 물건 그룹 데이터를 확인 할 수 있다. 
# 2/4 포스팅과 캡쳐의 시간이 다름에 따라 일부 매물의 수가 다를 수 있음

 

우린 여기에서 이 데이터를 활용하여, 다음 각 물건 별 데이터 요청을 위한 추가 값을 확인 할 수 있다. 

[그림 2] 각 그룹의 데이터를 활용하여 물건 별 데이터 요청 속성값 확인

 

 

  4. 각 물건 별 데이터 요청 : https://m.land.naver.com/cluster/ajax/articleList 

values = json_str['data']['ARTICLE']

# 큰 원으로 구성되어 있는 전체 매물그룹(values)을 load 하여 한 그룹씩 세부 쿼리 진행
for v in values:
    lgeo = v['lgeo']
    count = v['count']
    z2 = v['z']
    lat2 = v['lat']
    lon2 = v['lon']

    len_pages = count / 20 + 1
    for idx in range(1, math.ceil(len_pages)):
        
        remaked_URL2 = "https://m.land.naver.com/cluster/ajax/articleList?""itemId={}&mapKey=&lgeo={}&showR0=&" \
               "rletTpCd={}&tradTpCd={}&z={}&lat={}&""lon={}&totCnt={}&cortarNo={}&page={}"\
            .format(lgeo, lgeo, rletTpCds, tradTpCds, z2, lat2, lon2, count,cortarNo, idx)

 

 5. JSON 형태 데이터 파싱을 통한 원하는 데이터 추출

[그림 3] acticleList 요청에 대한 응답 JSON 형태

마지막 단계에서 articleList 요청을 통해서 각 매물 별 요청 진행 및 원하는 데이터를 얻을 수 있다.

코드는 아래와 같이 구성할 수 있다.

atclNo = v['atclNo']        # 물건번호
rletTpNm = v['rletTpNm']    # 상가구분
tradTpNm = v['tradTpNm']    # 매매/전세/월세 구분
prc = v['prc']              # 가격
spc1 = v['spc1']            # 계약면적(m2) -> 평으로 계산 : * 0.3025
spc2 = v['spc2']            # 전용면적(m2) -> 평으로 계산 : * 0.3025
hanPrc = v['hanPrc']        # 보증금                
rentPrc = v['rentPrc']      # 월세
flrInfo = v['flrInfo']      # 층수(물건층/전체층)
tagList = v['tagList']      # 기타 정보
rltrNm = v['rltrNm']        # 부동산
detaild_information = "https://m.land.naver.com/article/info/{}".format(atclNo)

사실 여기까지가 상가 매물 분석 및 크롤링의 모든 단계이다. 

 

여기에 필자는 사용성 측면의 용이성을 위해 아래와 같이 간단히 GUI 형태의 프로그램을 작성하였다. 

내용은 지금까지 작성한 절차를 그대로 적용하였으며, UI 요소만 적용되었다. 

 

마지막 단계에서는 tkinter 를 통해서 지금까지 작성한 내용을 쉽게 사용할 수 있도록 GUI 프로그램 작성에 대한 포스팅을 진행해보겠다. 

 

[그림 4] tkinter 를 활용한 부동산 상가 매물 검색 프로그램 GUI 버전

https://cocoabba.tistory.com/59

 

[PYTHON] 네이버 부동산 상가 매물 크롤링하기(4/4)

앞선 포스팅 1~3에서 python을 이용하여 네이버 부동산 상가 매물 크롤링을 하기 위한 과정을 세번째 단계로 정리하여 포스팅 하였다. 하지만 이렇게 코드로는 사용성이 낮아지는 부분이 있어서,

cocoabba.tistory.com

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함