携程国际机票sign破解

携程国际机票sign破解

1.全局搜索大法:

直接搜索对应的时间,定位到最后结果返回的请求。

在这里插入图片描述

发现请求头headers sign为变化状态以及参数 transactionID为变化状态(transactionID前面请求响应结果)。

在这里插入图片描述
transactionID为变化状态(transactionID前面请求响应结果)。
在这里插入图片描述

2.逆向回推法,先往上找找看看哪里设置了这两个变化参数。

发现:https://flights.ctrip.com/international/search/api/flightlist/oneway-tpe-szx?depdate=2020-09-14&cabin=y_s&adult=1&child=0&infant=0&containstax=1&v=0.9164251641244324 返回结果有transactionID。

参数分析:

oneway -> 单程    tpe -> 台北三字码    szx -> 深圳三字码  depdate->起始时间  cabin->仓位类型 

adult -> 成人    child->小孩   infant->婴儿    v ->时间戳刷新缓存 (一般情况直接忽略)

在这里插入图片描述

3.接着查找 哪一个请求最早有sign .

发现 https://flights.ctrip.com/international/search/api/search/batchSearch?v=0.026341469001777362

这个请求最早出现 sign ,且无源头查找sign,初步定义为 Js 动态生成 。

在这里插入图片描述

4. 堆栈跟踪法

在这里插入图片描述

一步步来,直接点进去,全局搜索大法。

在这里插入图片描述

逆向思维,倒推法,看到sign 就是 n ,那么n 是:

n = sessionStorage.getItem(i)) || (n = (new a.a).update(r).digest('hex'), sessionStorage.setItem(i, n)

sesessionStorage  本地存储的 name/value 键值对。get方法取键 i 为真.

且 n 为新new了一个对象把r进行md5  并且以键值对(i,n)设置回sessionStorage

简单啊,就是r进行了md5.

r是????

var r = e.transactionID + t,  不就是transactionID  + t

t 是 ????
在这里插入图片描述

var n = e.departureCityCode,
         r = e.arrivalCityCode,
         a = e.departureDate;
         t += n + r + a

英文学的好,很重要。

departureCityCode -> 起始三字码

arrivalCityCode -> 到达三字码     departureDate ->出发日期

在这里插入图片描述

Ca,这么简单啊… t 就是 String(起始地三字码+降落的三字码+出发时间)

Sign  =  md5(transactionID  +起始地三字码+降落的三字码+出发时间) 

在这里插入图片描述

在这里插入图片描述

分析完毕。over!

5.模拟请求,发现该网站自己一直发请求,直到拿到结果。

在这里插入图片描述

6.代码展示:

# encoding:utf-8
"""
@author Codeoooo
"""

import re
import json
import hashlib
import requests

from fake_useragent import UserAgent
from requests import RequestException


class CtripSpider:

    def __init__(self, depCode, arrCode, date, adult=1, child=0, infant=0):

        self.depCode = depCode
        self.arrCode = arrCode
        self.date = date
        self.adult = adult
        self.child = child
        self.infant = infant
        self.headers = {'User-Agent': UserAgent().random}

    def getTransactionId(self):
        """获取transactionId and Params"""
        url = 'https://flights.ctrip.com/international/search/oneway-{}-{}?depdate={}&cabin=y_s&adult={}&child={}&infant={}'.format(
            self.depCode, self.arrCode, self.date, self.adult, self.child, self.infant)

        transactionId, data = None, None
        for _ in range(3):
            try:
                response = requests.get(url, headers=self.headers)
                data = re.findall(r'GlobalSearchCriteria =(.+);', response.text)[0].encode('utf-8')
                transactionId = json.loads(data).get("transactionID")
                return transactionId, data
            except:
                continue
        return transactionId, data

    def getSign(self, transactionId):
        sign_value = transactionId + self.depCode + self.arrCode + self.date
        # 进行md5加密
        _sign = hashlib.md5()
        _sign.update(sign_value.encode('utf-8'))

        headers = {
            'origin': "https://flights.ctrip.com",
            'sign': _sign.hexdigest(),
            'transactionid': transactionId,
            'Host': "flights.ctrip.com",
            'content-type': "application/json;charset=UTF-8",
        }
        self.headers.update(headers)

    # 请求并获取响应,获取源代码
    def get_information_page(self, data):
        """

        :return:
        """
        while True:
            try:
                requests.packages.urllib3.disable_warnings()
                res = requests.post(
                    url="https://flights.ctrip.com/international/search/api/search/batchSearch",
                    headers=self.headers,
                    data=data,
                    proxies=None,
                    timeout=5
                )
            except RequestException:
                # todo 请求抛错未处理 可能为代理网路延迟问题
                # time.sleep(random.randint(1, 3))
                continue
            except Exception as e:
                # 其他未知错误
                print(e)
            else:
                # res.encoding = 'utf-8'
                # print(res.json())
                if res.json().get("data").get("context").get("searchCriteriaToken"):
                    return res.json()

    def main(self):
        transactionId, data = self.getTransactionId()
        if transactionId:
            self.getSign(transactionId)
            return self.get_information_page(data)
        else:
            # print("账号被封禁")
            return


if __name__ == '__main__':

    spider = CtripSpider("tpe", "bjs", "2020-09-14")
    print(spider.main())
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Codeoooo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值