一、为什么需要抓取机票价格?
2025年的机票价格波动比天气更难预测——早买怕降价,晚买怕涨价。某位经常出差的程序员朋友曾吐槽:"上周看上海飞北京的机票还是800元,今天再看直接涨到1500元,这价格波动比股票还刺激!"这种价格焦虑催生了一个真实需求:能否用技术手段实时监控机票价格,在低价时自动提醒?
免费编程软件「python+pycharm」 链接:pan.quark.cn/s/48a86be2f…
通过抓取某程等平台的价格数据,我们不仅能实现价格监控,还能分析历史价格趋势。比如发现"每周三下午3点价格最低"这类规律,或者通过对比不同航司的定价策略,找到性价比最高的航班。这些数据对个人旅行规划和商业决策都有实际价值。
二、技术选型:用Python搭建爬虫系统
1. 核心工具包
- requests:发送HTTP请求的瑞士军刀,适合处理静态页面
- Selenium:当页面用JavaScript动态加载数据时,它能模拟浏览器操作
- BeautifulSoup:解析HTML的轻量级工具,适合提取结构化数据
- Pandas:数据清洗和存储的利器,能把杂乱的数据整理成表格
- 代理IP池:应对反爬虫的关键武器,避免被封IP
2. 环境准备
pip install requests selenium beautifulsoup4 pandas fake_useragent
建议再安装一个浏览器驱动(如ChromeDriver),用于Selenium操作。
三、实战步骤:从0到1抓取价格数据
1. 破解动态加载的难题
某程的机票价格通常通过AJAX动态加载,直接请求网页可能看不到价格。这时需要:
-
方法一:分析网络请求
打开浏览器开发者工具(F12),在"Network"选项卡中搜索"price",找到返回JSON数据的接口。例如:import requests url = "https://flights.***.com/itinerary/api/12345/price" # 示例URL params = { "departure": "SHA", # 上海虹桥 "arrival": "PEK", # 北京首都 "date": "2025-12-15" } response = requests.get(url, params=params) print(response.json()) # 直接获取结构化价格数据 -
方法二:Selenium模拟点击
如果接口加密或难以定位,可以用Selenium模拟用户操作:from selenium import webdriver from selenium.webdriver.common.by import By from fake_useragent import UserAgent ua = UserAgent() options = webdriver.ChromeOptions() options.add_argument(f"user-agent={ua.random}") # 随机User-Agent driver = webdriver.Chrome(options=options) driver.get("https://flights.***.com/itinerary/oneway/SHA-PEK?date=2025-12-15") price_element = driver.find_element(By.CSS_SELECTOR, ".price_text") # 定位价格元素 print(price_element.text) driver.quit()
2. 数据清洗与存储
抓取到的原始数据可能包含乱码或冗余信息,需要用Pandas清洗:
import pandas as pd
# 假设从JSON获取的数据如下
data = [
{"flight": "MU5643", "price": 1200, "time": "08:00-10:30"},
{"flight": "FM9251", "price": 980, "time": "14:20-16:50"}
]
df = pd.DataFrame(data)
df.to_csv("flight_prices.csv", index=False) # 保存为CSV文件
3. 定时抓取与价格监控
用Python的schedule库实现每小时抓取一次:
import schedule
import time
def fetch_prices():
# 这里放入前面的抓取代码
print("正在抓取最新价格...")
schedule.every().hour.do(fetch_prices)
while True:
schedule.run_pending()
time.sleep(1)
更高级的做法是用云服务器(如阿里云ECS)运行爬虫,配合企业微信/邮件通知低价。
四、反爬虫攻防战:如何避免被封IP?
1. 代理IP池实战
当收到403错误时,说明IP已被封。解决方案:
-
购买住宅代理:如站大爷IP代理,提供全国各地的真实家庭IP
-
轮换策略:每请求1次就换IP(适合小规模抓取)
-
IP质量检测:提前测试代理的可用性和延迟
import requests from fake_useragent import UserAgent proxies = { "http": "http://123.123.123.123:8080", # 示例代理 "https": "http://123.123.123.123:8080" } ua = UserAgent() headers = {"User-Agent": ua.random} try: response = requests.get( "https://flights.***.com", headers=headers, proxies=proxies, timeout=10 ) print(response.status_code) except requests.exceptions.ProxyError: print("代理失效,切换IP...")
2. 模拟人类行为
- 随机延迟:请求间隔设为3-10秒的随机值
- 鼠标轨迹模拟:用Selenium的
ActionChains模拟滚动和点击 - Cookie管理:登录后保存Cookie,避免频繁重新登录
五、数据可视化:让价格波动一目了然
用Matplotlib绘制价格趋势图:
import pandas as pd
import matplotlib.pyplot as plt
# 读取历史数据
df = pd.read_csv("flight_prices.csv")
df["date"] = pd.to_datetime(df["date"]) # 转换日期格式
# 按日期分组计算平均价
daily_avg = df.groupby("date")["price"].mean()
# 画图
plt.figure(figsize=(12, 6))
plt.plot(daily_avg.index, daily_avg.values, marker="o")
plt.title("上海-北京机票价格趋势(2025年12月)")
plt.xlabel("日期")
plt.ylabel("平均价格(元)")
plt.grid(True)
plt.show()
六、常见问题Q&A
Q1:被网站封IP怎么办?
A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。若封禁严重,可降低抓取频率至每小时1次,并增加随机延迟。
Q2:如何抓取国际机票价格?
A:某程的国际机票接口与国内不同,需修改请求参数中的countryCode和货币类型。例如查询纽约到伦敦的机票:
params = {
"departure": "JFK",
"arrival": "LHR",
"date": "2025-12-20",
"countryCode": "US",
"currency": "USD"
}
Q3:爬取的数据与实际价格不符?
A:可能原因:
- 某程有"价格缓存"机制,显示的价格可能已过期
- 未登录用户看到的是"未含税价",登录后显示完整价格
解决方案:
- 添加Cookie模拟登录状态
- 抓取时检查响应头中的
X-Cache字段,优先选择未缓存的数据
Q4:能否用爬虫自动订票?
A:技术上可行,但强烈不建议!
- 违反某程《用户协议》第5.3条
- 可能导致账号被封或法律风险
- 支付环节涉及敏感信息,存在安全隐患
合法替代方案:用爬虫监控价格,收到低价提醒后手动购买。
七、进阶技巧:分布式爬虫与机器学习预测
对于大规模数据抓取,可用Scrapy框架搭建分布式爬虫,将任务分配到多台服务器。更高级的玩法是用历史价格数据训练机器学习模型(如LSTM神经网络),预测未来价格走势。不过这需要一定的数据科学基础,适合进阶玩家尝试。
结语:技术中立,但需守住底线
爬虫技术本身是中立的,但如何使用它体现了开发者的价值观。建议:
- 严格遵守目标网站的
robots.txt规则 - 控制抓取频率,避免给服务器造成负担
- 仅将数据用于个人学习或合法商业分析
正如某位资深爬虫工程师所说:"好的爬虫应该像空气一样存在——用户感觉不到它的存在,但数据在静静流动。"希望本文能帮助你掌握机票价格抓取的核心技术,同时成为负责任的数据采集者。