에어비앤비 데이터에 액세스하는 것은 부동산 시장 분석, 임대료 역학 조사, 경쟁사 분석, 후기 및 평점 평가에 매우 중요합니다. 이는 웹 데이터를 스크래핑하여 달성할 수 있습니다. 그러나 스크래핑은 사이트 이용 약관을 위반할 수 있으므로 이 데이터에 액세스하는 것은 어려울 수 있습니다.
다음 가이드에서는 파이썬과 셀레늄을 사용해 에어비앤비 숙소의 데이터를 추출하는 웹 스크레이퍼를 개발하는 방법을 단계별로 살펴보겠습니다. 이 가이드에서는 플랫폼에서 부과하는 잠재적인 차단 및 제한을 피하는 방법도 다룹니다.
웹 스크레이퍼를 만드는 첫 번째 단계는 웹사이트의 구조가 자주 변경될 수 있으므로 관심 있는 웹 페이지에 액세스하는 방법을 이해하는 것입니다. 사이트의 구조에 익숙해지려면 브라우저의 개발자 도구를 사용하여 웹 페이지의 HTML을 검사할 수 있습니다.
개발자 도구에 액세스하려면 웹페이지를 마우스 오른쪽 버튼으로 클릭하고 '검사'를 선택하거나 바로가기를 사용하세요:
각 목록 컨테이너는 다음과 같은 속성을 가진 div 요소로 감싸집니다: class="g1qv1ctd".
'위치'를 클릭하고 '영국 런던'을 입력하면 런던에서 제공되는 위치에 액세스할 수 있습니다. 웹사이트는 체크인 및 체크아웃 날짜를 추가할 것을 제안합니다. 이를 통해 객실 가격을 계산할 수 있습니다.
이 페이지의 URL은 다음과 같이 표시됩니다:
url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"
검색 페이지에서 제품 목록 데이터의 다음 속성을 스크랩합니다:
에어비앤비 데이터에 대한 웹 스크래핑을 시작하려면 먼저 개발 환경을 설정해야 합니다. 이를 위한 단계는 다음과 같습니다:
가상 환경을 사용하면 서로 다른 프로젝트에 대해 Python 패키지와 해당 종속성을 분리할 수 있습니다. 이렇게 하면 충돌을 방지하고 각 프로젝트에 올바른 종속성이 설치되어 있는지 확인할 수 있습니다.
관리자 권한으로 명령 프롬프트를 열고 다음 명령을 실행하여 "venv"라는 새 가상 환경을 만듭니다:
python -m venv venv
가상 환경을 활성화합니다:
venv\Scripts\activate
터미널을 열고 다음 명령을 실행하여 "venv"라는 새 가상 환경을 만듭니다:
sudo python3 -m venv venv
가상 환경을 활성화합니다:
source venv/bin/activate
가상 환경을 비활성화하려면 다음 명령을 실행하면 됩니다:
deactivate
이제 가상 환경이 설정되었으므로 필요한 라이브러리를 설치할 수 있습니다.
활성화된 가상 환경 내에서 다음 명령을 실행하여 필요한 라이브러리를 설치합니다:
pip install selenium beautifulsoup4 lxml seleniumwire
셀레늄을 사용하려면 선택한 브라우저와 인터페이스할 수 있는 드라이버가 필요합니다. 이 가이드에서는 Chrome을 사용합니다. 그러나 선택한 브라우저에 적합한 웹 드라이버를 설치했는지 확인하세요.
다운로드가 완료되면 드라이버가 시스템의 PATH 환경 변수로 액세스할 수 있는 디렉터리에 배치되어 있는지 확인하세요. 이렇게 하면 Selenium이 드라이버를 찾아 브라우저를 제어할 수 있습니다.
Python 파일의 시작 부분에서 Seleniumwire 및 BeautifulSoup 라이브러리를 가져옵니다. 이렇게 하면 됩니다:
from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random
또한 다양한 유틸리티를 위해 `random`, `time`, `csv` 라이브러리를 가져올 것입니다.
다음으로, 에어비앤비에 의해 차단되지 않도록 프록시 목록을 정의합니다. 프리미엄 프록시 없이 요청을 보내려고 하면 '액세스 거부' 응답이 표시될 수 있습니다.
다음과 같이 프록시를 설정할 수 있습니다:
# 프록시 목록
proxies = [
"username:password@Your_proxy_IP_Address:Your_proxy_port1",
"username:password@Your_proxy_IP_Address:Your_proxy_port2",
"username:password@Your_proxy_IP_Address:Your_proxy_port3",
"username:password@Your_proxy_IP_Address:Your_proxy_port4",
"username:password@Your_proxy_IP_Address:Your_proxy_port5",
]
"Your_proxy_IP_Address" 및 "Your_proxy_port"를 프록시 판매자로부터 얻은 실제 프록시 주소로 바꾸고 "username" 및 "password" 값도 실제 자격 증명으로 바꾸어야 합니다.
프록시 로테이션은 웹 스크래핑의 중요한 측면입니다. 웹사이트는 동일한 IP 주소에서 여러 요청을 받으면 봇과 스크래퍼에 대한 액세스를 차단하거나 제한하는 경우가 많습니다. 다른 프록시 IP 주소를 순환하여 사용하면 탐지를 피하고, 여러 오가닉 사용자로 표시되며, 웹사이트에 구현된 대부분의 스크래핑 방지 조치를 우회할 수 있습니다.
프록시 로테이션을 설정하려면 '랜덤' 라이브러리를 가져옵니다. 또한 목록에서 프록시를 선택하는 `get_proxy()` 함수를 정의합니다. 이 함수는 random.choice() 메서드를 사용하여 프록시 목록에서 프록시를 무작위로 선택하고 선택한 프록시를 반환합니다.
def get_proxy():
return random.choice(proxies)
다음으로 `listings()`라는 메인 함수를 정의합니다. 여기에서 "ChromeDriver"를 설정할 것입니다. 이 함수는 셀레늄을 사용하여 부동산 목록 페이지를 탐색하고 페이지가 로드될 때까지 기다린 다음 Beautiful Soup을 사용하여 HTML을 구문 분석합니다.
def listings(url):
proxy = get_proxy()
proxy_options = {
"proxy": {
"http": f"http://{proxy}",
"https": f"http://{proxy}",
"no_proxy": "localhost,127.0.0.1",
}
}
chrome_options = Options()
chrome_options.add_argument("--headless")
s = Service(
"C:/Path_To_Your_WebDriver"
) # ChromeDriver 경로로 바꾸기
driver = webdriver.Chrome(
service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
)
driver.get(url)
time.sleep(8) # 웹사이트의 로딩 시간에 따라 조정
soup = BeautifulSoup(driver.page_source, "lxml")
driver.quit()
여기서는 임의의 프록시를 선택하고 프록시 옵션을 설정하는 것으로 시작합니다. 이 옵션은 프록시 서버를 사용하도록 웹드라이버를 구성하는 데 사용됩니다. 다음으로 Chrome 옵션을 설정합니다. 헤드리스 모드에서 브라우저를 실행하려면 --headless 인수를 추가하면 브라우저가 그래픽 사용자 인터페이스 없이 백그라운드에서 실행됩니다.
그런 다음 서비스, 셀레늄 와이어 옵션 및 Chrome 옵션으로 웹드라이버를 초기화합니다. 그런 다음 웹드라이버를 사용하여 지정된 URL로 이동합니다. 페이지가 완전히 로드될 수 있도록 8초의 대기 시간을 추가한 다음 Beautiful Soup을 사용하여 반환된 HTML을 파싱합니다. 구문 분석이 완료되면 웹드라이버를 닫습니다.
HTML 콘텐츠를 성공적으로 확보했다면 다음 단계는 각 목록에 대한 관련 데이터를 추출하는 것입니다. BeautifulSoup을 사용하면 HTML 구조를 쉽게 탐색하고 목록 정보가 포함된 요소를 찾을 수 있습니다.
먼저 페이지의 모든 숙소 요소를 식별합니다. 이러한 요소에는 목록 URL, 제목, 설명, 평점, 가격 및 추가 정보 등 관심 있는 데이터가 포함되어 있습니다.
listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:
이 코드는 BeautifulSoup의 find_all() 메서드를 사용하여 "g1qv1ctd" 클래스를 가진 모든 div 요소를 찾습니다. 이러한 요소는 에어비앤비 페이지의 개별 숙소를 나타냅니다. 그런 다음 이러한 각 목록 요소를 반복하여 관련 데이터를 추출합니다.
발견된 각 목록 요소에 대해 목록의 URL을 추출합니다.
URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
"https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)
여기서는 'soup' 객체 내에서 'rfexzly' 클래스를 가진 앵커 태그를 검색합니다. 이 요소를 찾으면 'href' 속성(상대 URL이 포함된)을 추출하고 이를 기본 URL에 추가하여 전체 목록 URL을 만듭니다. 요소를 찾을 수 없으면 오류를 방지하기 위해 빈 문자열을 할당합니다.
먼저 각 숙소의 URL을 추출합니다. 이렇게 하면 나중에 필요한 경우 개별 리스팅 페이지를 방문할 수 있습니다.
title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
title_element.get_text(strip=True) if title_element else ""
)
제목은 클래스가 "t1jojoys"인 "div" 요소 안에 포함되어 있습니다. 이 요소의 텍스트 콘텐츠를 검색하여 선행 또는 후행 공백을 제거합니다. 요소를 찾을 수 없는 경우 빈 문자열이 저장됩니다.
Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
Description_element.get_text(strip=True) if Description_element else ""
)
제목 추출과 마찬가지로 이 코드는 클래스가 "t6mzqp7"인 스팬 요소를 찾습니다. 그런 다음 목록에 대한 간단한 설명이 포함된 이 요소의 텍스트 콘텐츠를 추출하고 정리합니다.
rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
rating_element.get_text(strip=True) if rating_element else ""
)
위 코드에서 볼 수 있듯이 클래스가 "ru0q88m"인 스팬 요소는 등급 값을 보유합니다. 이 값을 추출하여 불필요한 공백을 제거합니다.
마지막으로 리스팅의 가격을 추출합니다.
price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
f"{price_element.get_text(strip=True)} per night" if price_element else ""
)
이 코드는 현재 listing_element 내에서 클래스가 "_1y74zjx"인 요소를 찾습니다. 일반적으로 가격 정보가 포함된 이 요소를 찾으면 텍스트 내용을 추출하고 정리한 후 '1박당'을 추가하여 보다 유용한 가격 문자열을 구성합니다.
일부 목록에는 추가 정보를 추출할 수 있는 정보가 있을 수 있습니다.
listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
listing_info_element.get_text(strip=True) if listing_info_element else ""
)
aria-hidden="true" 속성을 가진 스팬 요소를 검색하여 목록에 대한 추가 정보를 찾습니다. 각 목록 요소에서 모든 관련 데이터를 추출한 후 수집한 데이터를 목록 목록에 추가합니다.
listings.append(listing_data)
모든 리스팅이 처리되면 추출된 데이터가 포함된 사전으로 표시된 리스팅 목록을 반환합니다.
return listings
에어비앤비 숙소 페이지에서 데이터를 성공적으로 스크랩했다면, 다음 중요한 단계는 향후 분석과 참조를 위해 이 중요한 정보를 저장하는 것입니다. 이 작업에는 csv 라이브러리를 사용합니다. 쓰기 모드에서 CSV 파일을 열고 csv.DictWriter 객체를 만듭니다. 그런 다음 헤더와 데이터를 파일에 씁니다.
airbnb_listings = listings(url)
csv_file_path = "proxy_web_listings_output.csv"
with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
fieldnames = [
"Listing URL",
"Title",
"Description",
"Rating",
"Price",
"Additional Listing information",
]
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for listing in airbnb_listings:
writer.writerow(listing)
print(f"Data has been exported to {csv_file_path}")
다음은 이 튜토리얼에 사용한 전체 코드입니다:
from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random
# 프록시 목록
proxies = [
"username:password@Your_proxy_IP_Address:Your_proxy_port1",
"username:password@Your_proxy_IP_Address:Your_proxy_port2",
"username:password@Your_proxy_IP_Address:Your_proxy_port3",
"username:password@Your_proxy_IP_Address:Your_proxy_port4",
"username:password@Your_proxy_IP_Address:Your_proxy_port5",
]
def get_proxy():
return random.choice(proxies)
def listings(url):
proxy = get_proxy()
proxy_options = {
"proxy": {
"http": f"http://{proxy}",
"https": f"http://{proxy}",
"no_proxy": "localhost,127.0.0.1",
}
}
chrome_options = Options()
chrome_options.add_argument("--headless")
s = Service(
"C:/Path_To_Your_WebDriver"
) # ChromeDriver 경로로 바꾸기
driver = webdriver.Chrome(
service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
)
driver.get(url)
time.sleep(8) # 웹사이트 로딩 시간에 따라 조정
soup = BeautifulSoup(driver.page_source, "lxml")
driver.quit()
listings = []
# 페이지에서 모든 목록 요소 찾기
listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:
# 각 리스팅 요소에서 데이터 추출
listing_data = {}
# 리스팅 URL
URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
"https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)
# 제목
title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
title_element.get_text(strip=True) if title_element else ""
)
# 설명
Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
Description_element.get_text(strip=True) if Description_element else ""
)
# 등급
rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
rating_element.get_text(strip=True) if rating_element else ""
)
# 가격
price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
f"{price_element.get_text(strip=True)} per night" if price_element else ""
)
# 추가 숙소 정보
listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
listing_info_element.get_text(strip=True) if listing_info_element else ""
)
# 목록에 목록 데이터 추가하기
listings.append(listing_data)
return listings
url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"
airbnb_listings = listings(url)
csv_file_path = "proxy_web_listings_output.csv"
with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
fieldnames = [
"Listing URL",
"Title",
"Description",
"Rating",
"Price",
"Additional Listing information",
]
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for listing in airbnb_listings:
writer.writerow(listing)
print(f"Data has been exported to {csv_file_path}")
이 코드의 이 부분은 스크랩된 데이터가 "proxy_web_listings_output.csv"라는 CSV 파일에 저장되도록 합니다.
스크래퍼의 결과는 아래와 같이 "proxy_web_listings_output.csv"라는 CSV 파일에 저장됩니다.
이 가이드에서는 파이썬을 사용해 에어비앤비 숙소의 데이터를 스크랩하여 가격, 예약 가능 여부, 후기 등 주요 세부 정보를 추출하는 방법을 효과적으로 설명합니다. 에어비앤비의 봇 방지 조치에 의해 차단되지 않도록 프록시를 사용하고 프록시를 교체하는 것이 중요하다는 점을 강조합니다.
댓글: 0