You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BeautifulSoup结合Selenium爬取Kayak时find_all返回0的问题

问题原因
  • Kayak自带反爬风控,旧版Chrome无头模式的浏览器特征非常明显,会被直接识别为爬虫请求,返回的页面不包含航班动态渲染内容,自然找不到目标span元素,和BeautifulSoup的查找逻辑无关。
  • 你使用的implicitly_wait仅会等待页面初始DOM加载完成,不会等待航班列表的异步接口请求、前端渲染流程结束,就算绕过反爬,抓取时机不对也拿不到目标内容。
  • 你拼接的目标URL末尾多了一个多余空格,可能触发异常请求逻辑。
可直接运行的修复代码
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from webdriver_manager.chrome import ChromeDriverManager
import time

# 基础参数配置
origin = "PIT"
destination = "ARN"
startdate = "2022-12-18"
# 去掉URL末尾多余空格
url = f"https://www.kayak.com/flights/{origin}-{destination}/{startdate}?sort=price_a"

# 配置Chrome选项,绕过基础反爬检测
chrome_options = Options()
# 用新版无头模式,浏览器特征和正常用户端一致
chrome_options.add_argument("--headless=new")
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
chrome_options.add_argument("user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option("useAutomationExtension", False)

# 启动驱动
driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
# 移除webdriver暴露的自动化标识
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
driver.get(url)

# 显式等待:直到航班出发时间元素渲染完成,最长等待40秒
WebDriverWait(driver, 40).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "span.depart-time.base-time"))
)
# 模拟用户滚动,触发所有航班项的懒加载
for scroll_pos in range(0, 2000, 500):
    driver.execute_script(f"window.scrollTo(0, {scroll_pos})")
    time.sleep(0.8)

# 此时再解析页面即可拿到目标元素
soup = BeautifulSoup(driver.page_source, "lxml")
deptimes = soup.find_all("span", attrs={'class': 'depart-time base-time'})
arrtimes = soup.find_all('span', attrs={'class': 'arrival-time base-time'})
meridies = soup.find_all('span', attrs={'class': 'time-meridiem meridiem'})

print(f"抓到出发时间数量:{len(deptimes)}")
driver.quit()
排查提示
  • 如果运行后返回的元素长度还是0,先打印driver.page_source搜索关键字depart-time,如果搜不到说明还是被风控拦截,可以尝试更换真实浏览器的user-agent、增加访问间隔、搭配代理使用。
  • 不要在页面刚加载完成就立刻取源码,Kayak的航班数据是分批异步加载的,必须等目标节点出现后再解析。

内容的提问来源于stack exchange,提问作者kzzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 18:54:32