好久不写文章了,两天弄了个携程的脚本,发现网上大多都是18年以前老版的做法现在已经没有借鉴的意义,于是记录攻略如下,希望能帮助到其它爬虫党。最近出国好多,查找机票价格特别烦,这次又准备买了,正好折腾一下。
网上现有脚本之所以不能执行除了页面改版外还因为携程加入sign签名使得爬取携程的难度大大上升,几乎搜不到可用的脚本,第一次真正写爬虫也希望能贡献给他人做参考。
对机票得有一个大概的认识,某一天的最低价各大网站都有提供了,所以我们这里比较的是时间段内的最低价,另外比如一周内的机票铁定贵,不太可能去买两个月以上的机票,当然跟这个脚本没关系。给出搜索后携程会推送最低价的机票,那么需求就变成在我计划出行的时间范围内哪一天走最便宜。本来的有网站提供类似时间段的搜索服务,不知道为啥现在没了。
在入手前先看看难度,之前已经搜索了好多携程爬取的文章,发现可以用它的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缺一不可。transactionid很快发现就在主页的head标签中,通过bs4可以很容易找出来。
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
- 抓包代理:http://oss.theautomatedtester.co.uk/browsermob-proxy-py/
- selenium获取所有自请求的数据:https://stackoverflow.com/questions/53286828/how-to-get-browser-network-logs-using-python-selenium
- 同上,目前chromedriver有bug:https://stackoverflow.com/questions/53049026/selenium-chrome-performance-logs-not-working/56536604
- 通过注入js脚本的方式获取所有xhr数据,没尝试成功:https://www.quora.com/Is-there-a-way-to-find-out-which-function-triggered-the-AJAX-request-e-g-on-Tumblr-infinite-scrolling
- 完整的爬虫教程,适合我这种第一次爬的新手:https://www.jianshu.com/p/0391b2d4f590
- 同上:https://cuiqingcai.com/2599.html
- 超牛的网站,能把curl命令转为各种语言的脚本,什么?还不懂?这意味着chrome控制台里的任何请求也可以直接翻译为脚本,真是爬虫好帮手啊:https://curl.trillworks.com/