python 爬取携程特价票-知道什么时候出发最便宜- 支持多航段搜索

好久不写文章了,两天弄了个携程的脚本,发现网上大多都是18年以前老版的做法现在已经没有借鉴的意义,于是记录攻略如下,希望能帮助到其它爬虫党。最近出国好多,查找机票价格特别烦,这次又准备买了,正好折腾一下。

网上现有脚本之所以不能执行除了页面改版外还因为携程加入sign签名使得爬取携程的难度大大上升,几乎搜不到可用的脚本,第一次真正写爬虫也希望能贡献给他人做参考。

  • 我的需求

对机票得有一个大概的认识,某一天的最低价各大网站都有提供了,所以我们这里比较的是时间段内的最低价,另外比如一周内的机票铁定贵,不太可能去买两个月以上的机票,当然跟这个脚本没关系。给出搜索后携程会推送最低价的机票,那么需求就变成在我计划出行的时间范围内哪一天走最便宜。本来的有网站提供类似时间段的搜索服务,不知道为啥现在没了。

  • 控制台分析和XHR回放

在入手前先看看难度,之前已经搜索了好多携程爬取的文章,发现可以用它的api直接取到航班json,控制台翻找后发现batchFlight这个地址就是,并且通过xhr可以回放。这点很重要,不是携程故意的漏洞,因为没登录也可以查机票,所以如果不让回放服务器就有压力了。既然可以回放那么思路就明确了,构建此XHR即可。

  • 测试脚本构建

XHR是一个Post请求,参数放在payloads中,啥都不说,先来个测试方法,用python来回放。如果回放成功说明我们需要的元素都在这里了,有洁癖的在这一步就可以试着缩减传送参数只传必要的。

def test_sample_request():
session = requests.session()
session.headers = {"hearders": random.choice(agents)}
base_url = "https://flights.ctrip.com/international/search/api/search/batchSearch"
url = base_url
payload = 'xxx payload json data'
headers['user-agent'] = random.choice(agents)
response = requests.post(url, headers=headers, params=params, data=payload.encode('utf-8'))
print(response.status_code)
print(response.content)
  • 确定sign和transactionid

经过上面的代码可以确定的是sign和transactionid缺一不可。transactionid很快发现就在主页的head标签中,通过bs4可以很容易找出来。

  • sign的破解

sign就比较麻烦了,通常的做法分为两种,一种是调试js破解sign的算法,需要大量精力明显不适合我,但是效率高,另一种是selenium模拟浏览器请求把sign拿出来。这里其实有点背道而驰,高手在模拟请求时就可以获取到所有数据才对,但是发现目前最新版的chrom对于子请求并不能获取到数据,从75版本开始不再记录response的数据。这里有的同学会考虑在selenium前面架设proxy,我也试了一下,发现等待子请求完成不是一件确定的事,反倒是模拟请求中获取sign基本没有缺失过,那么稳定为先,获取sign后用request获取json更好,把更多的时间用来分析返回的json上。

代码:

下面附上参考文献地址:https://github.com/today4king/daily-scripts/tree/master/flight-tickets

发表评论

电子邮件地址不会被公开。