Thu thập dữ liệu danh sách Airbnb bằng Python

Bình luận: 0

Việc thu thập dữ liệu (web scraping) danh sách Airbnb bằng Python rất quan trọng để phân tích thị trường bất động sản, nghiên cứu biến động giá thuê, thực hiện phân tích cạnh tranh và đánh giá nhận xét cùng xếp hạng. Điều này có thể được thực hiện bằng các kỹ thuật scraping. Tuy nhiên, việc truy cập thông tin này có thể gặp khó khăn vì hành vi scraping có thể vi phạm điều khoản sử dụng của trang web.

Tiếp theo, chúng ta sẽ xem hướng dẫn từng bước về cách phát triển một web scraper sử dụng Python và Selenium để thu thập các danh sách trên Airbnb. Hướng dẫn này cũng sẽ đề cập đến cách tránh các chặn và hạn chế mà nền tảng có thể áp đặt.

Hiểu cấu trúc trang web của Airbnb

Bước đầu tiên khi tạo một web scraper là phải hiểu cách truy cập các trang web mà bạn quan tâm, vì cấu trúc của các trang web thường thay đổi. Để làm quen với cấu trúc của một trang, bạn có thể sử dụng công cụ dành cho nhà phát triển (Developer Tools) của trình duyệt để kiểm tra HTML của trang.

Để truy cập Developer Tools, nhấp chuột phải vào trang web và chọn “Inspect” hoặc sử dụng phím tắt:

  • CTRL+SHIFT+I cho Windows;
  • Option + ⌘ + I trên Mac.

Mỗi khung chứa danh sách được bọc trong một phần tử div với thuộc tính sau: class="g1qv1ctd”.

1.png

Bằng cách nhấp vào "location" và gõ "London, UK" chúng ta có thể truy cập vị trí được cung cấp ở London. Trang web gợi ý thêm ngày nhận phòng và trả phòng để có thể tính giá của các phòng.

2.png

URL cho trang này sẽ trông giống như sau:

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"

Từ trang tìm kiếm, chúng ta sẽ thu thập các thuộc tính sau của dữ liệu danh sách sản phẩm từ Airbnb:

  • URL;
  • Tiêu đề;
  • Mô tả;
  • Đánh giá;
  • Giá;
  • Thông tin bổ sung (Số giường và các ngày khả dụng).

3.png

Hướng dẫn từng bước để xây dựng chương trình scraping Airbnb

Để bắt đầu thu thập dữ liệu Airbnb bằng Python, trước tiên bạn cần thiết lập môi trường phát triển. Dưới đây là các bước thực hiện:

Bước 1: Tạo môi trường ảo (virtual environment)

Môi trường ảo cho phép bạn cô lập các gói Python và phụ thuộc của chúng cho từng dự án. Mỗi dự án sẽ có các phụ thuộc chính xác khi không có sự can thiệp giữa các dự án.

Tạo môi trường ảo trên Windows

Người dùng Windows có thể tạo một môi trường ảo tên là “venv” bằng cách mở Command Prompt với quyền quản trị và chạy lệnh:

python -m venv venv

Để kích hoạt môi trường ảo vừa tạo, chạy lệnh:

venv\Scripts\activate

Tạo môi trường ảo trên macOS/Linux

Mở terminal và thực thi lệnh dưới đây để thiết lập một môi trường ảo mới gọi là “venv”:

sudo python3 -m venv venv

Kích hoạt môi trường ảo:

source venv/bin/activate

Để hủy kích hoạt môi trường ảo, chỉ cần chạy lệnh sau:

deactivate

Bước 2: Cài đặt các thư viện cần thiết

Sau khi đã thiết lập môi trường ảo, bạn có thể cài đặt các thư viện cần thiết.

