如何用Python爬取Airbnb多房源页面数据及可订状态?
Airbnb详情页数据爬取:设施、描述与可订状态实现方案
问题总结
你已经完成Airbnb搜索列表页的价格、名称、评分爬取,也掌握了分页获取房源链接的方法,现在需要:
- 基于已有的房源链接,爬取每个详情页的房源描述、设施(比如睡眠区域)
- 获取房源的可订状态
你尝试提取睡眠区域的代码因标签选择器不准确,未能拿到正确数据。
解决方案
1. 修正基础代码(避免重复初始化浏览器)
原代码重复初始化driver会打开多个浏览器窗口,先优化这部分:
from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager import pandas as pd import time import random # 仅初始化一次浏览器 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver.maximize_window() # 访问列表页获取房源链接 airbnb_url = 'https://www.airbnb.com/s/Thessaloniki--Greece/homes?tab_id=home_tab&flexible_trip_lengths%5B%5D=one_week&refinement_paths%5B%5D=%2Fhomes&place_id=ChIJ7eAoFPQ4qBQRqXTVuBXnugk&query=Thessaloniki%2C%20Greece&date_picker_type=calendar&search_type=unknown' driver.get(airbnb_url) time.sleep(5) # 等待列表页加载完成 links = [] soup = BeautifulSoup(driver.page_source, 'lxml') # 用更稳定的data属性选择器替代随机生成的class名 for card in soup.select('div[data-testid="card-container"]'): link_tag = card.select_one('a[href^="/rooms/"]') if link_tag: links.append('https://www.airbnb.com' + link_tag['href'])
2. 详情页核心数据爬取
用WebDriverWait替代固定延迟,提升稳定性;同时修正选择器适配Airbnb页面结构:
# 存储所有房源详情数据 all_property_data = [] for url in links: driver.get(url) # 等待详情页关键元素加载,避免空数据 WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "_14i3z6h"))) soup = BeautifulSoup(driver.page_source, 'lxml') property_info = {} # 提取房源描述 desc_section = soup.select_one('div[data-section-id="DESCRIPTION_DEFAULT"] div._14i3z6h') property_info['房源描述'] = desc_section.get_text(strip=True) if desc_section else '无描述' # 提取睡眠区域(设施分类) sleep_amenities = [] amenities_section = soup.select_one('div[data-section-id="AMENITIES_DEFAULT"]') if amenities_section: # 遍历所有设施项,筛选睡眠相关内容 for item in amenities_section.select('div._1fxyzhx'): item_text = item.get_text(strip=True) # 英文页面请替换为'bed'/'sleep'关键词 if '床' in item_text or '睡眠' in item_text: sleep_amenities.append(item_text) property_info['睡眠区域'] = ', '.join(sleep_amenities) if sleep_amenities else '无睡眠区域信息' # 提取可订状态 # 优先检查日历区域的可订提示 availability_tag = soup.select_one('div[data-testid="booking-calendar"] span._1hxyyw3') if availability_tag: property_info['可订状态'] = availability_tag.get_text(strip=True) else: # 检查是否有不可预订的提示 unavailable_tag = soup.select_one('div[data-testid="unavailable-message"]') property_info['可订状态'] = '不可预订' if unavailable_tag else '可预订' all_property_data.append(property_info) # 随机延迟,避免触发反爬机制 time.sleep(random.randint(2, 4)) # 保存为CSV文件 df = pd.DataFrame(all_property_data) print(df.head()) df.to_csv('airbnb_property_details.csv', index=False, encoding='utf-8-sig')
关键提示
- 选择器优先用固定属性:Airbnb的class名是动态生成的,优先使用
data-testid、data-section-id这类固定属性,比随机class更可靠 - 反爬应对:频繁请求会被限制,建议添加随机延迟,必要时使用代理IP
- 页面语言适配:如果是英文页面,把睡眠区域的筛选关键词改成
bed/sleep,可订状态检查Available/Unavailable - 元素等待:尽量用
WebDriverWait等待元素加载,替代固定延迟,效率更高且稳定
内容的提问来源于stack exchange,提问作者Lefteris Kyprianou
相关产品推荐
相关产品推荐

