使用Beautiful Soup爬取JetBlue积分返回None,是否HTML定位错误?
问题分析与解决
你遇到的job返回None的问题,核心原因有三个:
1. 页面依赖动态渲染
JetBlue的航班数据是通过JavaScript异步加载的,requests.get()只能获取初始静态HTML框架,里面并没有jb-flight-detail-item这类动态生成的DOM元素,BeautifulSoup自然无法找到目标节点。
2. 动态类名不可靠
你使用的ng-tns-c230-2是Angular框架生成的动态类名,每次页面加载都会随机变化,硬编码这类类名无法稳定定位元素。
3. 请求头缺失导致内容拦截
直接用requests发起请求时,缺少浏览器标识等关键请求头,容易被网站识别为爬虫,返回不完整或空内容。
解决方案
方案一:用Selenium处理动态页面(新手友好)
Selenium可以模拟浏览器加载页面,等待JavaScript渲染完成后再抓取内容:
from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 初始化Chrome浏览器(需提前安装对应版本的chromedriver) driver = webdriver.Chrome() url = 'https://www.jetblue.com/booking/flights?from=JFK&to=LAX&depart=2023-01-16&isMultiCity=false&noOfRoute=1&lang=en&adults=1&children=0&infants=0&sharedMarket=false&roundTripFaresFlag=false&usePoints=true' driver.get(url) # 等待积分元素加载完成(最多等待10秒) try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, 'jb-flight-detail-item .pointsText')) ) # 获取渲染后的完整页面源码 html_text = driver.page_source soup = BeautifulSoup(html_text, 'lxml') # 用通用选择器定位航班模块 job = soup.find('jb-flight-detail-item') if job: finding_point = job.find('span', class_='pointsText').text.strip() print(finding_point) else: print("未找到航班模块") finally: driver.quit()
方案二:直接调用API接口(高效推荐)
通过浏览器开发者工具(F12)分析网络请求,找到JetBlue加载航班数据的API接口,直接请求接口获取JSON数据,无需处理HTML:
import requests headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept': 'application/json', # 可从浏览器请求头中复制Referer、Cookie等必要字段 } api_url = 'https://www.jetblue.com/booking/api/flights' params = { 'from': 'JFK', 'to': 'LAX', 'depart': '2023-01-16', 'isMultiCity': 'false', 'noOfRoute': '1', 'lang': 'en', 'adults': '1', 'children': '0', 'infants': '0', 'sharedMarket': 'false', 'roundTripFaresFlag': 'false', 'usePoints': 'true' } response = requests.get(api_url, headers=headers, params=params) if response.status_code == 200: data = response.json() # 根据API返回的JSON结构提取积分信息(示例路径需根据实际返回调整) for route in data.get('routes', []): for flight in route.get('flights', []): points = flight.get('points', {}).get('amount') if points: print(f"所需积分:{points}") else: print(f"请求失败,状态码:{response.status_code}")
内容的提问来源于stack exchange,提问作者Gregory Durgin
相关产品推荐
相关产品推荐