Hiểu về các thư viện:

  • Selenium: Là công cụ tuyệt vời để scraping Airbnb với Python, cho phép bạn điều khiển trình duyệt web một cách lập trình. Nó cho phép tương tác với trang—nhấn nút, điền biểu mẫu và điều hướng giống người dùng thực.
  • Seleniumwire: Thư viện này mở rộng Selenium bằng cách cho phép bạn chặn và kiểm tra các yêu cầu HTTP và tích hợp proxy vào hoạt động scraping.
  • BeautifulSoup4: Mục đích là giúp xử lý tài liệu HTML và XML. Nó giúp bạn trích xuất thông tin cụ thể từ các trang web một cách có cấu trúc và hiệu quả. Điều này sẽ hỗ trợ việc thu thập dữ liệu từ Airbnb.
  • lxml: Trình phân tích HTML và XML nhanh và mạnh mẽ, bổ sung cho BeautifulSoup.

Trong môi trường ảo đã kích hoạt, chạy lệnh sau để cài đặt các thư viện cần thiết:

pip install selenium beautifulsoup4 lxml seleniumwire

Trình điều khiển Selenium (Selenium drivers)

Selenium yêu cầu một driver để giao tiếp với trình duyệt đã chọn. Hướng dẫn này sẽ sử dụng Chrome. Tuy nhiên, hãy đảm bảo bạn đã cài đặt WebDriver phù hợp cho trình duyệt mà bạn chọn.

Sau khi tải xuống, đảm bảo đặt driver vào thư mục mà hệ thống của bạn có thể truy cập thông qua biến môi trường PATH. Điều này giúp Selenium tìm thấy driver và điều khiển trình duyệt.

Bước 3: Import các thư viện

Như đã đề cập ở trên, điều đầu tiên cần làm là import các thư viện Seleniumwire và BeautifulSoup vào file Python của bạn. Trông sẽ như sau:

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

Chúng ta cũng sẽ import các thư viện `random`, `time`, và `csv` cho các tiện ích khác nhau.

Bước 4: Tích hợp proxy

Tiếp theo, chúng ta định nghĩa một danh sách proxy để tránh bị Airbnb chặn. Khi gửi yêu cầu mà không có proxy chất lượng, bạn có thể gặp phản hồi "Access Denied".

4.png

Bạn có thể cấu hình proxy như sau:

# List of proxies
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",

]

Hãy chắc chắn tùy chỉnh các trường “Your_proxy_IP_Address” và “Your_proxy_port” với thông tin tương ứng từ proxy của bạn. Ngoài ra đừng quên thay các placeholder “username” và “password” bằng thông tin đăng nhập thực tế.

Bước 5: Xoay vòng proxy

Xoay vòng proxy là một bước quan trọng trong web scraping. Các trang web thường chặn hoặc hạn chế quyền truy cập của bot và scraper khi chúng nhận được nhiều yêu cầu từ cùng một địa chỉ IP. Bằng cách xoay vòng qua các địa chỉ IP proxy khác nhau, bạn có thể tránh bị phát hiện, xuất hiện như nhiều người dùng thật và vượt qua hầu hết các biện pháp chống scraping được triển khai trên trang web.

Để thiết lập xoay vòng, hãy import thư viện “random”. Chúng ta cũng định nghĩa một hàm `get_proxy()` để chọn một proxy từ danh sách. Hàm này chọn ngẫu nhiên một proxy bằng phương thức random.choice().

def get_proxy():
    return random.choice(proxies)

Bước 6: Thiết lập WebDriver

Tiếp theo, chúng ta định nghĩa hàm chính có tên `listings()`. Đây là nơi chúng ta thiết lập “ChromeDriver”. Hàm này sử dụng Selenium để điều hướng đến trang danh sách bất động sản, chờ trang tải và phân tích HTML bằng Beautiful Soup.

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"
    )  # Thay bằng đường dẫn ChromeDriver của bạn
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Điều chỉnh dựa trên thời gian tải trang

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

