☰
告别网页抓取:Fli如何逆向Google Flights API实现零爬虫机票搜索
2026/9/29 21:37:18 网站建设 项目流程

告别网页抓取:Fli如何逆向Google Flights API实现零爬虫机票搜索

【免费下载链接】fliGoogle Flights MCP, CLI and Python Library项目地址: https://gitcode.com/gh_mirrors/fli2/fli

Fli是一个 Google Flights MCP、CLI 与 Python 库三合一的机票搜索工具:它通过逆向工程直接对接 Google Flights API,实现零爬虫、零 HTML 解析的航班搜索——不启动浏览器、不抓取网页,只需一个标准 HTTP 请求就能拿到结构化机票数据。本文带你拆解它的逆向原理,并用 30 秒跑通第一个搜索。

为什么网页抓取该退役了?

做过机票抓取的朋友都有切身体会:

  • 脆弱:Google 换个 CSS 类名、调个 DOM 结构,XPath 选择器就集体失效
  • 笨重:浏览器自动化方案要维护一堆无头浏览器进程,慢且占内存
  • 低效:解析大段 HTML 只为了抠出几个价格字段

Fli 的思路完全不同——既然 Google Flights 网页本身就是从内部 API 渲染出来的,那直接逆向出这个 API 的通信协议,绕开整个页面去说话。

Fli 零爬虫机票搜索的 4 步逆向原理 🛠️

整个传输层只有几百行代码,集中在 fli/search/ 目录下,流程清晰可复现:

第 1 步:逆向tfsprotobuf 参数

Google Flights 搜索页的 URL 长这样:https://www.google.com/trights?tfs=<一串base64>。这个tfs是一个 protobuf 二进制编码,里面装着行程类型、出发/到达机场、日期、舱位、乘客、中转偏好等全部搜索条件。Fli 用仅 60 行的最小白板协议编码器(fli/search/_proto.py)手工实现了 varint 和 length-delimited 字段编码,把搜索条件序列化成tfs值——完全不需要 protobuf 运行时依赖。

第 2 步:拼接搜索页 URL

fli/search/_tfs.py 中的build_tfs()把过滤器对象编码成tfs参数,page_url()再拼上语言(hl=)、国家(gl=)、货币(curr=)等本地化参数。

第 3 步:从页面中抽取ds:1数据块

Google 的搜索页把完整结果内联在一段AF_initDataCallback({key: 'ds:1', ..., data:[...]})的 JavaScript 回调里。extract_payload()用正则精准定位这个数据块并反序列化成 JSON——这一步拿到的是和内部 RPC 完全相同的结果结构。

第 4 步:解码为类型化模型

fli/search/_decoders.py 按逆向出的字段位置图(行内[2]、[3]是航班列表,价格、航段、中转、排放值各在固定下标)把原始 JSON 解码成FlightResult这类结构清晰的对象,业务代码从此不用碰任何下标魔法。

为什么要走搜索页而不是 RPC?

2026-08 起,Google 给FlightsFrontendService的 RPC 接口加上了只有页面自身 JavaScript 才能生成的x-goog-batchexecute-bgr签名头,普通 HTTP 客户端一律拿到空响应。而公开搜索页没有这道门——结果同样内联在页面里,只是换了tfs参数格式。Fli 顺势切换到这条通道,保持了纯 HTTP 的轻量架构。

30 秒上手:安装与第一次搜索 ⚡

零爬虫架构意味着零额外依赖,一条命令安装:

pip install flights

CLI 一行命令搜索 JFK 到伦敦的商务舱直飞航班:

fli flights JFK LHR 2026-10-25 --class BUSINESS --stops NON_STOP

想找最便宜的出行日期?fli dates JFK LHR --from 2026-01-01 --to 2026-02-01即可在日期区间里扫描票价。

Python 库同样简洁,核心模型定义在 fli/models/:

from fli.models import Airport, FlightSearchFilters, FlightSegment, PassengerInfo, SeatType from fli.search import SearchFlights filters = FlightSearchFilters( passenger_info=PassengerInfo(adults=1), flight_segments=[FlightSegment( departure_airport=[[Airport.JFK, 0]], arrival_airport=[[Airport.LAX, 0]], travel_date="2026-12-25", )], seat_type=SeatType.ECONOMY, ) for f in SearchFlights().search(filters) or []: print(f"${f.price} — {f.duration} 分钟 — {f.stops} 次中转")

MCP Server:让 AI 助手一句话查机票 🤖

Fli 内置了基于 FastMCP 的 MCP 服务器(fli/mcp/server.py),把search_flights(指定日期搜索)和search_dates(区间找最低价)两个工具暴露给 AI 客户端:

fli-mcp # STDIO 模式,供 Claude Desktop 等客户端使用 fli-mcp-http # HTTP 模式,默认服务在 127.0.0.1:8000/mcp/

在 Claude Desktop 配置里登记fli-mcp后,直接用自然语言提问即可:“帮我查 12 月 25 日从纽约 JFK 到洛杉矶的非直飞航班”——AI 会通过 MCP 协议调用底层同一个零爬虫搜索通道。完整配置见 docs/guides/mcp.md。

内置防护:限流、重试与错误分类 🛡️

逆向接口最怕打崩服务方,fli/search/client.py 内置了三重保护:

机制实现
全局限流令牌桶算法,所有线程共享 10 请求/秒预算
自动重试指数退避,最多 3 次;瞬时空页面(约 1/60 概率)单独再试
类型化错误超时、连接、证书、HTTP、解析失败各自独立异常类,错误信息直接给出修复建议

实用边界:这些限制要知道 📌

  • 多城市行程:结果由 Google 客户端侧通过受限 RPC 加载,页面内联不出数据,需分段搜索
  • 日期扫描:每天消耗一次页面抓取,单次最多 93 天
  • 三个过滤器(emissions、bags、exclude_basic_economy)无tfs字段,会被丢弃并给出警告
  • 更多示例可运行 examples/python/basic_one_way_search.py,TypeScript 移植版在 fli-js/

关键源码地图 📂

模块职责
fli/search/_proto.py极简 protobuf 编码器,生成tfs令牌
fli/search/_tfs.py搜索页传输层:构建 URL、抽取ds:1、客户端过滤
fli/search/_decoders.py把原始 JSON 解码为类型化航班模型
fli/search/_wire.py线格式分块与协议帧处理
fli/search/client.py限流、重试、浏览器指纹模拟的 HTTP 客户端
fli/models/机场、航司枚举与搜索过滤器模型
fli/cli/命令行入口(fli/fli-mcp)

总结

Fli 证明了逆向工程不需要重型武器:逆向一个tfsprotobuf 参数 + 一段页面内联数据,就能用纯 HTTP打通 Google Flights API,比爬虫方案更快、更稳、更抗 UI 变动。无论你想要 CLI 一行查询、Python 库深度定制,还是让 AI 助手直接查机票,这套零爬虫架构都能直接复用。

【免费下载链接】fliGoogle Flights MCP, CLI and Python Library项目地址: https://gitcode.com/gh_mirrors/fli2/fli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询