2020/01/21 - [Back-end/Python] - [크롤링] 직방에서 방찾기 (1) - 데이터 분석
지난 포스트에서 직방에서 방정보를 수집하기위한 API서버의 URL정보들을 수집했다. API서버에서 바로 데이터를 받아오는 방식으로 크롤러를 만들것이기 때문에 BS4와 같은 별도의 Parser는 사용하지 않을 것이며 Reuqests 라이브러리 하나로 간단하게 만들어 볼 것이다.
1. 라이브러리 설치.
1-1. requests 라이브러리 설치.
> pip install requests
2. 매물목록 데이터 확인.
2-1. 데이터 확인용 크롤러 생성.
- crawl_zigbang.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# crawl_zigbang.py
import requests
import json
from pprint import pprint
ROOM_LIST_URL="https://apis.zigbang.com/v3/items/ad/96?subway_id=96&radius=1&sales_type=&deposit_s=0&rent_s=0&floor=1~%7Crooftop%7Csemibase&domain=zigbang&detail=false"
ROOM_INFO_URL="https://apis.zigbang.com/v2/items/19854111"
SUBWAY_LIST_URL="https://apis.zigbang.com/property/biglab/subway/all?"
req = requests.get( ROOM_LIST_URL )
if req.status_code == 200:
data = json.loads( req.text )
print( data.keys() )
print( data['total_count'], len(data['list_items']) )
pprint( data['list_items'][:5] )
|
cs |
- 3 ln: 파이썬에서 Json 데이터를 조작하기 위한 내장 라이브러리.
- 4 ln: Dict, List 등의 데이터를 출력할 때, 보기좋게 만들어주는 내장 라이브러리.
- 6~8 ln: 지난 포스트에서 수집한 RequestURL.
- 10 ln: GET 방식으로 매물목록을 요청.
- 12 ln: 요청이 성공했을 경우.
- 13 ln: 문자열로된 Json을 Dictionary로 파싱.
2-2. 실행결과.
- list_items에 매물목록 정보와 공인중개사의 정보가 있음.
- 매물의 상세 정보를 요청하기위해서 item_id를 추출.
* data["list_items"]["simple_item"]["item_id"]
- 공인중개사 정보는 필요없으므로 버림.
2-3. 매물목록에서 매물의 ID만 추출.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# crawl_zigbang.py
import requests
import json
from pprint import pprint
ROOM_LIST_URL="https://apis.zigbang.com/v3/items/ad/96?subway_id=96&radius=1&sales_type=&deposit_s=0&rent_s=0&floor=1~%7Crooftop%7Csemibase&domain=zigbang&detail=false"
ROOM_INFO_URL="https://apis.zigbang.com/v2/items/19854111"
SUBWAY_LIST_URL="https://apis.zigbang.com/property/biglab/subway/all?"
req = requests.get( ROOM_LIST_URL )
if req.status_code == 200:
data = json.loads( req.text )
item_ids = [ item["simple_item"]["item_id"] for item in data["list_items"] if 'ad_agent' not in item ]
pprint( item_ids[:5] )
|
cs |
- 15 ln: 공인중개사 정보를 제외하고 item_id만 추출.
2-4. 실행결과.
- 매물의 ID 정보만 추출성공.
2-5. 지하철 정보와 매물의 상세정보도 위와 같이 분석하면서 필요한 데이터를 어떻게 수집할지 분석해야함.
4. 최종 소스.
4-1. 지하철역을 중심으로 매물의 상세정보 수집하는 크롤러.
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# crawl_zigbang.py
import requests
import json
from pprint import pprint
SUBWAY_LIST_URL="https://apis.zigbang.com/property/biglab/subway/all?"
ROOM_LIST_URL="https://apis.zigbang.com/v3/items/ad/{subway_id}?subway_id={subway_id}&radius=1&sales_type=&deposit_s=0&rent_s=0&floor=1~%7Crooftop%7Csemibase&domain=zigbang&detail=false"
ROOM_INFO_URL="https://apis.zigbang.com/v2/items/{room_id}"
# 지하철 정보 수집
def getSubwayId( subway_name ):
REQUEST_URL = SUBWAY_LIST_URL
req = requests.get( SUBWAY_LIST_URL )
if req.status_code == 200:
data = json.loads( req.text )
subway_info = [ item['id'] for item in data if item['name'] == subway_name ]
if len(subway_info) > 0:
return subway_info[0]
return None
# 매물 목록 수집
def getRoomList( subway_id ):
REQUEST_URL = ROOM_LIST_URL.format( subway_id=subway_id )
req = requests.get( REQUEST_URL )
if req.status_code == 200:
data = json.loads( req.text )
return [ item["simple_item"]["item_id"] for item in data["list_items"] if 'ad_agent' not in item ]
return list()
# 매물 상세정보 수집
def getRoomInfo( room_id ):
REQUEST_URL = ROOM_INFO_URL.format( room_id=room_id )
req = requests.get( REQUEST_URL )
if req.status_code == 200:
data = json.loads( req.text )
return data
return None
# 매물 상세정보를 입맞대로 파싱
def parseRoomInfo( room_info, find_text=None ):
parsed_data = {
"url": 'https://www.zigbang.com/home/oneroom/items/{}'.format( room_info["item"].get("item_id") )
, "item_id": room_info["item"].get("item_id")
, "제목": room_info["item"].get("title")
, "주소": ( room_info["item"].get("local1"), room_info["item"].get("local2"), room_info["item"].get("local3"), room_info["item"].get("local4") )
, "설명": {
"요약": room_info["item"].get("agent_comment")
, "상세내용": room_info["item"].get("description")
}
, "정보": {
"사진": room_info["item"].get("images")
, "전세/월세": room_info["item"].get("sales_type")
, "방": room_info["item"].get("service_type")
, "층수": "{}/{}".format( room_info["item"].get("floor"), room_info["item"].get("floor_all") )
}
, "비용": {
"관리비": room_info["item"].get("manage_cost")
, "보증금액": room_info["item"].get("보증금액")
, "월세금액": room_info["item"].get("월세금액")
}
, "면적": {
"공급면적_m2": room_info["item"].get("공급면적_m2")
, "대지권면적_m2": room_info["item"].get("대지권면적_m2")
, "전용면적_m2": room_info["item"].get("전용면적_m2")
}
, "중개사": room_info["agent"].get("owner")
}
if find_text is not None:
if parsed_data["설명"]["상세내용"].find( find_text ) > 0:
return parsed_data
return None
return parsed_data
# 지하철 정보 수집
subway_name = '수유역'
subway_id = getSubwayId( subway_name )
if subway_id is not None:
# 매물 목록 수집 요청
room_list = getRoomList( subway_id ) # 수유역=96
for room_id in room_list:
# 매물 상세 정보 수집 요청
room_info = getRoomInfo( room_id )
# 매물 상세정보를 입맞대로 파싱
parend_room_info = parseRoomInfo( room_info, '대출' )
if parend_room_info is not None:
pprint( parend_room_info )
else:
print( "{}을 찾을 수 없습니다. {}".format( subway_name, subway_id ) )
|
cs |
- 최대한 이해하기 쉽게 변수명과 함수명으로 만들었으니 천천히 보면서 이해해보는걸 추천함.
4-2. 실행.
> python crawl_zigbang.py
4-3. 실행결과.
- 위와같이 데이터가 잘 수집되는 것을 확인할 수 있음.
- 조회하는 데이터의 갯수를 제한하지 않으면 조회할 때마다 100개가 넘은 데이터를 요청함.
- 따라서, 주기적으로 수집하고자 하는 경우에는 Database나 File에 결과와 수집이력을 저장하여 중복수집되지 않도록 로직을 변경해야함.
5. 마치며.
- 지금까지 직방에서 지하철역을 기준으로 매물을 수집하는 크롤러를 작성해보았다. 예제는 단순히 이런식으로 데이터를 수집할 수 있다는 것을 보여주는 것이기 때문에 저장소는 따로 설정하지 않았다. 수집된 데이터는 취향에 따라 가공해서 쓰는 것을 추천한다.
'Back-end > Python' 카테고리의 다른 글
[Telegram] 무작정 시작하기 (1) - 설치 및 실행 (0) | 2020.01.30 |
---|---|
[Celery] 무작정 시작하기 (5) - Monitoring (0) | 2020.01.28 |
[크롤링] 직방에서 방찾기 (1) - 데이터 분석 (2) | 2020.01.21 |
[Celery] 무장적 시장하기 (4) - Group과 Chord (0) | 2020.01.20 |
[Celery] 무작정 시작하기 (3) - Chain (0) | 2020.01.20 |
댓글