Để scrape Airbnb bằng Python, chúng ta bắt đầu bằng cách chọn ngẫu nhiên một proxy và thiết lập các tùy chọn. Những tùy chọn này sẽ được dùng để cấu hình webdriver. Tiếp theo, chúng ta thiết lập Chrome options. Thêm tham số --headless để chạy trình duyệt ở chế độ nền (không có giao diện đồ họa).

Sau đó khởi tạo webdriver với service, seleniumwire options và Chrome options. Webdriver được dùng để điều hướng đến URL đã cho. Chúng ta thêm thời gian chờ 8 giây để trang tải hoàn toàn, rồi phân tích HTML trả về bằng Beautiful Soup. Sau khi phân tích xong, webdriver sẽ được đóng lại.

Bước 7: Tìm và trích xuất dữ liệu danh sách

Khi đã có nội dung HTML, bước tiếp theo là trích xuất dữ liệu liên quan cho mỗi bất động sản. Với BeautifulSoup, chúng ta có thể dễ dàng duyệt cấu trúc và tìm đến các phần chứa thông tin cần thiết.

Trích xuất các phần tử danh sách

Trước tiên, chúng ta xác định tất cả các khối trên trang chứa thông tin bất động sản. Các phần này bao gồm URL, tiêu đề, mô tả, đánh giá, giá và thông tin bổ sung.

listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:

Đoạn code này sử dụng phương thức find_all() của BeautifulSoup để tìm tất cả các thẻ div có class “g1qv1ctd”. Mỗi thẻ này đại diện cho một bất động sản trên Airbnb. Sau đó, vòng lặp sẽ lấy dữ liệu cần thiết từ từng phần tử.

Trích xuất URL danh sách

Với mỗi khối tìm được, chúng ta trích xuất URL.

URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
    "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)

Chúng ta tìm trong đối tượng soup một thẻ anchor có class “rfexzly”. Nếu tìm thấy, nó sẽ lấy thuộc tính 'href' (chứa URL tương đối) và kết hợp với URL gốc để tạo địa chỉ đầy đủ. Nếu không tìm thấy, một chuỗi rỗng sẽ được dùng để tránh lỗi.

Trích xuất tiêu đề danh sách

Tiếp theo, chúng ta lấy tiêu đề, nằm trong thẻ div có class “t1jojoys”. Lấy và làm sạch văn bản. Nếu không có thẻ, sẽ lưu chuỗi rỗng.

title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
    title_element.get_text(strip=True) if title_element else ""
)

Trích xuất mô tả danh sách

Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
    Description_element.get_text(strip=True) if Description_element else ""
)

Tương tự cách lấy tiêu đề, đoạn này tìm thẻ span có class "t6mzqp7". Trích xuất và làm sạch nội dung văn bản, chứa mô tả ngắn gọn về bất động sản.

Trích xuất đánh giá danh sách

rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
    rating_element.get_text(strip=True) if rating_element else ""
)

Như trong đoạn code trên, một thẻ span có class “ru0q88m” chứa giá trị đánh giá. Chúng ta trích xuất và làm sạch nó để loại bỏ khoảng trắng thừa.

Trích xuất giá của danh sách

Cuối cùng, chúng ta trích xuất giá.

price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
    f"{price_element.get_text(strip=True)} per night" if price_element else ""
)

Đoạn code này tìm phần tử có class "_1y74zjx" trong listing_element hiện tại. Nếu phần tử này (chứa thông tin giá) được tìm thấy, nội dung văn bản sẽ được lấy, làm sạch và thêm "per night" để tạo chuỗi giá đầy đủ hơn.

Trích xuất thông tin bổ sung của danh sách

Một số bất động sản có thể bao gồm chi tiết bổ sung.

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 ""
)

Chúng ta tìm thẻ span có thuộc tính aria-hidden="true" để lấy thông tin bổ sung này. Sau khi thu thập dữ liệu từ một bất động sản, chúng ta thêm nó vào danh sách:

listings.append(listing_data)

