본문 바로가기
AI/자연어처리

[생활속의 IT] 자연어 처리#5 - 직방 부동산 평가 크롤링하기

by 생활속의 IT램프 2020. 3. 24.

seoul.py
0.00MB

[이전 글 보기]

2020/03/22 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#1 - 아나콘다 설치하기

2020/03/22 - [AI/자연어처리] - [생활속의 IT] 자연어 처리 - 참고) Jupyter의 개념

2020/03/23 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#2 - 크롤러 만들기

2020/03/23 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#3 - 직방의 지리정보 Geohash 이해하기

2020/03/24 - [AI/자연어처리] - [생활속의 IT] 자연어 처리#4 - 직방 아파트ID 얻기

 

이제 직방에서 전국 아파트 ID를 얻는것까지 성공했으니

본격 아파트 평가데이터를 크롤링해보도록 하겠습니다.

 

1. 평가 데이터 구성 확인하기

 

2. 평가 데이터 수집하여 CSV로 만들기

 

3. 결과 확인하기

 

-----------------------------------------------------------------------------------------------------------------------------------

 

1. 평가 데이터 구성 확인하기

 

우선 아파트 ID를 하나 줘서 평가데이터가 어떻게 구성되어 있는지 탐색해보도록 하겠습니다.

주피터에서 아래와 같이 입력하고 돌려봅니다.

 

1
2
3
4
5
6
7
8
9
10
import requests 
import json 
 
danjiId=18433 
url = "https://apis.zigbang.com/property/apartments/{}/reviews/v1".format(danjiId) 
 
if req.status_code == 200
    data = json.loads(req.text) 
    print(data)

 

 

json 정리해서 확인해보면 아래와 같은데 왼쪽의 data 항목을 펼쳤을 때 오른쪽과 같이 나타납니다. 

 

 

 

Score가 있고 desc에 상세 평가 데이터가 적혀있습니다.

또한 교통점수, 관리점수, 주변환경, 거주환경까지도 점수를 주고 있습니다.

직방에서 본 리뷰 내용과 동일하네요.

 

 

이제 어떤 데이터를 가져올지 정해야 합니다.

그리고 CSV로 만들기 위해 저장하는 형태도 결정해야 합니다.

저는 이렇게 만들겁니다.

 

컬럼 목록

danjiId: 아파트 단지의 ID

name(APT): 아파트 단지 명

age

sex

Married

ResidenceType: 자가 거주일 경우 점수를 더 높게 줄 것 같습니다. 이런 경향을 확인하기 위해 일단 수집해봅니다.

Score: 전체 점수

desc: 전체 평점

trafficDesc

trafficScore

aroundScore

aroundDesc

careScore

careDesc

residentScore

residentDesc

 

 

2. 평가 데이터 수집하여 CSV 만들기

리뷰 데이터의 구성을 확인했으니 그럼 코딩을 시작해보겠습니다.

함수는 4개를 만들었습니다.

 

(1) 함수#1: 아파트 ID 얻어오기

