使用BeautifulSoup抓取Airbnb数据时无法获取下一页内容的问题求助
解决Airbnb多页爬虫仅能抓取少量页面的问题
我帮你排查了代码里的几个关键问题,这应该就是你爬不到后续页面的核心原因,下面一步步给你分析和修正:
问题成因分析
- 反爬机制拦截:Airbnb对无标识的请求敏感度很高,你直接用
requests.get发送请求却没携带浏览器标识(User-Agent),很容易被识别为机器人,后续页面会被限制访问,导致抓不到数据。 - 分页逻辑错误:你的
find_next_page函数犯了一个低级错误——它没有用当前页面的soup对象,反而重新请求初始URL来查找下一页链接,这会导致永远找不到正确的后续分页地址,循环很快就会终止。 - 动态class名失效:Airbnb的class名是动态生成的(比如
_8ssblpx、_1tanv1h这类带随机字符的),网站更新后这些名字大概率会变,依赖它们定位元素稳定性极差,容易抓不到内容。 - 信息提取逻辑混乱:
get_listing_title这类函数接收的是单个房源对象,但函数内部又做了for l in listing循环,这会遍历房源的子元素,导致提取逻辑出错,很多时候会返回None。
修正后的完整代码
我调整了所有问题点,改用更稳定的元素定位方式(比如data-testid属性),添加了请求头,修复了分页逻辑:
import requests import bs4 import pandas as pd import time import random # 模拟浏览器的请求头,替换成你自己浏览器的User-Agent(可在浏览器控制台Network面板查看) HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } def get_page(url): # 添加随机延迟,模拟人类访问节奏 time.sleep(random.uniform(3, 6)) try: response = requests.get(url, headers=HEADERS) response.raise_for_status() # 主动抛出请求错误 soup = bs4.BeautifulSoup(response.text, "html.parser") return soup except requests.exceptions.RequestException as e: print(f"请求页面失败: {e}") return None def get_listings(soup): # 改用data-testid定位房源容器,比动态class稳定得多 if not soup: return [] return soup.find_all("div", {"data-testid": "listing-card"}) def get_listing_title(listing): try: title_elem = listing.find('div', {'data-testid': 'listing-card-title'}) return title_elem.text.strip() if title_elem else None except Exception as e: print(f"提取标题失败: {e}") return None def get_listing_subtitle(listing): try: subtitle_elem = listing.find('span', {'data-testid': 'listing-card-subtitle'}) return subtitle_elem.text.strip() if subtitle_elem else None except Exception as e: print(f"提取副标题失败: {e}") return None def get_listing_info(listing): try: info_elem = listing.find('div', {'data-testid': 'listing-card-info'}) return info_elem.text.lower().strip() if info_elem else None except Exception as e: print(f"提取房源信息失败: {e}") return None def find_next_page(soup): base_url = "https://www.airbnb.it" if not soup: return None try: # 定位下一页按钮,改用更稳定的选择器 next_btn = soup.find("a", {"data-testid": "pagination-next-arrow"}) if next_btn and 'href' in next_btn.attrs: return base_url + next_btn['href'] else: return None except Exception as e: print(f"查找下一页失败: {e}") return None # 初始化数据列表 title = [] subtitle = [] info = [] # 初始URL(修正了原URL的转义字符) url = 'https://www.airbnb.it/s/Italy/homes?checkin=2021-08-01&checkout=2021-08-02' while url is not None: print(f"正在抓取页面: {url}") soup = get_page(url) listings = get_listings(soup) if not listings: print("当前页面未找到房源,可能被反爬或页面结构变化") break for l in listings: title.append(get_listing_title(l)) subtitle.append(get_listing_subtitle(l)) info.append(get_listing_info(l)) # 获取下一页URL url = find_next_page(soup) # 生成DataFrame airbnb_data = pd.DataFrame(data={'title': title, 'subtitle': subtitle, 'info': info}) print(airbnb_data.head()) # 可选:保存到CSV文件 # airbnb_data.to_csv('airbnb_italy.csv', index=False, encoding='utf-8-sig')
额外建议
- 更新User-Agent:代码里的User-Agent需要替换成你自己浏览器的(Chrome开发者工具→Network→任意请求→Headers中查看),避免被识别为固定机器人。
- 处理动态内容:如果Airbnb部分内容是JS动态加载的,静态抓取仍无效,可以考虑用
selenium或playwright模拟浏览器渲染页面。 - 异常扩展:代码里加了基础的异常捕获,你可以根据需要扩展,比如处理IP被封的情况,或者添加代理池。
- 请求频率:用随机延迟代替固定的5秒,更接近人类访问行为,降低被封风险。
内容的提问来源于stack exchange,提问作者ctrl_z
相关产品推荐
相关产品推荐

