Web Crawling(웹 크롤링)_동적 페이지_직방 원룸 정보 (python)

juyeon·2022년 8월 5일
0

크롤링

목록 보기
6/13

직방 원룸 정보

Get, Post 방식 둘다, 개발자 도구 이용

무엇이 필요한가?

  • 동 이름
  • 원룸의 위치
  • 원룸 매물 정보

직방 > 지역 검색 > 원룸 정보

: '동 이름'을 넣으면 그 동의 원룸 정보를 추출하고 싶다.

크롤링 절차

  • 3번의 request가 필요함
import requests
import pandas as pd

1. 동이름으로 원룸의 위도와 경도을 받기(1번째 request)

addr = "광주시 신안동" # '광주광역시 신안동'은 검색에 안 나온다!
url = f"https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=원룸"
response = requests.get(url)
data = response.json()["items"][0] # dict로 바꿔주고, itmes에서 0번째 인덱스만.
lat, lng = data["lat"], data["lng"] # 위도, 경도 값 가져옴

  • 이렇게 프리뷰로 원하는 정보가 어떻게 속해있는지 알 수 있다.

2. 위도와 경도로 그 근방을 다 볼 순 없을까?: geohash 사용하기

  • 위도와 경도는 '점'에 해당한다. 이 '점'을 '범위' 값으로 전환하자
  • 직방의 경우 items?deposit~ 에 geohash가 있더라 > 어? geohash가 뭐지? > 찾아보니,,,
    • geohash란, 사각형의 격자구조를 이용하여 지구상의 위치를 고유하게 식별할 수 있는 고유 지리 ID
    • 1) 계층구조를 가진다.
    • 2) 하위 레벨은 상위레벨의 문자열을 포함한다.
    • 3) precision이 커질수록 영역은 작아진다.


!pip install geohash2
import geohash2

geohash = geohash2.encode(lat, lng, precision=5)

3. 범위 값으로 원룸 매물 아이디 값을 수집한다(2번째 request)

# \(역슬래시): 개행하기 위해서. 뒤에 공백문자 있으면 에러남
url = f"https://apis.zigbang.com/v2/items?deposit_gteq=0&domain=zigbang\
&geohash={geohash}&needHasNoFiltered=true&rent_gteq=0&sales_type_in=전세|월세&service_type_eq=원룸"

response = requests.get(url)
items = response.json()["items"]

ids = [item["item_id"] for item in items]

4. 아이디 값으로 원룸 매물 정보를 추출한다(3번째 request)

Post 방식임!!

  • get 방식은 url안에 데이터가 있지만, post 방식은 url 안에 데이터가 없기 때문에 params로 따로 데이터를 만들어서 설정해줘야 함

Request Payload에 params(파라미터)가 나와있음

무슨 columns 를 추출할까 살펴보기

  • 데이터가 990 몇개 넘으면 못 가져오니까, 900개까지만 설정
url = "https://apis.zigbang.com/v2/items/list"
params = {
    "domain": "zigbang",
    "withCoalition": "true",
    "item_ids": ids[:900]
}
response = requests.post(url, params)

items = response.json()["items"]
colums = ["item_id", "address1", "sales_type", "deposit", "rent", "manage_cost"]

df = pd.DataFrame(items)[colums]

모듈로 만든다면?

  • df[df["address1"].str.contains(addr)].reset_index(drop = True)
    : 이게 없으면, 범위값으로 출력이 되기 때문에 근처 다른 동까지 나와버림! 우리는 addr에 지정된 동만 보고 싶기 때문~
%%writefile zigbang.py

import requests
import pandas as pd
import geohash2

def oneroom(addr): # 동이름 넣으면 정보 반환하도록
    url = f"https://apis.zigbang.com/v2/search?leaseYn=N&q={addr}&serviceType=원룸"
    response = requests.get(url)
    data = response.json()["items"][0]
    lat, lng = data["lat"], data["lng"]
    geohash = geohash2.encode(lat, lng, precision=5)

    url = f"https://apis.zigbang.com/v2/items?deposit_gteq=0&domain=zigbang\
&geohash={geohash}&needHasNoFiltered=true&rent_gteq=0&sales_type_in=전세|월세&service_type_eq=원룸"
    response = requests.get(url)
    items = response.json()["items"]
    ids = [item["item_id"] for item in items]

    url = "https://apis.zigbang.com/v2/items/list"
    params = {
        "domain": "zigbang",
        "withCoalition": "true",
        "item_ids": ids[:900]
    }
    response = requests.post(url, params)

    items = response.json()["items"]
    colums = ["item_id", "sales_type", "deposit", "rent", "address1", "manage_cost"]
    df = pd.DataFrame(items)[colums]
    df = df[df["address1"].str.contains(addr)].reset_index(drop = True)
    df = df.rename(columns = {"address1": "주소", "sales_type": "유형","deposit": "보증금", "rent": "월세", "manage_cost": "관리비"})
        
    return df

꿀팁

행열이 다 보이지 않고, 끊겨서 보인다?!

: #max_rows, max_columns 설정

pd.options.display.max_columns
pd.options.display.max_columns = 50

requests.get(url) # <Response [403]>가 뜸.

  • user-agent가 파이썬으로 인식되어서.. 서버가 정상적인 사용자가 아니라고 판단하고 차단함.

  • 원래는 user-agent는 브라우저(뭐 사파리라던가..)여야함.

  • 이걸 구분하는 방법은 직접 해보는 수밖에 없음

  • 아래 내리면 request headers가 있음

user-agent 만으로는 여전히 차단된다면? 그럼 다른 데이터를 넣어보자!

  • 보통 cookie, referer, user-agent 선에서 됨
profile
내 인생의 주연

0개의 댓글