5레벨의 geohash값을 인자로 주면 그 안의 단지ID를 리스트로 리턴해주는 함수입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def getDanjiList(geohash):
    req = requests.get(url)
    items = req.json()
 
    danjiList=[]
    if items["vrItems"!=[]:       ## vrItems 대상이 있으면 진행
        for i in items["vrItems"]:
            danjiList.append(i["areaDanjiId"])
    if items["recommendItems"!=[]:       ## recommend 대상이 있으면 진행
        for i in items["recommendItems"]:
            danjiList.append(i["areaDanjiId"])
    if items["items"!=[]:       ## Items 대상이 있으면 진행
        for i in items["items"]:
            danjiList.append(i["areaDanjiId"])
 
    danjiList = list(set(danjiList))
 
 
    return danjiList
 
 

 

(2) 리뷰 데이터 가져오기

함수#1에서 아파트ID를 가져왔으면 해당 ID를 인수로 주어 리뷰 데이터를 가져오는 함수입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def rmCR(text):
    while ("\n" in text or "\r" in text):
        text = text.replace("\n"," ")
        text = text.replace("\r"" ")
    return text
 
 
def getReviewData(danjiId):
    reviewList=[]
 
    url = "https://apis.zigbang.com/property/apartments/{}/reviews/v1".format(danjiId)
    req_review = requests.get(url)
 
    if req_review.status_code == 200:
        review_data = json.loads(req_review.text)
        if review_data["summary"]["reviewCount"!= 0:                  # 리뷰가 없는 아파트는 스킵
            for j in review_data["data"]:
                reviewList.append([danjiId, review_data["summary"]["danjiName"], j["age"], j["sex"],
                                    j["residenceType"], j["married"], j["score"], rmCR(j["desc"]), j["trafficScore"],
                                    rmCR(j["trafficDesc"]),
                                    j["aroundScore"], rmCR(j["aroundDesc"]), j["careScore"], rmCR(j["careDesc"]),
                                    j["residentScore"], rmCR(j["residentDesc"])])
 
    return reviewList
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

코드를 보면 rmCR 이라는 함수를 또 만들었습니다.

리뷰 데이터에는 \r이나 \n이 섞여있는 경우 CSV파일에서 줄넘어가기가 되기 때문에

이것을 없애주는 함수를 만들었습니다. (\r이나 \n 은 캐리지 리턴이라고 합니다)

 

(3) CSV파일로 만들기

리뷰가 담긴 리스트를 주면 {geohash명}.csv 이름으로 CSV파일을 생성하는 함수입니다.

 

1
2
3
4
5
6
7
8
def makeCSV(geohashName, reviewList):
    fileName = geohashName + ".csv"
    f = open(fileName, 'w', encoding='utf-8', newline='')
    wr = csv.writer(f)
    for i in reviewList:
        wr.writerow(i)
    f.close()
    print(fileName+" has been created")

 

(4) 5레벨 Geohash 가져오기

 

1
2
3
4
5
6
7
8
9
10
11
def getHigherGeohash(strgh):        # string 형태의 geohash 입력시 상위 레벨의 geohash 32개를 리스트로 전달
    returnList=[]
    for i in range(10):
        returnList.append(strgh+str(i))
    startIdx = ord('b')
    endIdx = ord('z')
    for i in range(startIdx, endIdx + 1):
        if (chr(i) != 'i' and chr(i) != 'l' and chr(i) != 'o'):
            returnList.append(strgh + chr(i))
 
    return returnList
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

우리는 3레벨 geohash 값 4개를 주어 4096 개의 5레벨 geohash를 얻어올 예정입니다.

이제 본문입니다.

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
geohash = ['wyd','wye','wy6','wy7']
tmp = []
for i in geohash:
    tmp4Lv=getHigherGeohash(i)
    for j in tmp4Lv:
        tmp5Lv=getHigherGeohash(j)
        tmp.append(tmp5Lv)
totalGeohash = []
for i in tmp:
    totalGeohash+=i
 
 
 
for i in totalGeohash:
    DanjiListPerGeohash = getDanjiList(i)        # 5레벨 Geohash별로 처리
    reviewPerGeohash=[]
    for j in DanjiListPerGeohash:
        tmpList = getReviewData(j)
        if len(tmpList) > 0:
            for z in tmpList:
                reviewPerGeohash.append(z)
    if len(reviewPerGeohash) > 0:           # 해당 5레벨 geohash에 리뷰가 1개라도 있으면
        reviewPerGeohash.insert(0,["danji_id""danji_name""age""sex""residenceType""married""totalScore",
                        "totalDesc""trafficScore""trafficDesc""aroundScore",
                        "aroundDesc""careScore""careDesc""residentScore""residentDesc"])
 
        makeCSV(i,reviewPerGeohash)
    else:                                   # 리뷰가 하나도 없으면
        print(i+" doesn't have any review data")
 

 

작성한 소스코드는 첨부파일에 올려놓겠습니다. (파이썬 3.7)

 

3. 결과 확인하기

 

돌리면 5레벨의 geohash별로 전국 아파트의 리뷰데이터가 담긴 CSV를 떨구게 됩니다.

참고로 시간이 매우 오래 걸립니다. (정확히 재보진 않았지만 3시간 이상 걸린 듯 합니다)

결과는 아래와 같이 가상환경 홈디렉토리에 파일들이 보입니다.

 

현재 기준 약 480개의 geohash 데이터가 만들어졌고 크기는 약 90MB 입니다.

열어서 잘 들어갔는지 확인해보겠습니다.

액셀로 열 때는 그냥 클릭해서 열지말고 아래와 같이 데이터 --> 텍스트/CSV에서 열도록 합니다.

 

데이터가 많이 담긴 wydq5 파일을 열어보겠습니다.

 

유니코드는 반드시 UTF-8로 열어야 안깨져 보이게 됩니다.

이제 로드 버튼을 누르면 아래와 같이 잘 들어간 것을 확인할 수 있습니다.

 

총 라인수는 2749 라인이고 파일 크기는 2,784KB 입니다.

대략 1라인당 1KB 정도 하는듯 합니다.

크롤링 결과 모인 파일 크기가 약 90MB 이므로 약 90,000 라인이 있을거라 예상할 수 있겠습니다.

(1KB * 90,000 = 90MB)

 

이제 전체 과정 중 수집을 마쳤습니다.

다음은 모델생성을 위한 전처리 과정을 보도록 하겠습니다.

댓글