Sau khi xử lý tất cả danh sách, chúng ta trả về một danh sách chứa các bất động sản, mỗi phần tử là một dictionary với dữ liệu đã trích xuất.

return listings

Bước 8: Ghi dữ liệu vào tệp CSV

Sau khi thu thập thành công dữ liệu từ các trang Airbnb, bước quan trọng tiếp theo là lưu trữ thông tin giá trị này để phân tích và tham khảo sau này. Chúng ta sử dụng thư viện csv cho nhiệm vụ này. Mở một tệp CSV ở chế độ ghi và tạo đối tượng csv.DictWriter. Sau đó ghi tiêu đề và dữ liệu vào tệp.

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}")

Đây là đoạn code Python hoàn chỉnh để scrape Airbnb mà chúng ta đã dùng trong hướng dẫn này:

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

# Danh sách proxy
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"
    )  # Thay bằng đường dẫn đến ChromeDriver của bạn
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Điều chỉnh dựa trên thời gian tải trang

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

    listings = []

    # Tìm tất cả phần tử danh sách trên trang
    listing_elements = soup.find_all("div", class_="g1qv1ctd")

    for listing_element in listing_elements:
        # Trích xuất dữ liệu từ mỗi phần tử danh sách
        listing_data = {}

        # URL danh sách
        URL_element = soup.find("a", class_="rfexzly")
        listing_data["Listing URL"] = (
            "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
        )

        # Tiêu đề
        title_element = listing_element.find("div", class_="t1jojoys")
        listing_data["Title"] = (
            title_element.get_text(strip=True) if title_element else ""
        )

        # Mô tả
        Description_element = listing_element.find("span", class_="t6mzqp7")
        listing_data["Description"] = (
            Description_element.get_text(strip=True) if Description_element else ""
        )

        # Đánh giá
        rating_element = listing_element.find("span", class_="ru0q88m")
        listing_data["Rating"] = (
            rating_element.get_text(strip=True) if rating_element else ""
        )

        # Giá
        price_element = listing_element.select_one("._1y74zjx")
        listing_data["Price"] = (
            f"{price_element.get_text(strip=True)} per night" if price_element else ""
        )

        # Thông tin bổ sung
        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 ""
        )

        # Thêm dữ liệu danh sách vào mảng
        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"Dữ liệu đã được xuất ra {csv_file_path}")

Đoạn mã trên đảm bảo rằng mọi dữ liệu được thu thập bởi scraper sẽ được lưu trong một tệp có tên "proxy_web_listings_output.csv" ở định dạng CSV.

Kết quả

Kết quả từ scraper của chúng ta được lưu vào tệp CSV có tên “proxy_web_listings_output.csv” như hình dưới đây.

5.jpg

Hướng dẫn này giải thích hiệu quả cách thu thập dữ liệu danh sách Airbnb bằng Python, cho phép trích xuất các thông tin chính như giá cả, tình trạng sẵn có và đánh giá. Nó nhấn mạnh tầm quan trọng của việc sử dụng proxy và xoay vòng chúng để tránh bị chặn bởi các biện pháp chống bot của Airbnb.

Kết luận

Scraping dữ liệu Airbnb bằng Python và Selenium giúp bạn có quyền truy cập trực tiếp vào thông tin giá trị như giá cả, tình trạng sẵn có — những thông tin then chốt cho nghiên cứu thị trường, phân tích đầu tư hoặc thậm chí xây dựng công cụ bất động sản của riêng bạn. Mặc dù quá trình này có những thách thức kỹ thuật (và một số vấn đề pháp lý), nhưng việc thiết lập đúng môi trường, hiểu cách hoạt động của trang web và sử dụng các công cụ như proxy và trình duyệt headless có thể giúp bạn vượt qua hầu hết các trở ngại. Hãy chắc chắn tôn trọng điều khoản sử dụng của nền tảng và luôn xử lý dữ liệu một cách có trách nhiệm.

Bình luận:

0 Bình luận