3407802468@qq.com 6 månader sedan
incheckning
ce467112d1
39 ändrade filer med 8649 tillägg och 0 borttagningar
  1. 85 0
      3.31Gk航司/akm逆向/demo.py
  2. 39 0
      3.31Gk航司/akm逆向/test.js
  3. 468 0
      3.31Gk航司/akm逆向/分析.js
  4. 836 0
      3.31Gk航司/akm逆向/扣算法2.js
  5. 829 0
      3.31Gk航司/akm逆向/逆向.js
  6. 40 0
      3.31Gk航司/tls - ja3 指纹.py
  7. 8 0
      3.31Gk航司/其他/.idea/.gitignore
  8. 8 0
      3.31Gk航司/其他/.idea/3.31Gk航司.iml
  9. 38 0
      3.31Gk航司/其他/.idea/inspectionProfiles/Project_Default.xml
  10. 6 0
      3.31Gk航司/其他/.idea/inspectionProfiles/profiles_settings.xml
  11. 7 0
      3.31Gk航司/其他/.idea/misc.xml
  12. 8 0
      3.31Gk航司/其他/.idea/modules.xml
  13. 6 0
      3.31Gk航司/其他/1.html
  14. 197 0
      3.31Gk航司/其他/ast/ast.js
  15. 264 0
      3.31Gk航司/其他/ast/decode.js
  16. 59 0
      3.31Gk航司/其他/ast/encode.js
  17. 3191 0
      3.31Gk航司/其他/ast/收集函数加密/ast.js
  18. 59 0
      3.31Gk航司/其他/ast/收集函数加密/decode.js
  19. 59 0
      3.31Gk航司/其他/ast/收集函数加密/encode.js
  20. 3 0
      3.31Gk航司/其他/bm_sz 生成/分析
  21. 30 0
      3.31Gk航司/其他/bm_sz 生成/第一次请求akm.py
  22. 64 0
      3.31Gk航司/其他/cookie参数测试.py
  23. 71 0
      3.31Gk航司/其他/demo2.py
  24. 120 0
      3.31Gk航司/其他/html解析.py
  25. 3 0
      3.31Gk航司/其他/test.js
  26. 71 0
      3.31Gk航司/其他/verify.py
  27. 94 0
      3.31Gk航司/其他/分析.txt
  28. 717 0
      3.31Gk航司/其他/响应数据分析.py
  29. 82 0
      3.31Gk航司/其他/控制流平坦化-状态机为变量/ast.js
  30. 33 0
      3.31Gk航司/其他/控制流平坦化-状态机为变量/encode.js
  31. 100 0
      3.31Gk航司/其他/控制流平坦化-状态机为变量/test.js
  32. 20 0
      3.31Gk航司/其他/获取加密cookie.py
  33. 52 0
      3.31Gk航司/分析
  34. 163 0
      3.31Gk航司/请求-curl_cffi.py
  35. 169 0
      3.31Gk航司/请求-httpx.py
  36. 176 0
      3.31Gk航司/请求-requests版.py
  37. 168 0
      3.31Gk航司/请求-tls_client.py
  38. 234 0
      3.31Gk航司/请求requests 多线程.py
  39. 72 0
      3.31Gk航司/请求测试.py

+ 85 - 0
3.31Gk航司/akm逆向/demo.py

@@ -0,0 +1,85 @@
+# from curl_cffi import requests
+#
+# import requests
+# import execjs
+# import json
+#
+# requests = requests.Session()
+#
+# with open('逆向.js', encoding='utf-8') as f:
+#     js = f.read()
+# ctx = execjs.compile(js)
+#
+#
+# headers = {
+#     "accept": "*/*",
+#     "accept-language": "zh-CN,zh;q=0.9",
+#     "cache-control": "no-cache",
+#     "content-type": "text/plain;charset=UTF-8",
+#     "origin": "https://booking.jetstar.com",
+#     "pragma": "no-cache",
+#     "priority": "u=1, i",
+#     "referer": "https://booking.jetstar.com/",
+#     "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+#     "sec-ch-ua-mobile": "?0",
+#     "sec-ch-ua-platform": "\"Windows\"",
+#     "sec-fetch-dest": "empty",
+#     "sec-fetch-mode": "cors",
+#     "sec-fetch-site": "same-origin",
+#     "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
+# }
+#
+#
+# # akm js file url
+# # url = "https://www.jetstar.com/RGa75acATohb/xCwZta/rbnL7W/9J7Vz2pzzSVwGEXE/YxU3A31SAw/chwnU/DkTD0s"
+# url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+#
+# data = {
+#     'sensor_data': ctx.call('encrypt1')
+# }
+# data = json.dumps(data, ensure_ascii=False)
+# response = requests.post(url, headers=headers,
+#                          verify=False,
+#                          data=data,
+#                          impersonate='chrome110'  # 不指定 impersonate 时,TLS 指纹是 curl 原生的,而非浏览器指纹(依旧过不了检测)。需显式设置该参数以绕过 TLS 指纹检测
+#                          )
+#
+# print(response.text)
+#
+# bmsz = response.cookies.get_dict()['bm_sz']
+# print('bmsz =>', bmsz)
+#
+#
+# data2 = {
+#     "sensor_data": ctx.call('encrypt2', bmsz)
+# }
+#
+# data2 = json.dumps(data2)
+# # print(data2)
+# response2 = requests.post(url, headers=headers, data=data2, verify=False,
+#                           impersonate='chrome110'
+#                           )
+# print(response2.text)
+# print(response2.status_code)
+# print(response2.cookies.get_dict())
+#
+#
+# import requests
+# # 隧道域名:端口号
+# # tunnel = "l716.kdltps.com:15818"
+# tunnel = "l716.kdltps.com:15818"
+#
+# # 用户名密码方式
+# username = "t14669095435186"
+# password = "cle082qz"
+# proxies = {
+#     "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel},
+#     "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": tunnel}
+# }
+# print(requests.get('https://myip.ipip.net/', proxies=proxies).text)
+# print(requests.get('https://tls.peet.ws/api/all', proxies=proxies).text)
+
+# 113.14.208.206
+# 0149f47eabf9a20d0893e2a44e5a6323
+# 0149f47eabf9a20d0893e2a44e5a6323
+# 0149f47eabf9a20d0893e2a44e5a6323

+ 39 - 0
3.31Gk航司/akm逆向/test.js

@@ -0,0 +1,39 @@
+// AUx 也是数组
+Alx = []['concat'](AUx)["concat"](
+    [
+        {"lds": '1'},
+        {'sst': ''}
+    ]
+);
+
+var U9x = function () {
+    var MGx = "-1,-1,-1";
+    //  window.performance.memory; 获取 JavaScript 内存使用情况
+    `   返回一个包含以下属性的对象(示例值):
+
+属性	类型	描述
+usedJSHeapSize	number	当前 JavaScript 堆内存已使用的字节数(实际使用量)。
+totalJSHeapSize	number	当前 JavaScript 堆内存总分配的字节数(包含未使用的空闲内存)。
+jsHeapSizeLimit	number	JavaScript 堆内存的最大限制字节数(由浏览器或系统决定)
+`
+    if (window['performance'] && window['performance']['memory']) {
+        var sGx = window['performance']['memory'];
+        MGx = ''['concat'](sGx['jsHeapSizeLimit'], ',')['concat'](sGx['totalJSHeapSize'], ',')['concat'](sGx['usedJSHeapSize']);
+    }
+    var OGx = ''['concat'](MGx, ',')['concat']("950");
+    return OGx
+
+};
+
+
+//用于获取浏览器支持的​​语音合成(TTS,Text-to-Speech)的语音列表
+// var k5x = window["speechSynthesis"]["getVoices"]();  // 20
+// V1x = k5x['length']
+//
+// Mkx = ''['concat'](U9x(), ',')['concat'](V1x);
+//
+// W0x = ''.concat(Mkx, ',')['concat']('1,1,1', ',')['concat']("0", ',')['concat'](pRx, ',,,,,,')['concat'](f5x, ',,,')
+
+
+// 第4个数要注意
+wsl = "2248146944,110285101,98152829, 950, 20, 1,1,1,0,1,,,,,,0,,,1,1"

+ 468 - 0
3.31Gk航司/akm逆向/分析.js

@@ -0,0 +1,468 @@
+navigator = {
+    userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'
+}
+window = global
+
+
+// 新的akm js文件 搜索,可以搜  = {}; 从而快速定位 指纹数组生成位置 第一次请求时,里面有些值可能为空。。。观察下
+
+
+function getObj() {
+    // 可写死的值
+    let ver = '',
+        url = "https://www.jetstar.com/hk/zh/home?adults=1&children=0&flexible=1&flight-type=2&infants=0&origin=PVG&tab=1",
+        fpt = ";-1;dis;;true;true;true;-480;true;24;24;true;false;-1",
+        dsi = [{"get": ""}, {"set": "0"}, {"ico": "070f409b82df3bdd2f51a6415c7895353c153c47fe6dd8a0f87f3d14c46ccb2b"}, {"ift": "3"}, {"xof": "4,11,1,1,8"}, {"xot": "4,11,1,1,8"}, {"wev": "Google Inc. (Intel);wev;Google Inc. (Intel)"}, {"wre": "Google Inc. (Intel);wre;Google Inc. (Intel)"}, {"wdr": "0"}, {"iks": ""}, {"lds": "1"}, {"sst": ""}],
+        // mev 可写死, 但可能会触发验证码??
+        mev = "0,1,114,1356,242;1,1,694,1351,250;2,1,783,1295,311;3,1,838,1281,331;4,1,1306,1275,333;5,1,1311,1266,333;6,1,1322,1255,333;7,1,1337,1233,337;8,1,1354,1216,340;9,1,1370,1209,340;10,1,1394,1202,340;11,1,1403,1201,340;12,1,2892,1191,340;13,1,2905,1183,340;14,1,2921,1181,339;15,1,3038,1177,338;16,1,3072,1175,336;17,1,3445,1174,336;18,1,3629,1170,336;19,1,3656,1169,336;20,1,3673,1167,337;21,1,3689,1163,338;22,1,3706,1152,338;23,1,3722,1135,338;24,1,3739,1113,328;25,1,3757,1080,302;26,1,3772,1052,281;27,1,3789,1006,251;28,1,3806,939,209;29,1,3823,865,174;30,1,3840,834,150;31,1,3857,820,141;32,1,3873,818,134;33,1,3889,818,123;34,1,3906,818,112;35,1,3922,818,103;36,1,3940,819,98;37,1,3956,820,96;38,1,4084,822,96;39,1,4106,827,105;40,1,4123,832,109;41,1,4139,843,112;42,1,4156,866,112;43,1,4173,908,105;44,1,4190,968,105;45,1,4253,1340,56;46,1,4281,1388,35;47,1,4294,1393,31;48,1,4373,1390,30;49,1,4390,1378,27;50,1,4406,1368,23;51,1,4424,1357,19;52,1,4440,1348,16;53,1,4457,1346,14;54,1,4490,1344,13;55,1,4507,1337,10;56,1,4523,1332,7;57,1,4533,1327,4;58,1,5324,1072,69;59,1,5343,1062,69;60,1,5357,1054,69;61,1,5374,1046,69;62,1,5390,1034,68;63,1,5407,1021,64;64,1,5424,1014,63;65,1,5443,1005,61;66,1,5458,994,60;67,1,5474,977,55;68,1,5491,965,51;69,1,5507,958,47;70,1,5525,950,45;71,1,5542,944,45;72,1,5557,943,45;73,3,5633,943,45,-1;74,4,5725,943,45,-1;75,2,5728,943,45,-1;76,1,8014,509,619;77,1,8021,509,622;78,1,8029,502,628;79,1,8103,447,670;80,1,8145,447,674;81,1,8156,447,675;82,1,8172,448,675;83,1,8332,449,675;84,1,8340,456,675;85,1,8348,465,672;86,1,8356,476,670;87,1,8364,487,668;88,1,8372,498,665;89,1,8380,511,658;90,1,8389,521,655;91,1,8396,530,652;92,1,8404,532,650;93,1,8414,533,649;94,1,8426,534,649;95,3,8544,534,649,-1;",
+
+        startTs = Date.now() - 1000
+    // window.bmak.startTs = startTs
+    ajr = ajr(startTs)  //用到 2 次,且要一致
+    // console.log(ajr)
+    ;
+    return {
+        "ver": ver,                         // 网页固定值,"C9vFEovTrypIjd1JK5C8oAAPjzy2LU11L9garZrvwm8="
+        "fpt": fpt,                         // 可写死
+        "fpc": fpc(fpt),                    // 根据fpt值生成
+        "ajr": ajr,                         // 变化了 根据 startTs生成  可写死, 根据ua值生成
+        "din": din(startTs),           // 可写死, 数组:23位
+        "eem": "do_en,dm_en,t_en",          // 可写死, 检测函数后拼接而成,  示例值:"do_en,dm_en,t_en"
+        "ffs": "",                          // 可写死, 值为空
+        "vev": "2,490;3,5328;2,6723;3,8541;",                                   // 可写死, ============================================
+        "inf": "",                          // 网站固页值  示例值:""
+        "ajt": '0,0',                       // 可写死 第一次请求为'0,0' 同一会话每次请求不一样,写死时 要注意要和生成 dvc 的入参一致
+
+        // kev mev tev pev oev if 都是从一个函数返回的6位数组(变量组成 只有 0 1 有值,其他都是空字符串 可能会变)中升序取值  应该是轨迹数组
+        "kev": "",                 // 可为空, 从6数组取值
+        "mev": mev,                // 可写死, 从6数组取值  鼠标移动轨迹
+        "tev": "",                 // 从6数组取值                示例值:""
+        "pev": "",                 // 从6数组取值                示例值:""
+        "oev": "",                 // 从6数组取值                示例值:""
+        "if": "",                  // 从6数组取值                示例值:""
+
+        "dme": "0,521,-1,-1,-1,-1,-1,-1,-1,-1,-1;",                // 可写死
+        "doe": "0,522,-1,-1,-1;",                                  // 可写死
+        "pur": url,                                                // 可写死 网页url 不能有反斜杠 \ 和双引号 "    示例值:
+
+        "mst": mst(startTs, ajr),                                                                         //   数组:30位  -------------------------分析
+
+        "o9": 0,                        // 可写死, 网页固定值
+        "sde": "0,0,0,0,1,0,0",         // 可写死
+        "pmo": "",                      // 可写死, 网页固定值
+        "dpw": "",                      // 可写死, 网页固定值
+        "pac": "",                      // 可写死, 网页固定值
+        "per": '能写死',                                                                                      // 逆向----------------------------------
+        "dsi": dsi,                     // 可写死, 数组:12位
+        "wsl": "2172649472,76515477,62483333,100,1,1,1,1,0,1,,,,,,0,,,1,1",   // 可写死  前3个数字是浏览器堆内存信息 中间2个数在变化
+        "hls": "-1,,,1,1",              // 可写死, 网页固定值
+        "pde": "",                      // 可写死
+        "fwd": [{"fmh": ""}, {"fmz": "1"}, {"ssh": "79d476b3ee7a1d053d47c234f8b00e881ef941614b47791e1d4610cb5e47a0ff"}],  // 可写死
+    }
+
+}
+
+
+// 公共方法
+var TSK = function (INK) {
+    if (INK == null)
+        return -1;
+    try {
+        var I8K = 0;
+        for (var IjK = 0; IjK < INK["length"]; IjK++) {
+            var UQK = INK["charCodeAt"](IjK);
+            if (UQK < 128) {
+                I8K = I8K + UQK;
+            }
+        }
+        return I8K;
+    } catch (JHK) {
+        console.log('报错逻辑....')
+        return -2;
+    }
+};
+
+// XHK, 需要 AMK["fpValStr"] 值
+function fpc(val) {
+    return "".concat(TSK(val));
+}
+
+
+// ajr ---------------------------------
+function ajr(startTimestamp) {
+    var lfv = function (Jw) {
+        var rTv = function (bxv, g8v) {
+            return bxv >>> g8v | bxv << 32 - g8v;
+        };
+        var kw = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
+        var Jl = 0x6a09e667;
+        var BXv = 0xbb67ae85;
+        var SVv = 0x3c6ef372;
+        var FCv = 0xa54ff53a;
+        var VTv = 0x510e527f;
+        var tEv = 0x9b05688c;
+        var ttv = 0x1f83d9ab;
+        var hVv = 0x5be0cd19;
+        var SUv = unescape(encodeURIComponent(Jw));
+        var hXv = SUv["length"] * 8;
+        SUv += String["fromCharCode"](0x80);
+        var Sfv = SUv["length"] / 4 + 2;
+        var pw = Math["ceil"](Sfv / 16);
+        var nfv = new (Array)(pw);
+        for (var Ol = 0; Ol < pw; Ol++) {
+            nfv[Ol] = new (Array)(16);
+            for (var fLv = 0; fLv < 16; fLv++) {
+                nfv[Ol][fLv] = SUv["charCodeAt"](Ol * 64 + fLv * 4) << 24 | SUv["charCodeAt"](Ol * 64 + fLv * 4 + 1) << 16 | SUv["charCodeAt"](Ol * 64 + fLv * 4 + 2) << 8 | SUv["charCodeAt"](Ol * 64 + fLv * 4 + 3) << 0;
+            }
+        }
+        var VCv = hXv / Math["pow"](2, 32);
+        nfv[pw - 1][14] = Math["floor"](VCv);
+        nfv[pw - 1][15] = hXv;
+        for (var Fbv = 0; Fbv < pw; Fbv++) {
+            var GTv = new (Array)(64);
+            var khv = Jl;
+            var jXv = BXv;
+            var Ydv = SVv;
+            var jtv = FCv;
+            var cl = VTv;
+            var Ehv = tEv;
+            var Vfv = ttv;
+            var ddv = hVv;
+            for (var Jvv = 0; Jvv < 64; Jvv++) {
+                var qCv = void 0
+                    , lvv = void 0
+                    , Kq = void 0
+                    , vtv = void 0
+                    , Dnv = void 0
+                    , NCv = void 0;
+                if (Jvv < 16)
+                    GTv[Jvv] = nfv[Fbv][Jvv];
+                else {
+                    qCv = rTv(GTv[Jvv - 15], 7) ^ rTv(GTv[Jvv - 15], 18) ^ GTv[Jvv - 15] >>> 3;
+                    lvv = rTv(GTv[Jvv - 2], 17) ^ rTv(GTv[Jvv - 2], 19) ^ GTv[Jvv - 2] >>> 10;
+                    GTv[Jvv] = GTv[Jvv - 16] + qCv + GTv[Jvv - 7] + lvv;
+                }
+                lvv = rTv(cl, 6) ^ rTv(cl, 11) ^ rTv(cl, 25);
+                Kq = cl & Ehv ^ ~cl & Vfv;
+                vtv = ddv + lvv + Kq + kw[Jvv] + GTv[Jvv];
+                qCv = rTv(khv, 2) ^ rTv(khv, 13) ^ rTv(khv, 22);
+                Dnv = khv & jXv ^ khv & Ydv ^ jXv & Ydv;
+                NCv = qCv + Dnv;
+                ddv = Vfv;
+                Vfv = Ehv;
+                Ehv = cl;
+                cl = jtv + vtv >>> 0;
+                jtv = Ydv;
+                Ydv = jXv;
+                jXv = khv;
+                khv = vtv + NCv >>> 0;
+            }
+            Jl = Jl + khv;
+            BXv = BXv + jXv;
+            SVv = SVv + Ydv;
+            FCv = FCv + jtv;
+            VTv = VTv + cl;
+            tEv = tEv + Ehv;
+            ttv = ttv + Vfv;
+            hVv = hVv + ddv;
+        }
+        return [Jl >> 24 & 0xff, Jl >> 16 & 0xff, Jl >> 8 & 0xff, Jl & 0xff, BXv >> 24 & 0xff, BXv >> 16 & 0xff, BXv >> 8 & 0xff, BXv & 0xff, SVv >> 24 & 0xff, SVv >> 16 & 0xff, SVv >> 8 & 0xff, SVv & 0xff, FCv >> 24 & 0xff, FCv >> 16 & 0xff, FCv >> 8 & 0xff, FCv & 0xff, VTv >> 24 & 0xff, VTv >> 16 & 0xff, VTv >> 8 & 0xff, VTv & 0xff, tEv >> 24 & 0xff, tEv >> 16 & 0xff, tEv >> 8 & 0xff, tEv & 0xff, ttv >> 24 & 0xff, ttv >> 16 & 0xff, ttv >> 8 & 0xff, ttv & 0xff, hVv >> 24 & 0xff, hVv >> 16 & 0xff, hVv >> 8 & 0xff, hVv & 0xff];
+    };
+    var gTv = function (RNv) {
+        return Math["floor"](Math["random"]() * RNv["length"]);
+    };
+    var Fw = function (kzv) {
+        var W3v = '';
+        for (var F6v = 0; F6v < kzv["length"]; F6v++) {
+            W3v += kzv[F6v]["toString"](16)["length"] === 2 ? kzv[F6v]["toString"](16) : "0"["concat"](kzv[F6v]["toString"](16));
+        }
+        return W3v;
+    };
+
+    var fDv = Fw(lfv(btoa(startTimestamp)));
+    var tfv = [];
+    var dnv = "";
+    for (var XVv = 0; XVv < 5; XVv++) {
+        var Pgv = gTv(fDv);
+        tfv["push"](Pgv);
+        dnv = dnv + fDv[Pgv];
+    }
+    var zCv = [dnv, tfv];
+    return zCv["join"]("|")
+}
+
+
+// din 23arr ----------------------- 第 5 个
+function din(startTs) {
+
+    ` **************** adp 生成过程(可写死) ***************
+    
+    var Q56 = window['callPhantom'] ? 1 : 0;                                        // 值为 0 ,  检测无头浏览器
+    var kR6 = window['ActiveXObject'] && 'ActiveXObject' in window ? 1 : 0;         // 值为 0 ,  识别 IE 浏览器(ActiveXObject 是 IE 特有的属性
+    var pW6 = typeof window['document']['documentMode'] == 'number' ? 1 : 0;        // 值为 0 ,  检测 IE 文档模式(document.documentMode 是 IE 特有属性)
+    var cc6 = window['chrome'] && window['chrome']['webstore'] ? 1 : 0;             // 值为 0 ,  检测 Chrome 浏览器
+    var UR6 = window['navigator']['onLine'] ? 1 : 0;                                // 值为 1 ,  检测网络状态,  navigator.onLine可判断浏览器是否在线
+    var mk6 = window['opera'] ? 1 : 0;                                              // 值为 0 ,  检测旧版 Opera 浏览器(opera 是旧版 Opera 特有)
+    var VZ6 = typeof window['InstallTrigger'] !== 'undefined' ? 1 : 0;              // 值为 0 ,  检测 Firefox 浏览器(InstallTrigger 是 Firefox 特有属性)
+    var rQ6 = window['HTMLElement'] && window['Object']['prototype']['toString'].call(window['HTMLElement'])['indexOf']('Constructor') > 0 ? 1 : 0;  // 值为 0 ,
+    var g36 = typeof window['RTCPeerConnection'] === 'function' || typeof window['mozRTCPeerConnection'] === 'function'  // 值为 1 , 判断浏览器是否支持 WebRTC
+    var Ng6 = 'mozInnerScreenY' in window ? window['mozInnerScreenY'] : 0;          // 值为 0 ,  检测 Firefox 特定属性
+    var OL6 = typeof window['navigator']['vibrate'] === 'function' ? 1 : 0;         // 值为 1 ,  检查设备是否支持振动
+    var Wc6 = typeof window['navigator']['getBattery'] === 'function' ? 1 : 0;      // 值为 1 ,  检查电池API支持
+    var U96 = !window['Array']['prototype']['forEach'] ? 1 : 0;                     // 值为 0 ,  检测 ES5 数组方法支持
+    var EC6 = 'FileReader' in window ? 1 : 0;                                       // 值为 1 ,  检测是否支持文件读取
+    
+    var nS6 = 'cpen:'['concat'](Q56, ',i1:')['concat'](kR6, ',dm:')['concat'](pW6, ',cwen:')['concat'](cc6, ',non:')['concat'](UR6, ',opc:')['concat'](mk6, ',fc:')['concat'](VZ6, ',sc:')['concat'](rQ6, ',wrc:')['concat'](g36, ',isc:')['concat'](Ng6, ',vib:')['concat'](OL6, ',bat:')['concat'](Wc6, ',x11:')['concat'](U96, ',x12:')['concat'](EC6);
+    `
+
+    // PMK ------------------------------------------ ran 生成 ----------------------------------------------------------
+    var ZEK = Math.random()
+    var KDK = parseInt(ZEK * 1000 / 2, 10)
+    var PMK = "".concat(ZEK).slice(0, 11) + KDK
+
+    var Arr23 = [
+        {"wdr": 0},                         // window.webdriver ? 1 : 0; =>  0
+        {"xag": 12147},                     // 不会js文件是不一样的  网页固定值 RcK(973, [])
+        {"asw": 1920},                      // window.screen.availWidth
+
+        {"nal": "zh-CN"},                   // navigator['language']
+        {"wow": 1920},                      // window.outerWidth
+
+        // 将时间戳 window.bmak.startTs 除以固定数值 (2016*2016)4064256,并将结果转换为十进制整数
+        {"hz1": parseInt(startTs / 4064256, 10)},
+
+        {"nps": "20030107"},                // navigator['productSub']
+        {"pha": 0},                         // window._phantom ? 1 : 0;  =>  0
+        {"ibr": 0},                         // 网页固定值
+        {"adp": "cpen:0,i1:0,dm:0,cwen:0,non:1,opc:0,fc:0,sc:0,wrc:1,isc:0,vib:1,bat:1,x11:0,x12:1"}, // SKK()
+        {"hal": startTs / 2},               // ZqK = window.bmak.startTs / 2
+        {"ucs": "8106"},                    // CCK 生成逻辑 ''.concat(TSK(navigator.userAgent))  =》 '8106'
+        {"she": 1080},                      // window.screen.height => 1080
+        {"wih": 919},                       // window.innerHeight   =>  919
+        {"ash": 1040},                      // window.screen.availHeight
+        {"dau": 0},                         // window.domAutomation ? 1 : 0; => 0
+        {"wiw": 1920},                      // window.innerWidth    => 1920  616??
+        {"nap": "Gecko"},                   // navigator['product']
+        {"npl": 5},                         // navigator['plugins']['length']
+        {"swi": 1920},                      // window.screen.width  =>
+        {"tsd": 0},                         // 网页固定值
+        {"ua": navigator.userAgent},
+        {"ran": PMK},                       // 随机值(应该可以写死)
+    ]
+
+    return Arr23
+}
+
+
+function mst(startTs, ajr) {
+
+    // 时间戳差值
+    var Bmd = Date.now() - startTs;
+
+    // window.bmak.startTs = startTs
+    require('./扣算法2')
+
+    var dbd = dDd(startTs);
+    console.log('ajr', ajr)
+    Agd = arg1.Gb(0, ajr, 1, 0)
+    console.log(Agd)
+    return [
+        {'kevl': 1},
+        {'mevl': 32},
+        {'tevl': 32},
+        {'devl': 0},
+        {'dmvl': 0},  // 变化的
+        {'pevl': 0},
+        {'tovl': 0},  // 变化的
+        {'delt': Bmd},  // 时间戳差值
+        {'it': 0},
+        {'sts': startTs},
+        {'fct': -999999},  // HAd['td']
+        {'dd2': parseInt(parseInt(startTs / 4064256, 10) / 23, 10)},
+        {'kc': 0},
+        {'mc': 0},
+        {'ww8': 0},
+        {'pc': 0},
+        {'tc': 0},
+        {'ssts': Bmd},  // 时间戳差值
+        {'tst': 0},
+        {'rval': '-1'}, // HAd['rVal']
+        {'rcfp': '-1'}, // HAd['rCFP']
+        {'nfas': 30261693},
+        {'jsrf': "PiZtE"},
+        {'jsrf1': dbd[0]}, //开始时间戳 计算的随机值
+        {'jsrf2': dbd[1]},
+        {'signals': '0'},
+        {'mwd': "0"},
+        {'hea': ''},
+        // 第1个值根据 ajr 生成   第2个值是时间戳差值  第3个是根据环境判断得来的  不同js会变
+        {'dvc': ''['concat'](Agd, ',')['concat'](0, ',')['concat']("i+j+g+d+k+h+f+l+")},  // 不能写死 尤其是第一个值 ------------
+        {'srd': "0"}
+    ];
+}
+
+var dDd = function (YS) {
+    var P3 = function (ZA) {
+        var SW = ZA[0] - ZA[1];
+        var ng = ZA[2] - ZA[3];
+        var sb = ZA[4] - ZA[5];
+        var CJ = Math["sqrt"](SW * SW + ng * ng + sb * sb);
+        return Math["floor"](CJ);
+    };
+    var H7d = Math["floor"](Math["random"]() * 100000 + 10000);
+    var vZ = String(YS * H7d);
+    var sQd = 0;
+    var P4d = [];
+    var Ffd = vZ["length"] >= 18 ? true : false;
+    while (P4d["length"] < 6) {
+        P4d["push"](parseInt(vZ["slice"](sQd, sQd + 2), 10));
+        sQd = Ffd ? sQd + 3 : sQd + 2;
+    }
+    var FMd = P3(P4d);
+    return [H7d, FMd];
+};
+
+
+// console.log(JSON.stringify(mst(1745981943082)));
+console.log(getObj(1746587916230))
+
+
+// console.log(arg1.Gb(141296, "46e1c|63,3,35,62,19", 1, 12250583))
+console.log(dDd(1746587916230))
+
+
+
+
+
+
+
+
+
+
+// wsl --------------------------------------------------------------------------------
+
+var U9x = function () {
+    var MGx = "-1,-1,-1";
+    //  window.performance.memory; 获取 JavaScript 内存使用情况
+    `   返回一个包含以下属性的对象(示例值):
+
+属性	类型	描述
+usedJSHeapSize	number	当前 JavaScript 堆内存已使用的字节数(实际使用量)。
+totalJSHeapSize	number	当前 JavaScript 堆内存总分配的字节数(包含未使用的空闲内存)。
+jsHeapSizeLimit	number	JavaScript 堆内存的最大限制字节数(由浏览器或系统决定)
+`
+    if (window['performance'] && window['performance']['memory']) {
+        var sGx = window['performance']['memory'];
+        MGx = ''['concat'](sGx['jsHeapSizeLimit'], ',')['concat'](sGx['totalJSHeapSize'], ',')['concat'](sGx['usedJSHeapSize']);
+    }
+    var OGx = ''['concat'](MGx, ',')['concat']("950");
+    return OGx
+
+};
+
+
+//用于获取浏览器支持的​​语音合成(TTS,Text-to-Speech)的语音列表
+var k5x = window["speechSynthesis"]["getVoices"]();  // 20
+V1x = k5x['length']
+
+Mkx = ''['concat'](U9x(), ',')['concat'](V1x);
+
+W0x = ''.concat(Mkx, ',')['concat']('1,1,1', ',')['concat']("0", ',')['concat'](pRx, ',,,,,,')['concat'](f5x, ',,,')
+
+
+// 第4个数要注意
+wsl = "2248146944,110285101,98152829, 950, 20, 1,1,1,0,1,,,,,,0,,,1,1"
+
+
+// per --------------------------------------------------------------------------------
+Q0x = '999999'['concat'](P1x['slice'](wm, 2)['join'](''), '9')['concat'](P1x[lz], '9')['concat'](P1x['slice'](S1)['join'](''), '999');
+
+
+// fwd --------------------------------------------------------------------------------
+var qtx = function () {
+    c1x = [{"fmh": ""}, {'fmz': "1"}, {"ssh": K5x || ''}]
+    return c1x;
+};
+
+
+// mst --------------------------------------------------------------------------------
+
+// 时间戳差值
+var Bmd = Date.now() - window.bmak["startTs"];
+NGd = parseInt(window.bmak['startTs'] / 4064256, 10);
+
+WYd = parseInt(NGd / 23, 10);
+
+// 时间戳差值
+var Omd = Date.now() - window.bmak["startTs"]
+var dDd = function (YS) {
+    var H7d = Math["floor"](Math["random"]() * 100000 + 10000);
+    var vZ = String(YS * H7d);
+    var sQd = 0;
+    var P4d = [];
+    var Ffd = vZ["length"] >= 18 ? true : false;
+    while (P4d["length"] < 6) {
+        P4d["push"](parseInt(vZ["slice"](sQd, sQd + 2), 10));
+        sQd = Ffd ? sQd + 3 : sQd + 2;
+    }
+    var FMd = P3(P4d);
+    return [H7d, FMd];
+};
+var P3 = function (ZA) {
+    var SW = ZA[0] - ZA[1];
+    var ng = ZA[2] - ZA[3];
+    var sb = ZA[4] - ZA[5];
+    var CJ = Math["sqrt"](SW * SW + ng * ng + sb * sb);
+    return Math["floor"](CJ);
+};
+var dbd = dDd(window.bmak['startTs']);
+
+DAd = "1,4815,3,1605,5,963"
+ Agd = Qc(Bmd, DAd, 0, 0);
+var r8d = [
+    {'kevl': 1},
+    {'mevl': 32},
+    {'tevl': 32},
+    {'devl': 0},
+    {'dmvl': 0},
+    {'pevl': 0},
+    {'tovl': 0},
+    {'delt': Bmd},  // 时间戳差值
+    {'it': 0},
+    {'sts': window.bmak['startTs']},
+    {'fct': -999999},  // HAd['td']
+    {'dd2': WYd},
+    {'kc': 0},
+    {'mc': 0},
+    {'ww8': 0},
+    {'pc': 0},
+    {'tc': 0},
+    {'ssts': Omd},
+    {'tst': 0},
+    {'rval': '-1'}, // HAd['rVal']
+    {'rcfp': '-1'}, // HAd['rCFP']
+    {'nfas': 30261693},
+    {'jsrf': "PiZtE"},
+    {'jsrf1': dbd[0]}, //开始时间戳 计算的值  会变
+    {'jsrf2': dbd[1]},
+    {'signals': '0'},
+    {'mwd': "0"},
+    {'hea': ''},
+    {'dvc': ''['concat'](Agd, ',')['concat'](0, ',')['concat']("l+g+e+a+i+f+j+c+h+b+d+k+")},  // kAd
+    {'srd': "0"}
+];
+
+
+// sde --------------------------------------------------------------------------------
+// var TKd = window['$cdc_asdjflasutopfhvcZLmcfl_'] || document['$cdc_asdjflasutopfhvcZLmcfl_'] ? true ? '1' : Mr()[LJ(kq)](XF, xMd) : gq(typeof Ik()[dY(bY)], 'undefined') ? Ik()[dY(F9)].apply(null, [T2, rdd, RN, Qm(F8)]) : Ik()[dY(Lm)](v9, rk, qr, v9);
+// var Kfd = RI(m4[AI()[Qz(mb)].call(null, gY, rV)][AI()[Qz(Ck)](lq, wF)][Ik()[dY(O3)](xr, Zr, jY, BN)][tk()[Ir(PB)].apply(null, [FW, Nm, mj, Ew])](tk()[Ir(S3)].apply(null, [lz, ON, YY, I4])), null) ? Mr()[LJ(BI)](vN, qA) : cJ(typeof Ik()[dY(PB)], gb('', [][[]])) ? Ik()[dY(Lm)](Qm(Qm(F8)), rk, qr, n9) : Ik()[dY(F9)](n3, cxd, KZ, Nm);
+// var Fnd = RI(typeof m4[cJ(typeof AI()[Qz(wp)], gb([], [][[]])) ? AI()[Qz(S3)](Nb, Am) : AI()[Qz(Lp)](nW, Dw)][tk()[Ir(S3)](xY, UN, YY, I4)], AI()[Qz(qm)].apply(null, [H9, FP])) && m4[AI()[Qz(S3)].call(null, Nb, Am)][tk()[Ir(S3)](kp, Sr, YY, I4)] ? Mr()[LJ(BI)].call(null, vN, qA) : Ik()[dY(Lm)](DJ, rk, qr, Ag);
+//
+//
+// var V6 = RI(typeof m4[cJ(typeof AI()[Qz(Ib)], gb([], [][[]])) ? AI()[Qz(mb)](gY, rV) : AI()[Qz(Lp)](rl, LO)][tk()[Ir(S3)](dz, sI, YY, I4)], AI()[Qz(qm)].apply(null, [H9, FP])) ? Mr()[LJ(BI)].apply(null, [vN, qA]) : Ik()[dY(Lm)](kq, rk, qr, X3);
+// dZ += rx;
+// var P1 = cJ(typeof m4[AI()[Qz(mb)].call(null, gY, rV)][Ik()[dY(Hm)].apply(null, [X3, WN, hk, Qm(Lm)])], AI()[Qz(qm)](H9, FP)) || cJ(typeof m4[AI()[Qz(Ck)](lq, wF)][gq(typeof Ik()[dY(jk)], 'undefined') ? Ik()[dY(F9)](dg, ZR, rB, Qm(Qm(Lm))) : Ik()[dY(Hm)].apply(null, [S3, WN, hk, Vr])], AI()[Qz(qm)].call(null, H9, FP)) ? Mr()[LJ(BI)](vN, qA) : Ik()[dY(Lm)](Ng, rk, qr, lz);
+// var zF = RI(m4[gq(typeof AI()[Qz(Fb)], gb([], [][[]])) ? AI()[Qz(Lp)].call(null, tN, IA) : AI()[Qz(mb)].apply(null, [gY, rV])][AI()[Qz(Ck)](lq, wF)][Ik()[dY(O3)].apply(null, [kr, Zr, jY, d8])][gq(typeof tk()[Ir(PJ)], gb([], [][[]])) ? tk()[Ir(X9)](mb, d8, tW, JR) : tk()[Ir(PB)](W3, LI, mj, Ew)](tk()[Ir(kb)](DJ, Ng, sq, zO)), null) ? gq(typeof Mr()[LJ(ON)], gb([], [][[]])) ? Mr()[LJ(kq)](t6, mF) : Mr()[LJ(BI)].apply(null, [vN, qA]) : Ik()[dY(Lm)](Qm(Qm(Lm)), rk, qr, xz);
+// var Tz = RI(m4[AI()[Qz(mb)](gY, rV)][AI()[Qz(Ck)](lq, wF)][Ik()[dY(O3)](Lm, Zr, jY, fr)][cJ(typeof tk()[Ir(HZ)], 'undefined') ? tk()[Ir(PB)].apply(null, [nW, Qm([]), mj, Ew]) : tk()[Ir(X9)](Qm(Qm([])), sp, YA, m3)](FY()[PW(lm)](Qm([]), lz, xs, ql, H9, Op)), null) ? gq(typeof Mr()[LJ(XY)], gb('', [][[]])) ? Mr()[LJ(kq)](IZ, I8) : Mr()[LJ(BI)].call(null, vN, qA) : Ik()[dY(Lm)].apply(null, [Qm([]), rk, qr, Lr]);
+// var vw = [TKd, Kfd, Fnd, V6, P1, zF, Tz];
+// var Kl = vw[Mr()[LJ(At)].apply(null, [JUd, YA])](lW()[Gp(XY)].apply(null, [vv, Lm, Nq, x3]));

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 836 - 0
3.31Gk航司/akm逆向/扣算法2.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 829 - 0
3.31Gk航司/akm逆向/逆向.js


+ 40 - 0
3.31Gk航司/tls - ja3 指纹.py

@@ -0,0 +1,40 @@
+from tls_client import Session
+
+# 自定义 JA3 字符串
+ja3 = "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0"
+
+session = Session(
+    client_identifier="Chrome_120",
+    random_tls_extension_order=True,
+
+)
+headers = {
+    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+    "accept-language": "zh-CN,zh;q=0.9",
+    "cache-control": "no-cache",
+    "pragma": "no-cache",
+    "priority": "u=0, i",
+    "referer": "https://booking.jetstar.com/",
+    "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+    "sec-ch-ua-mobile": "?0",
+    "sec-ch-ua-platform": "\"Windows\"",
+    "sec-fetch-dest": "document",
+    "sec-fetch-mode": "navigate",
+    "sec-fetch-site": "same-origin",
+    "sec-fetch-user": "?1",
+    "upgrade-insecure-requests": "1",
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
+}
+
+session.headers.update(headers)
+
+response = session.get("https://tls.peet.ws/api/all", headers=headers)
+print(response.text)
+
+
+"""
+2eb0a61fa86253c470b1d53224c0f7ad
+74c901ecc2a908b2f4b458d0fcbbbcd9
+b6d8149144237b3e6a1cf629b4a0abfa
+
+"""

+ 8 - 0
3.31Gk航司/其他/.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 8 - 0
3.31Gk航司/其他/.idea/3.31Gk航司.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="jdk" jdkName="Python 3.9 (py3.9) (3)" jdkType="Python SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 38 - 0
3.31Gk航司/其他/.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,38 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <Languages>
+        <language minSize="125" name="JavaScript" />
+        <language minSize="68" name="Python" />
+      </Languages>
+    </inspection_tool>
+    <inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoredPackages">
+        <value>
+          <list size="11">
+            <item index="0" class="java.lang.String" itemvalue="selenium-wire" />
+            <item index="1" class="java.lang.String" itemvalue="pymongo" />
+            <item index="2" class="java.lang.String" itemvalue="pyhttpx" />
+            <item index="3" class="java.lang.String" itemvalue="selenium" />
+            <item index="4" class="java.lang.String" itemvalue="undetected-chromedriver" />
+            <item index="5" class="java.lang.String" itemvalue="seleniumbase" />
+            <item index="6" class="java.lang.String" itemvalue="pyexecjs" />
+            <item index="7" class="java.lang.String" itemvalue="requests" />
+            <item index="8" class="java.lang.String" itemvalue="loguru" />
+            <item index="9" class="java.lang.String" itemvalue="xdeek-logger" />
+            <item index="10" class="java.lang.String" itemvalue="redis" />
+          </list>
+        </value>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="N806" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>

+ 6 - 0
3.31Gk航司/其他/.idea/inspectionProfiles/profiles_settings.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>

+ 7 - 0
3.31Gk航司/其他/.idea/misc.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (py3.9) (3)" project-jdk-type="Python SDK" />
+</project>

+ 8 - 0
3.31Gk航司/其他/.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/3.31Gk航司.iml" filepath="$PROJECT_DIR$/.idea/3.31Gk航司.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
3.31Gk航司/其他/1.html

@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
+<HTML><HEAD><TITLE>Bad Request</TITLE>
+<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
+<BODY><h2>Bad Request - Invalid Header</h2>
+<hr><p>HTTP Error 400. The request has an invalid header name.</p>
+<script type="text/javascript"  src="/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"></script></BODY></HTML>

+ 197 - 0
3.31Gk航司/其他/ast/ast.js

@@ -0,0 +1,197 @@
+const fs = require('fs')
+const parser = require('@babel/parser') // 解析 JavaScript 代码
+const traverse = require('@babel/traverse').default // 遍历 AST
+const generator = require('@babel/generator').default // 生成代码
+const t = require('@babel/types')
+
+
+// 定义文件路径
+const input_js = './encode.js'
+const output_js = './decode.js'
+
+// 读取文件内容并解析成 AST
+const js_code = fs.readFileSync(input_js, {encoding: 'utf-8'})
+
+
+const ast = parser.parse(js_code)  // 解析代码为 AST
+
+// 字面量访问器 -------------------------------
+const varPool = new Map(); // 存储(第一个函数)计算出的变量值
+const varPool2 = new Map(); // 存储(第二个函数)计算出的变量值
+
+const visitor_literal = {
+    // 第一阶段:处理 QxN 函数
+    FunctionDeclaration(path) {
+        let {id} = path.node
+        let bodyPath = path.get('body')
+        if (!t.isIdentifier(id, {name: 'QxN'})) return;
+
+        bodyPath.traverse({
+            AssignmentExpression(path) {
+                const rightPath = path.get('right'); // 获取右侧表达式的路径(左边是变量名)
+                const var_name = path.node.left.name  // 获取左侧的变量名
+                // evaluate() 方法是路径对象(Path)提供的方法,而非节点(Node)本身的方法。你需要通过路径来调用该方法
+                const evaluated = rightPath.evaluate(); // 调用evaluate()
+
+                if (evaluated.confident) {
+                    let value = evaluated.value
+                    varPool.set(var_name, value); // 存储变量值
+                    console.log(rightPath.toString(), '=>', value); // 输出确定的值
+                    rightPath.replaceWith(t.valueToNode(value))  // 替换为字面量
+                } else {
+                    console.log('无法静态求值');
+                }
+
+            }
+        })
+
+    },
+    Program: {
+        exit(path) {
+            // 第二阶段:在所有节点处理完成后处理 ShN 函数
+            path.traverse({
+                FunctionDeclaration(path) {
+                    let {id} = path.node
+                    let bodyPath = path.get('body')
+                    if (!t.isIdentifier(id, {name: 'ShN'})) return;
+
+                    bodyPath.traverse({
+                        AssignmentExpression(path) {
+                            const rightPath = path.get('right');
+                            const var_name = path.node.left.name  // 获取左侧的变量名
+                            // evaluate() 方法是路径对象(Path)提供的方法,而非节点(Node)本身的方法。你需要通过路径来调用该方法
+                            // 继续遍历rightPath下的节点,替换已知变量引用为字面量
+                            rightPath.traverse({
+                                // subPath表示子路径,定位子路径下的标识符
+                                Identifier(subPath) {
+                                    if (varPool.has(subPath.node.name)) {
+                                        subPath.replaceWith(
+                                            t.valueToNode(varPool.get(subPath.node.name))
+                                        )
+                                    }
+                                }
+                            });
+
+                            // 再次尝试计算表达式
+                            const evaluated = rightPath.evaluate();
+                            if (evaluated.confident) {
+                                let value = evaluated.value
+                                varPool2.set(var_name, value)
+                                console.log(rightPath.toString(), '=>', evaluated.value); // 输出确定的值
+
+                                rightPath.replaceWith(t.valueToNode(evaluated.value));
+                            }
+                        }
+
+                    })
+
+                }
+
+            });
+        }
+    }
+};
+
+
+// 定位 return j2.call(this, xL);
+const visitor_ = {
+
+    CallExpression(path) {
+        let {callee} = path.node
+
+        if (!t.isFunctionExpression(callee)) return;
+
+        path.traverse({
+            ReturnStatement(path) {
+                let {argument} = path.node
+                if (!t.isCallExpression(argument)) return;
+
+                let {callee: {property,}, arguments: args} = argument
+
+                if (args.length !== 2 || !t.isIdentifier(property, {name: 'call'})) return;
+                console.log(path.toString())
+
+
+            }
+        })
+
+    },
+
+}
+
+
+// 控制流平坦化访问器 -------------------------------
+function return_num(varStr) {
+    // 根据变量字符串,返回对应变量值
+    if (varPool.has(varStr) || varPool2.has(varStr)) {
+        return varPool[varStr] || varPool2[varStr]
+    }
+    console.warn(`${varStr}未找到`)
+
+}
+
+const visitor_for = {
+    ForStatement(path) {
+        const {test, body} = path.node;     // 解构循环条件和循环体
+
+        // let {} = test                       // 从循环条件取出具体值,在变量值map中查找,方便下面循环处理
+
+        // 初始状态变量值
+        let init_name = 'HO';               // 状态变量名
+        let init_value = 3;                 // 初始状态值
+
+        const switch_body = body.body[0];   // 提取循环体内的switch语句
+
+        // 验证是否为 Switch 语句,否则终止处理
+        if (!t.isSwitchStatement(switch_body)) return;
+
+        const {discriminant, cases} = switch_body;  // 解构 Switch 的条件和分支列表
+
+        // 验证 Switch 条件是否为指定状态变量
+        if (!t.isIdentifier(discriminant, {name: init_name})) return;
+
+        const ret_body = [];               // 存储最终生成的代码块集合
+        let end_flag = false;              // 终止循环处理标志
+
+        while (init_value !== 662) {       // 循环处理所有状态分支
+            if (end_flag) break;           // 检测终止条件
+
+            for (const each_case of cases) {              // 遍历 Switch 的所有 case 分支
+                const {test, consequent} = each_case;     // 从case分支中取出条件和对应代码块
+
+
+                if (init_value !== test.name) continue;  // 跳过非当前状态的 case 分支
+
+
+            }
+
+
+        }
+    }
+}
+
+const visitor_while = {
+    VariableDeclarator(path) {
+        let {id, init} = path.node
+
+        if (!t.isIdentifier(id, {name: 'j2'})) return
+
+        path.traverse(visitor_for)
+        // console.log(id.name)
+    }
+}
+
+
+traverse(ast, visitor_literal); // 还原初始化2个变量赋值函数
+// traverse(ast, visitor_);
+// traverse(ast, visitor_while);
+
+console.log(varPool2)
+
+// 使用 Babel 生成新的代码
+let {code} = generator(ast)
+
+
+// 将生成的代码写入指定的文件
+// fs.writeFile(output_js, code, (err) => {
+// })

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 264 - 0
3.31Gk航司/其他/ast/decode.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 59 - 0
3.31Gk航司/其他/ast/encode.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3191 - 0
3.31Gk航司/其他/ast/收集函数加密/ast.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 59 - 0
3.31Gk航司/其他/ast/收集函数加密/decode.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 59 - 0
3.31Gk航司/其他/ast/收集函数加密/encode.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 0
3.31Gk航司/其他/bm_sz 生成/分析


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 30 - 0
3.31Gk航司/其他/bm_sz 生成/第一次请求akm.py


+ 64 - 0
3.31Gk航司/其他/cookie参数测试.py

@@ -0,0 +1,64 @@
+
+
+# 只带 SEFD 和 ASP.NET_SessionId 会报错
+cookies = {
+    # "$date_selected": "0",
+    # "optimizelyEndUserId": "oeu1744595167365r0.8968549342456524",
+    # "bid_JSaU2TcvPguuhpZfmwr34R7R8Wo7moKH": "fbcdc2e7-4124-47b7-bd23-b63061f4e537",
+    # "AMCVS_8D0D1C8B532B54B40A490D4D%40AdobeOrg": "1",
+    # "bx_bucket_number": "42",
+    # "bx_guest_ref": "587456a6-5f66-49a4-80cf-d730c5c1a2ba",
+    # "s_cc": "true",
+    # "htjs_anonymous_id": "18b92168-bd03-4295-9296-1cf56b28cab6",
+    # "_gcl_au": "1.1.259153084.1744595174",
+    # "optimizelySession": "0",
+    # "_fbp": "fb.1.1744613560083.2120932399812202",
+    # "PlatformChannel": "REVTS1RPUA==",
+    # "PlatformAppVersion": "",
+    # "WorkFlow": "MA==",
+    # "s_sq": "%5B%5BB%5D%5D",
+    # "user-location": "country_code=AU,region_code=NSW,city=SYDNEY,lat=-33.88,long=151.22",
+    # "AKA_A2": "A",
+    # "bm_ss": "ab8e18ef4e",
+    # "ab.storage.deviceId.8eb26f80-6f07-43d3-be0e-778c98485224": "g%3Aee8e7ee6-34ae-480d-2a66-99bd0dad803b%7Ce%3Aundefined%7Cc%3A1743408255712%7Cl%3A1744684408023",
+    # "bxIDT": "",
+    # "gpv_mpl": "1",
+
+    # "mcp-pre-selected-currency": "null",
+    # "gpv_pn": "%2Fbooking%2Fselect-flights",
+    # "gpv_v1": "%2Fbooking-flow-ngbe",
+    # "__RequestVerificationToken": "_GsgZMqY1rXYqfQ96sUCXLjYpoBXK7mB8uLeplvbOZo15DEFJ5hzMFsUyH94rigM_AQr6-lDYwzzR7DVDXr6kYVmgOiZV8kq8puFpk18bg1IWGFwKW4tYCeyN6FUbXQtil0RSA2",
+    # "X-Session-Id": "24vpdrcoqoppqnveymu3eltv",
+    # "X-Session-Sig": "c0a2c5116a8bb863133cd0e3eeb8fb7e6a8cbf576210eace5f0fcd27d717d88a",
+
+    # 不带 SEFD 会触发验证码 (每次请求都会变化,请求成功后,响应cookie会返回这个值; 同一个代码中 SEFD只能请求4次 第5次时,就会触发验证码, 更换它就没事了)
+    "SEFD": "eyJPcmlnaW4iOiJQVkciLCJEZXN0aW5hdGlvbiI6IktNSSIsIlJvdW5kVHJpcCI6ZmFsc2UsIkRlcGFydHVyZURhdGUiOiIyMDI1LTA1LTMxVDAwOjAwOjAwIiwiUmV0dXJuRGF0ZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDAiLCJBZHVsdHMiOjEsIkNoaWxkcmVuIjowLCJJbmZhbnRzIjowfQ==",
+
+    # "bm_so": "7698670B499A260BE6A3F4AC213FB146A9A75B95EF674ED595B97F45A8CBB95A~YAAQAgUgF4+8zjKWAQAA4sBoNwPzlPg/g8PzigNKJ31ExpnJxMfQtD1Su5bRRWHD6koSoi9qOmYlXz74OC8wEcVuACq5tGPivwiQ60Sko+bH1LJfFZdmzSaI1iv03FzSYhrq/g3KLR217Bz+iAgEwNiwoHLR1uN0AsOiNOCTPsHEwETT3Y5f1EhJdBtzKllcjNRJAub5W0A+tzCc4Q+ALECFacB3WGsBiZqbVlebdQ1p9XM+egTC0DHDkY9DfIzCMBggR9kmz7hwjLORla8U5wkRFH5l46XpDu84D07fb8G7Qpfds9WrFg0Zv/JgRoCw2ciASKOkVJ0FdWe+YW2nJyVNHVR2MQZ9PA5o0AEgWCABDGGgiWxcqApsCdRcMQrja7+vZHJA+0oDm+CiYlVMl2IfCcMt958/54vutMalTjWdSrbyoSGez66K4AnU/n5wsPKs6lmp9kemr3yrxjarTQ==",
+    # "MT": "1744686338958",
+    # "ab.storage.sessionId.8eb26f80-6f07-43d3-be0e-778c98485224": "g%3Ae5689bcb-fc11-ff83-81a1-4f31bf107f85%7Ce%3A1744688139890%7Cc%3A1744684408021%7Cl%3A1744686339890",
+
+
+    # "s_nbs": "1744686342",
+    # "htjs_sesh": "{%22id%22:1744684429277%2C%22expiresAt%22:1744688144291%2C%22timeout%22:1800000%2C%22sessionStart%22:false%2C%22autoTrack%22:true}",
+    # "RT": "\"z=1&dm=jetstar.com&si=e684950f-3a6d-4647-9fe3-27df785970eb&ss=m9hw1mh9&sl=e&tt=7j7r&bcn=%2F%2F684d0d45.akstat.io%2F&obo=5&ld=15vtt\"",
+
+    # "flightIndex": "0",
+    # "bm_sv": "6A3EC4D0406D1A497A8C3FD65F715C94~YAAQJAUgF7fJ7h6WAQAAStFpNxtXE33mIKEHjS2pkJAKeXCnaFA9hsmQdlRonaOnxFRx5x4IkdB2YcIFgW0imoKXf9T0+0rYOa6i15SuC77zcuXcHN32TUA6Cy9LSM2eEC8UOkYVYBZGvAGxn35yoI6OI/eldQma6Uv8fHdCitt7l708KZi4/ox0yGA1A2ISo3YmveNg47x6pX/O4goi9u5+FaXsM/jMXDKGdFywWg/p513Is0eNv7OObAoC6UAH9Q==~1",
+
+    # 这个必须带,(同一个会话中 ASP.NET_SessionId 是不变的 待验证!!)
+    "ASP.NET_SessionId": "wf30ys1zm1y5zi3ius1vkbut",
+
+    # "dotrez": "\\u00219cFnD/LGKhSbWaTKjWHgUrSHoe1obMAGG8p4/HmpcTLZGKlG6ONGvIX5E/2f4TmQMoapbwu1IvZIdpI=",
+    # "_abck": "930E26A3CD6C8D10C55BDD4E4EE13B50~-1~YAAQHAUgF9H2BDWWAQAAxFhrNw0FT7RyViSSrpUtP3vZ0qAaoF037BWwFzO7OIoTvJtndrO304YZeE/dsGtt46swTSTlz8OhInpEstk1b4MZhMVUgArmxQSbUyumMBl9qXAjIsCe5goLmT8u5I1AndVLT7ESrGz1NACO8cBRkO4GESR6/ljHH/PZYXV5HjacZIy9oGlNWaXUXGRDqSesn5mylmB+xOkg5kiI302j4QKhTqOs1lr/lJibDerRpIxorsVlhRGJAyfbbzRQVlCQ3bDRgIXraQoJXvrKQOohBzvJ/I0aFZ3+Jp4iWKbhosOJydf80t4rDlxaoNEEYtk9NYOxc86iuPyVXWcBATloD6vPJTjWquFcpawn4I+DL/92se/bAKieFxciUm+kDgDIzIioDabit+UYU5nHe9KCHOUmetCKwel4OxoPcpBmdsCsNz/5f2krCjb16fxqxUDF0dZuXentP8Z5PSPB2bXAwxwMbB21/FhA8odoyWPvIbOIpTFAGEPvPP7MF4Ii8czDNQTMg0WG5BIq5oXWR3xGcDu1d2TgzaUzKuZ6YPFThItfAisNqqeJy6UmcC1Ia3NUjMlyeYF7TZYISLSGiQ6rYyfas3dKxTm+IsBm+0ol/M4lGpa+tjkIWO5FJVUn96xuRPdzy7QF7ZrxNAID8Cbpk+29fQIr9AYq0QZB3Mi9ByAbScGGcyhk09wpul+1ZJly~-1~-1~-1",
+    # "bm_s": "YAAQHAUgF9L2BDWWAQAAxFhrNwODr3pxx2fke2m/JKT6P2irIYpOHcTjOc4vL0Pt6uGWQt1lmMew5jdCwvRLrM5VAvNouDNBvtKOewwEZ8jmBDkT0VdZoXZprj6eEa6dS1lhlXC3kfaB7IFo/4qXsD735xtuKbUWNbaF34XcQPldBr+yJAQQbJdJaAOw9MYNG08HVPaGpacIW4EfcBHU6SMcugUHmyhepFoUQI7H4RDicVJmGheAKkG7D+aSxiOufTs5b9HhI8f0QU9czhZs1xFAs7T+AkIm1Nf35T3Ynr9vd0pq/JAm83/OP32qQjZwmE4L6oHMo6RnH+V/7pyK84EAq23sr19kd+8tonu+ii+dfJyNh0ULmJ8zI59lHbqPWoB+bhAaYLzeb4hVZMUwur6hvM1f8vVePAtUstr2SdxJoy7ASVqfJaCiGcixadLe0WzY64SUg/ZmT+xO",
+
+    # 只带 SEFD 和 ASP.NET_SessionId 会报错, 再带个 bm_sz 就可以
+    "bm_sz": "240D392558B96D94D296BEF81A894105~YAAQHAUgF9P2BDWWAQAAxFhrNxsOcABuBbRjbd+k1j02geHY6EEHSzBfigP7IJ7wKnbCuTcz+3pnnbljDPPVkkr/eenq4V0QfiTD5yBx81YoAGq47fmRw5QMThY3nkRz81gwwHgUPTlIWEE3qkiB6CtB/Ih/h+H9XKkPj79ynRIDSX8KVmEE8Uuv5QeaRNiaX0gdeqUHKionhtE02U9TdvOnGa6yh7gGBZyiME5N5eTHJziblAF4iY/IMU8Gw9aQYwF9S7lu5Ejm7LzjS8tpN0g64GiUEviC5f+To7aRTt7NTcHx4pgbOctg/nigwbgLSAxY2uOz0s1vVO3xr0GSLCq7nXliTfJ4KamL7yHfC/CqXROZy8dzFzqI4wOiM2BbfcLiHWhmhY9IGnBEOia3bvl7Vl1lxfRqpl92m+kWRmMpoyVNqWutvD8JlmF0bqLx6YusdVfsDYXhxuTASgUR3wDWZ4yBd8jsBG8dYvAwy2DmmIxOOqainI2xCO5PAzTnv3NiQojLNloYPzDzXMFo4g1cbwqv06OuP1IVAXx3PXiRC/VenlAw4D+LIORDXR7W~4601670~3617843",
+
+    # "_dd_s": "rum=2&id=c451fcb4-3547-4e95-937e-04435aae9853&created=1744684407029&expire=1744687421491",
+    # "s_getNewRepeat": "1744686521497-Repeat"
+    # "bm_lso":
+    # ak_bmsc
+    # AMCV_8D0D1C8B532B54B40A490D4D
+}

+ 71 - 0
3.31Gk航司/其他/demo2.py

@@ -0,0 +1,71 @@
+import requests
+
+
+headers = {
+    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+    "accept-language": "zh-CN,zh;q=0.9",
+    "cache-control": "no-cache",
+    "pragma": "no-cache",
+    "priority": "u=0, i",
+    "referer": "https://booking.jetstar.com/",
+    "sec-ch-ua": "\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"",
+    "sec-ch-ua-mobile": "?0",
+    "sec-ch-ua-platform": "\"Windows\"",
+    "sec-fetch-dest": "document",
+    "sec-fetch-mode": "navigate",
+    "sec-fetch-site": "same-origin",
+    "sec-fetch-user": "?1",
+    "upgrade-insecure-requests": "1",
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
+}
+
+url = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+params = {
+    "s": "true",
+    "adults": "1",
+    "children": "0",
+    "infants": "0",
+    "selectedclass1": "economy",
+    "currency": "CNY",
+    "mon": "true",
+    "channel": "DESKTOP",
+    "origin1": "PVG",
+    "destination1": "KMJ",
+    "departuredate1": "2025-05-12"
+}
+
+ip = '000000000024'
+proxies = {
+    'http': f'http://B_3351_HK___5_ss-{ip}:ev2pjj@proxy.renlaer.com:7778',
+    'https': f'http://B_3351_HK___5_ss-{ip}:ev2pjj@proxy.renlaer.com:7778'
+}
+cookies = {
+    # "ASP.NET_SessionId": "fs0akgjdzhdbwjdlk1345egb",
+
+    # "SEFD": "eyJPcmlnaW4iOiJQVkciLCJEZXN0aW5hdGlvbiI6IlFTVSIsIlJvdW5kVHJpcCI6ZmFsc2UsIkRlcGFydHVyZURhdGUiOiIyMDI1LTA2LTEyVDAwOjAwOjAwIiwiUmV0dXJuRGF0ZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDAiLCJBZHVsdHMiOjEsIkNoaWxkcmVuIjowLCJJbmZhbnRzIjowfQ==",
+
+    # "bm_sz": "1AF44A3B342C0D65F7FE487CEE4B582B~YAAQuqzbFxUlkUqWAQAA0aJOehsVzB0waQURNtQG+ozage9BslR5TVlORc0702ZswDMt5mhWFgT5YZcpMATNFJuEtK4l2IEjzc6A5qCfBaZHiYSbw/2wDEopU/xGH2mKKOyAArvP/Ui9bk4tpjBbOKE6KvMwzsmAs/0dO5Q40Py1YrDeJpFJlsQ+OTAEbdm1hl28uuzi118b02DSCtc9tG1pPFcs/x9BXVid1nILwcsg1XZf3s3basCdvkjUImUxxp71atqcVRr1Ho8s2NFzEFOj2hqhkNV4j4+Gumrgiyru7TQvn37BeRLqb3W8RIMhnQiC6FrUBlKLkdpdfVvBuhCTxX164Efg8PNLJudApfmrSW4t+3dZmng=~4277552~4277555",
+    "bm_sz": "1AF44A3B342C0D65F7FE487CEE4B582B~YAAQuqzbFxUlkUqWAQAA0aJOehsVzB0waQURNtQG+ozage9BslR5TVlORc0702ZswDMt5mhWFgT5YZcpMATNFJuEtK4l2IEjzc6A5qCfBaZHiYSbw/2wDEopU/xGH2mKKOyAArvP/Ui9bk4tpjBbOKE6KvMwzsmAs/0dO5Q40Py1YrDeJpFJlsQ+OTAEbdm1hl28uuzi118b02DSCtc9tG1pPFcs/x9BXVid1nILwcsg1XZf3s3basCdvkjUImUxxp71atqcVRr1Ho8s2NFzEFOj2hqhkNV4j4+Gumrgiyru7TQvn37BeRLqb3W8RIMhnQiC6FrUBlKLkdpdfVvBuhCTxX164Efg8PNLJudApfmrSW4t+3dZmng=~4277552~4277555",
+
+}
+response = requests.get(url, headers=headers, cookies=cookies, params=params,
+                        # proxies=proxies,
+                        timeout=15)
+
+
+print(response.text)
+print(response.cookies.get_dict().get('SEFD'))
+print(response)
+
+
+from lxml import etree
+import json
+
+html = etree.HTML(response.text)
+data = html.xpath("//script[@id='bundle-data-v2']/text()")[0]
+json_data = json.loads(data)
+print(json_data)
+
+
+
+# akm文件名称 2hOd3M

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 120 - 0
3.31Gk航司/其他/html解析.py


+ 3 - 0
3.31Gk航司/其他/test.js

@@ -0,0 +1,3 @@
+
+
+''['concat']('bJuuHvFXAI5wXS6lfXoa/bPz62/VEoOV5bodHyJ9lxU=' )

+ 71 - 0
3.31Gk航司/其他/verify.py

@@ -0,0 +1,71 @@
+import requests
+
+
+headers = {
+    "accept": "*/*",
+    "accept-language": "zh-CN,zh;q=0.9",
+    "cache-control": "no-cache",
+    "pragma": "no-cache",
+    "priority": "u=1, i",
+    "referer": "https://booking.jetstar.com/hk/zh/booking/select-flights",
+    "sec-ch-ua": "\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"",
+    "sec-ch-ua-mobile": "?0",
+    "sec-ch-ua-platform": "\"Windows\"",
+    "sec-fetch-dest": "empty",
+    "sec-fetch-mode": "cors",
+    "sec-fetch-site": "same-origin",
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
+}
+cookies = {
+    "$optimizelyEndUserId": "oeu1744595167365r0.8968549342456524",
+    "bid_JSaU2TcvPguuhpZfmwr34R7R8Wo7moKH": "fbcdc2e7-4124-47b7-bd23-b63061f4e537",
+    "AMCVS_8D0D1C8B532B54B40A490D4D%40AdobeOrg": "1",
+    "bx_bucket_number": "42",
+    "bx_guest_ref": "587456a6-5f66-49a4-80cf-d730c5c1a2ba",
+    "s_cc": "true",
+    "htjs_anonymous_id": "18b92168-bd03-4295-9296-1cf56b28cab6",
+    "_gcl_au": "1.1.259153084.1744595174",
+    "optimizelySession": "0",
+    "user-location": "country_code=AU,region_code=NSW,city=SYDNEY,lat=-33.88,long=151.22",
+    "AKA_A2": "A",
+    "bm_ss": "ab8e18ef4e",
+    "ab.storage.deviceId.8eb26f80-6f07-43d3-be0e-778c98485224": "g%3Aee8e7ee6-34ae-480d-2a66-99bd0dad803b%7Ce%3Aundefined%7Cc%3A1743408255712%7Cl%3A1744613552266",
+    "ak_bmsc": "0C44E7FAA04DABAF0E911B33938AFB91~000000000000000000000000000000~YAAQPJw+F3CAmAWWAQAAGDISMxvLvAESCoKHTt1O08nNiA/HnQ4AFKBRQ7NfQ5z0Q3uffqgevW6oQtndWSYM0L/P1aqtHc9dSvi9LI43CMebVI4bcNsxJ9ZECzg3K0DUcR4qO/34pAG0eMoLGr03Eg6DPqefuSwlyevi8qKbX9txtairrYtNRZnd+CESJf3RCC/OAz+ltYzB9U9U9cQ0r/n1mQJBq7pCGp/YpXxAiZftVkMR6oOydo+Vo/pED3rSp7n6SGf5m40cM0Hpoo5e6UPnKLvUJJS9NiZHV/Lu7NP4VNAaO8SrRHxvUe2VPMxs3dhhITF776iq5VFYgBT48QFfPyaw0wFsPXkfKnCZViyNzdSd+htF6TkcYZ0O80GjiBN2AgMrK/BX6jIfelQLgBTuFNOU5s1v/TgiC0gdUXqYnf/N8/kAzlhwXm2x8jMtAW8Yx+Ci1MhW7+8olRW2",
+    "AMCV_8D0D1C8B532B54B40A490D4D%40AdobeOrg": "179643557%7CMCIDTS%7C20193%7CMCMID%7C36684697300333487793028373615178378568%7CMCAAMLH-1745218358%7C8%7CMCAAMB-1745218358%7CRKhpRz8krg2tLO6pguXWp5olkAcUniQYPHaMWWgdJ3xzPWQmdj0y%7CMCOPTOUT-1744620758s%7CNONE%7CMCAID%7CNONE%7CvVersion%7C5.5.0",
+    "bxIDT": "",
+    "_fbp": "fb.1.1744613560083.2120932399812202",
+    "ASP.NET_SessionId": "f3dsc2stgnsfm35jm03erg1j",
+    "PlatformChannel": "REVTS1RPUA==",
+    "PlatformAppVersion": "",
+    "dotrez": "\\u0021moNy7WDrGPklsbbsNjR940Pn0OOujCv8dGPDL5PJDU70lLXZqJ1m4f4iRSglGB7jJCaANH7uqPY/PzU=",
+    "WorkFlow": "MA==",
+    "__RequestVerificationToken": "hvo_OXbN34o-NTEYGkBEeX0PJWTbdCXMhGIi-ch1wYib1fJZh1ujCrCCoEy2DUr_J5XL0xpsVAKew0bpcq2d7ZbdzuZa9fw0xL1-ILfq4Oo6Wb9OruX3Ky34UBFV5yi86N6B5A2",
+    "mcp-pre-selected-currency": "null",
+    "X-Session-Id": "f3dsc2stgnsfm35jm03erg1j",
+    "X-Session-Sig": "eb0dd2484b86005277b0571b451792e19391adb75db620b5c607a0c04c44c306",
+    "gpv_pn": "%2Fbooking%2Fselect-flights",
+    "gpv_mpl": "1",
+    "gpv_v1": "%2Fbooking-flow-ngbe",
+    "SEFD": "eyJPcmlnaW4iOiJQVkciLCJEZXN0aW5hdGlvbiI6IktNSSIsIlJvdW5kVHJpcCI6ZmFsc2UsIkRlcGFydHVyZURhdGUiOiIyMDI1LTA1LTE1VDAwOjAwOjAwIiwiUmV0dXJuRGF0ZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDAiLCJBZHVsdHMiOjEsIkNoaWxkcmVuIjowLCJJbmZhbnRzIjowfQ==",
+    "bm_s": "YAAQUpw+FxXUtguWAQAAuVY3MwOqdib805oHFgMgglmkEF+c8Qf0hhRH9RSyvPKRKv4tFF+ibmCM40T1Cu/AlLCGLX8GvRiIzoCM5ONwiF2suBymLV1QR0P2l0GIh0sSIQ0UXvaTidz7D2O0BWRyKZUJpnM3Ois7hVJW0tWDVvQTIkK8NrYgdMJr0SLV9U/sqXS7U1Jdqg3yLzip6OLDY1IplbMJofy16dwGIRuy5NYbwlMpkq2BTKW8RhjDxSGZHZThLnLkIRGX7SlpybXhDMwSkFf9+UHCKMA2C5tSOAoum82aMI/ae6rRMHH32QOib6GFjXLyEvXRkgAVfWWpATmzS/AnQQIDTqGYJ7tkIUQYzGibg73OG63IfwunTnfiq673iUEhEliH49WwbUDCSj1a4mipChaEujPG7sWhpr51Rj8a7uvgKXsRPWNNbxXGp4rmmrTHaUHozuZV",
+    "bm_so": "506C3F1F429C03D7A6F354D59077C3132920801FCF4C82226135EAE8C27168A8~YAAQUpw+FxbUtguWAQAAulY3MwNxdhuBBkxMC+wofVTMg0gto9A0DdMNCIFq0NSf16LSlnwuHY8+G4MGBLfiBP4U9ros5JWYEa1LM4Bv9D1rxVxY3ni9IP30+YAs4KIbEVq/I1Ki4gbUo8afEMlWcVs0ii3zmDOMmfiyMq54k0Lvb6aoj1GgMh8D97lgtjDAjf5vY69yDjRHlhk40lIco6OWcNngh6vCr4AfSTf2iGaG38I+mpNrnCYPFUrhwpjqyp+4+75I8Rl7/9ntMKcRivyH/aO5xR1lrSUgBP9GB0l8+fvd9fZBu/ZjI7HFAb9rzLrfWQTMts+QepkR8yscHWshCKATuVkjEIe2JULM53kRQ9r8m77kqwuT03XS/8rgTUl9DSbu18kfqQtn+4loxxGBGZAUgNOvqR86SfXN/9VFQUDq7/3WR0gQ+5bNveVsMFD4dM4FMTvxsu7RlufcWQ==",
+    "MT": "1744615989411",
+    "ab.storage.sessionId.8eb26f80-6f07-43d3-be0e-778c98485224": "g%3A4c55aa01-21bc-c3c3-fbc4-252c2e5e71e8%7Ce%3A1744617790072%7Cc%3A1744613552264%7Cl%3A1744615990072",
+    "s_nbs": "1744615991",
+    "htjs_sesh": "{%22id%22:1744613626301%2C%22expiresAt%22:1744617792678%2C%22timeout%22:1800000%2C%22sessionStart%22:false%2C%22autoTrack%22:true}",
+    "bm_lso": "506C3F1F429C03D7A6F354D59077C3132920801FCF4C82226135EAE8C27168A8~YAAQUpw+FxbUtguWAQAAulY3MwNxdhuBBkxMC+wofVTMg0gto9A0DdMNCIFq0NSf16LSlnwuHY8+G4MGBLfiBP4U9ros5JWYEa1LM4Bv9D1rxVxY3ni9IP30+YAs4KIbEVq/I1Ki4gbUo8afEMlWcVs0ii3zmDOMmfiyMq54k0Lvb6aoj1GgMh8D97lgtjDAjf5vY69yDjRHlhk40lIco6OWcNngh6vCr4AfSTf2iGaG38I+mpNrnCYPFUrhwpjqyp+4+75I8Rl7/9ntMKcRivyH/aO5xR1lrSUgBP9GB0l8+fvd9fZBu/ZjI7HFAb9rzLrfWQTMts+QepkR8yscHWshCKATuVkjEIe2JULM53kRQ9r8m77kqwuT03XS/8rgTUl9DSbu18kfqQtn+4loxxGBGZAUgNOvqR86SfXN/9VFQUDq7/3WR0gQ+5bNveVsMFD4dM4FMTvxsu7RlufcWQ==^1744615996823",
+    "s_getNewRepeat": "1744616779146-Repeat",
+    "flightIndex": "0",
+    "bm_sv": "7207D8F841AF8E9BDA9D23034FADD6F8~YAAQJpw+FzzQIgSWAQAAk25DMxta9j5xv3jdwoJxDOITY+Wflqq2eFKYyqtfAuHvdw9eQ8UII/cXnBWOlcvbBye+bEarlRmHMLqVDFbOGOSlRA2j3PlmDst9mb10FDbpOPRyhUdTMl0v1vpGO+TwWds2JACGZMtiINRiE3kvVNR6x7zp3Q2n9Ac0MGlTMlIC8XpuMHLAWc/xghpX/vnGYtcAzfTQN7r0th8jd6HPzE+RrHZoPuMdv6gTUaVzEVC71Po=~1",
+    "_dd_s": "rum=1&id=c9cc81e9-3a29-4228-b957-dee6664e16d9&created=1744613551560&expire=1744617679229",
+    "bm_sz": "5EC9B527A352F347DA0063D7B71B3D08~YAAQLpw+F7XoYQuWAQAAX4FDMxvMs0Itx40egwDMd0XvSr1l/MsRFCtrIdzETkM0qc4aWXx9AbRnyrkPl+KlHR8MpwPfgBsEaplHDj3p3Mfzbnx8UvTfhRC/cnEOSEq3lEbspvqO6TpQqKYW3u41kCNBTPivAVDe9sx3MyRUfE7/k4PJOJSWVX+LNvXcis2aW4LzfACzo1LQDt4prs6TUfBCel37yo2T3g8Ek0uiRf/QoPGDzt2UNtGEvtxDgFZCdJErrkGzRj/P+LDm14JXqAXJXc0h720RvlO184xFlqSMJf9a/qLXZMwqJqzAUVbKjE65m7MInl/P4vSkC4FA+KbR9FBBgh+gVE/ivYpINz4jLZf7OcnWYPaGAEmqYSD5B/Q6pYUkETZOH7sJapqbxjN4ZHulFk7LlOmPNoIr7xRK8bzUe7R8Z9HDgv8mgWzsnhAcAY+Rf5XsewcTKXEa1fiXFVr5PaiZQPCyY+w3CbY/HHdpQwMlWlpNwMB9vCq0Vsj9w2kwbcQ0+TfkZ7XaHKuXwRErpscmjHavkhfu~4470852~4337713",
+    "RT": "\"z=1&dm=jetstar.com&si=e684950f-3a6d-4647-9fe3-27df785970eb&ss=m9gpv0pf&sl=g&tt=50nd&bcn=%2F%2F684d0d4c.akstat.io%2F&ld=1xeu2\"",
+    "_abck": "38D48222CFE7D244DC0476D5FD72BF23~0~YAAQLpw+F23qYQuWAQAA+5hDMw014xnfg6TDltur/ldhtpsCZO8HLjOH1lmPD7NSFPzqNwjZbyx0AQRMWWtSXV5letmclPNoGkrgxewo6RNE1/z1XBoT1FMxLAEDmIZdsnBy0ChHbwz2evSDSQmSMA/CvsKRAs13H7Yu35Al4Ks5nnXHWe27hXR4pDrcz4jveKfuPADWfTp4jNuQVzqexiXfB9u7iIrw1jt5uHH6PB8u9278aOu2DFq8CJts0lqjxyWRO4x1EGPu877yx+w1skLVE7CqVwzRIZnLQLJxI1ZOGOOnPX1GJOBr33oySZ342bh9jorYYLzNNo6FYPFKyomEel4LNerooclb747iEX4Li4LQLRadGkosssWXL6bdAkGOFdI4WYOjvHnRNWZcgjghJa5OfMq7/9BOIVqr8CSHFS7yWd6QEllSy84AuopZfELQtxETO+Ko1I3FKABC3CPPzgBMXLdGGxdKQU2QLIYPHuYJ47SpVeMcaA7/DN0EjLGe+PVQjw/LGSAlygUKdGmbyZR5DmnCqfHaE9nMik5JWTC1EGA+MJk7Zg+L0KFTqY4X2dKr+XpP+DjbI5pbUfGTR2YZYqFiQ4v5wVRefDxHqWzDPhQnvaj3+4ubiRVTDQsOjgoW2T1maLu76nhf/KAFjIVLc//82FB/8YhUItBw9n+8RNdNVhjVYszdeXf3B9gWMxNvwKdJBkPsCVsybpB9ZPfmlunsX9DEQ7eiwlSeWglC0y8NkvOMx8ACaWVY20yywYRdddVvz94ZEtQUodcll/Tp6mEIreSLfnyTKz6d0gOYDlycGj0Js1yYxJ2gOwfKGivyDB99qHSmjNsHVAE/+zhHQeWbUYufaQIKWTd0ptsN/gwKXq+BoGVB5PuXJJ9QGF8wUql1Cx+Aw+0EDyZpzxBylqGSbArqZhqI93KHiWKNRPFSl6F0vv+QjCrOob3u~-1~||0||~-1",
+    "sec_cpt": "A4CCF25250832ED2213B78C549F3367C~2~YAAQLpw+F27qYQuWAQAA+5hDMwwkgbOzQnx9/8SYdI7oPat24X5uht70NNJjmGxruTzynKkerbIJA8uQynenJ/P2ZVbNJTp91nNd8LCi1c6j59Swmi5p3U8QYs/6K7CekfqIDtBraWn6OT9dnD9dQ0+ng0ol2QK4k4kNIQ4ipVcHKf1fkbKaPlgNpPzRofS/33PKfQIOr8rt9DBfK+ohnkdC9SNaJtQJjN6/F/h318TCBxc3BeMxazFWYO0+zdcHfMaKaQZ0nXem5hj984NcAWgG4aEe+s+97VaIbCsnABrFxFtI71cXXfWfQNPGIAzGVGYHdvHnyVnqIhFwI8XZCo/+0AljqwIvWRwLkEZ31W9nnMozQswpe7EHjmDWCbbUg0fKzuz2l6iEtoCLsmjsE4b5YALcDlA3jV2VEUGKlZ0r5U2Lqqets2ZT6jSSBmBE4eeXNTxGlI5Hlzod7hzynq7xu9yY90aJ75UyidTiQ30EXCo8xk3RU5zfLAvMbmdGeGMGjIT4cFj/5M2DaUonlinlZxYIprz/YW7hDxXlAKEdMPziapqKjhtMEg7KPowknHcyaGvR7BVrKmZPMT9zwm4WWBN9xCBpQC5MjaQYRYTBOfK02lsxvya5JJfPYoxrqvgOnSk7mJNxLrSFvbovyqMKL8HeBZILYfsV3oUzenkto0ymGJdMbtlYRWuRQdN/rUkd5Yc4E7OOqYs8GaRdVHjTyZmIzkTgKuyX8SG9IOkiC2C6sjennQRFa2bjfZaH0LzbCB36cgXGM9+7ealO2ivpd/FKy7MF4qK1zazPU4/uRPG4jRRgFOpHIy2bH0wkq1jE4onpQqMkXCVCSsTuHf9CqX0mKKKJucQEq5IhAESmGK+vkGvJf1Q3NRuLyJvPdRX66ncAgri60TinzwQHDZRnaGBlbBl+bKywUpW5cXCK4rJ7oRwuyA8/6MI3ZA=="
+}
+url = "https://booking.jetstar.com/_sec/cp_challenge/verify"
+response = requests.get(url, headers=headers, cookies=cookies)
+
+print(response.text)
+print(response.cookies.get_dict())
+print(response)

+ 94 - 0
3.31Gk航司/其他/分析.txt

@@ -0,0 +1,94 @@
+
+可能是
+ 0.请求 https://www.jetstar.com/IN8wyRJtH_OQqV-jNF2LfziXtCg/DJE5SpEuNO1J/BD9HAQ/KksEJgAX/I3M
+    携带cookie
+        _dd_s=  空值
+    获取cookie
+        ak_bmsc
+        user-location
+ 1.先请求主页https://www.jetstar.com/hk/zh/home?tab=1,
+   携带cookie
+        _dd_s
+        ak_bmsc
+        ak_bmsc
+   获取cookie
+        AKA_A2
+        _abck
+        bm_mi
+        bm_s
+        bm_so
+        bm_ss
+        bm_sv
+        bm_sz
+
+ 2.再请求https://auth.jetstar.com/authorize这个接口验证 获取cookies bm_sv值
+
+
+
+ 请求航班信息中的这几个 cookie 是变化的
+    SEFD
+    bm_s
+    bm_so
+    bm_sz
+    bm_lso
+    MT
+    ab.storage.sessionId.8eb26f80-6f07-43d3-be0e-778c98485224
+    optimizelySession
+    bm_sv
+    s_nbs
+    htjs_sesh
+    _abck
+    RT
+    _dd_s
+    s_getNewRepeat
+
+
+
+
+
+
+澳大利亚的网站,代理用 AU
+
+
+cookie
+    备注: 要带  有时效性, 不带也可以请求,但是没有价格等数据
+    主要带以下 3 个值
+        SEFD: 不带它会触发验证码
+            来源: 请求成功后,响应cookie会返回这个值; 第一次生成位置待确定 ?
+            注意: 每次请求该值都会变化, 测试在同一个代码中, SEFD不变的情况下,最多请求4次, 第5次请求时,会触发验证码, 更换它就没事了)
+
+        ASP.NET_SessionId:
+            这个必须带,有时候不带也可以请求 待观察 (同一个会话中 ASP.NET_SessionId 是不变的 待验证!!)
+
+        bm_sz:
+            有时候只带这 1 个也可以请求
+            只带 SEFD 和 ASP.NET_SessionId 这2个,请求会报错, 测试了再带个 bm_sz 就可以正常请求
+            这个值不对, 也会触发验证码
+            来源: 有2个
+                1.请求主页来的
+                    请求主页响应的 https://www.jetstar.com/hk/zh/home, 请求接口后也会响应一个新的这个值
+                    请求主页响应的cookie值, 要再请求1次阿卡麦文件,, 响应 abck 为 -1 可以用
+
+                2.从网页akm接口获取
+                    Akamai文件分析
+                        第一次请求
+                            携带cookie: MT _dd_s  ak_bmsc
+                            返回响应{"success": false}
+                            响应cookie:_abck  bm_sz
+                            用这个响应cookie bm_sz 直接请求是不会请求成功的
+                        第二次请求
+                             响应cookie abck为 -1 也可以使用
+
+
+
+
+新ip请求 要过验证码  !!! 可能是加密参数没带全 或 没带对 所以出现验证码
+    验证api https://booking.jetstar.com/_sec/cp_challenge/verify
+     响应 cookie sec_cpt  应该是用这个cookie作为验证值, 验证时会请求几次 /0dVo  (阿卡麦验证接口),如果响应 abck 为 0的话 直接携带请求验证api接口
+     sec_cpt 里面也有关于它的状态值  注意观察!!
+
+
+
+
+响应数据在 html的   <script type="application/json" id="bundle-data-v2"  文件中
+

+ 717 - 0
3.31Gk航司/其他/响应数据分析.py

@@ -0,0 +1,717 @@
+var = {
+    "Trips": [
+        {
+            "TripIndex": 0,
+            "Flights": [
+                {
+                    "IsCjFare": false,
+                    "JourneySellKey": "GK~  36~ ~~PVG~04/21/2025 02:15~NRT~04/21/2025 06:20~~^GK~ 631~ ~~NRT~04/21/2025 12:40~KMI~04/21/2025 14:45~~",
+                    "HighlightProductClass": null,
+                    "Lob": "GKINT",
+                    "JourneyStations": "PVG-NRT-KMI",
+                    "SelectedServiceBundleCode": null,
+                    "SelectedProductClass": null,
+                    "Bundles": [
+                        {
+                            "ProductClass": null,
+                            "ServiceBundleCode": "S000",
+                            "ServiceBundleCodeType": 0,
+                            "Amount": 0,
+                            "CjAmount": 0,
+                            "RegularInclusiveAmount": "1219.56",
+                            "CjInclusiveAmount": 0,
+                            "FlightFareKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~",
+                            "CjFlightFareKey": null,
+                            "SavingPercent": 0,
+                            "IsSaleFare": false,
+                            "HasCjFareBundle": false,
+                            "IsBusinessClassBundle": false,
+                            "BundleLabel": "基本票",
+                            "BundleName": "基本票",
+                            "BundleSubHeader": "我們的基本票價",
+                            "BundleSsrCode": "STRT",
+                            "IsStarterBundle": true,
+                            "BundleProductName": "",
+                            "BundleColorVariant": "bundle-100"
+                        },
+                        {
+                            "ProductClass": null,
+                            "ServiceBundleCode": "P200",
+                            "ServiceBundleCodeType": 0,
+                            "Amount": 413.27,
+                            "CjAmount": 0,
+                            "RegularInclusiveAmount": "1632.83",
+                            "CjInclusiveAmount": 0,
+                            "FlightFareKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~",
+                            "CjFlightFareKey": null,
+                            "SavingPercent": 0,
+                            "IsSaleFare": false,
+                            "HasCjFareBundle": false,
+                            "IsBusinessClassBundle": false,
+                            "BundleLabel": "基本加值套票",
+                            "BundleName": "基本加值套票",
+                            "BundleSubHeader": "行李 + 座位 + 餐膳",
+                            "BundleSsrCode": "STPL",
+                            "IsStarterBundle": false,
+                            "BundleProductName": "基本加值套票",
+                            "BundleColorVariant": "bundle-200"
+                        },
+                        {
+                            "ProductClass": null,
+                            "ServiceBundleCode": "F200",
+                            "ServiceBundleCodeType": 0,
+                            "Amount": 452.65,
+                            "CjAmount": 0,
+                            "RegularInclusiveAmount": "1672.21",
+                            "CjInclusiveAmount": 0,
+                            "FlightFareKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~",
+                            "CjFlightFareKey": null,
+                            "SavingPercent": 0,
+                            "IsSaleFare": false,
+                            "HasCjFareBundle": false,
+                            "IsBusinessClassBundle": false,
+                            "BundleLabel": "Flex",
+                            "BundleName": "Flex",
+                            "BundleSubHeader": "積分與彈性",
+                            "BundleSsrCode": "FLXN",
+                            "IsStarterBundle": false,
+                            "BundleProductName": "Flex 套票",
+                            "BundleColorVariant": "bundle-300"
+                        },
+                        {
+                            "ProductClass": null,
+                            "ServiceBundleCode": "M200",
+                            "ServiceBundleCodeType": 0,
+                            "Amount": 599.3,
+                            "CjAmount": 0,
+                            "RegularInclusiveAmount": "1818.86",
+                            "CjInclusiveAmount": 0,
+                            "FlightFareKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~",
+                            "CjFlightFareKey": null,
+                            "SavingPercent": 0,
+                            "IsSaleFare": false,
+                            "HasCjFareBundle": false,
+                            "IsBusinessClassBundle": false,
+                            "BundleLabel": "彈性加值",
+                            "BundleName": "彈性加值",
+                            "BundleSubHeader": "新增彈性 + 附加項目",
+                            "BundleSsrCode": "FPLS",
+                            "IsStarterBundle": false,
+                            "BundleProductName": "彈性加值套票",
+                            "BundleColorVariant": "bundle-400"
+                        }
+                    ],
+                    "OriginalBundleSsrCode": "",
+                    "EconomyPreSelectedBundleCode": null,
+                    "MobileEcoPreSelectedBundleCode": "S000",
+                    "MobileBizPreSelectedBundleCode": null,
+                    "BusinessPreSelectedBundleCode": null,
+                    "DisplayBundle": "STPL",
+                    "MerchandiseMessagesInfo": [
+                        {
+                            "Message": "超值優惠",
+                            "Bundle": "FPLS",
+                            "Position": "top"
+                        },
+                        {
+                            "Message": "節省附加項目費用!^",
+                            "Bundle": "FPLS",
+                            "Position": "bottom"
+                        }
+                    ],
+                    "DisplayFlightInfo": {
+                        "Legs": [
+                            {
+                                "Color": "flight-one",
+                                "HasToolTip": false,
+                                "IsConnectingFlight": false,
+                                "IsInternational": true,
+                                "IsDepartingFromInternationalTerminal": false,
+                                "DepartureStation": "PVG",
+                                "ArrivalStation": "NRT",
+                                "DisplayStd": "2025年4月21日 (週一) 上午2:15",
+                                "DisplaySta": "2025年4月21日 (週一) 上午6:20",
+                                "Equipment": {
+                                    "Type": "32J",
+                                    "IsAircraftType": true
+                                },
+                                "FlightDesignator": {
+                                    "FlightNumber": "  36",
+                                    "CarrierCode": "GK",
+                                    "OpSuffix": " "
+                                },
+                                "DisplayDepartureAirportTerminal": "上海 (浦東) - 2號航站樓",
+                                "DisplayArrivalAirportTerminal": "東京 (成田) - 3號航站樓",
+                                "IsAircraftBusinessCabin": false,
+                                "DisplayTravelDuration": "3小時 5分鐘",
+                                "DisplayAircraft": "空中巴士 A320-200",
+                                "OperatorName": "NGBE.Global.Carrier.GK",
+                                "IsSubjectToGovtApproval": false,
+                                "TransitAirport": "東京 (成田)",
+                                "TransitDuration": "6小時 20分鐘",
+                                "CabinType": "Y",
+                                "Lob": "GKINT"
+                            },
+                            {
+                                "Color": "flight-one",
+                                "HasToolTip": false,
+                                "IsConnectingFlight": false,
+                                "IsInternational": false,
+                                "IsDepartingFromInternationalTerminal": false,
+                                "DepartureStation": "NRT",
+                                "ArrivalStation": "KMI",
+                                "DisplayStd": "2025年4月21日 (週一) 下午12:40",
+                                "DisplaySta": "2025年4月21日 (週一) 下午2:45",
+                                "Equipment": {
+                                    "Type": "32J",
+                                    "IsAircraftType": true
+                                },
+                                "FlightDesignator": {
+                                    "FlightNumber": " 631",
+                                    "CarrierCode": "GK",
+                                    "OpSuffix": " "
+                                },
+                                "DisplayDepartureAirportTerminal": "東京 (成田) - 3號航站樓",
+                                "DisplayArrivalAirportTerminal": "宮崎",
+                                "IsAircraftBusinessCabin": false,
+                                "DisplayTravelDuration": "2小時 5分鐘",
+                                "DisplayAircraft": "空中巴士 A320-200",
+                                "OperatorName": "NGBE.Global.Carrier.GK",
+                                "IsSubjectToGovtApproval": false,
+                                "TransitAirport": null,
+                                "TransitDuration": null,
+                                "CabinType": "Y",
+                                "Lob": "GKDOM"
+                            }
+                        ],
+                        "BusinessFlightInfo": {
+                            "IsPreselected": false,
+                            "IsSpecialFare": false,
+                            "IsLowOnSeats": false,
+                            "HasAlert": false,
+                            "TicketsAvailability": "NotAvailable",
+                            "RemainingSeats": 0,
+                            "ShouldShowSeatCountdownLabel": false,
+                            "IsFlexSameDayChange": false
+                        },
+                        "EconomyFlightInfo": {
+                            "IsPreselected": false,
+                            "IsSpecialFare": true,
+                            "IsLowOnSeats": true,
+                            "HasAlert": false,
+                            "TicketsAvailability": "Available",
+                            "RemainingSeats": 4,
+                            "ShouldShowSeatCountdownLabel": true,
+                            "IsFlexSameDayChange": false
+                        },
+                        "FareAlertInfo": {
+                            "IsVtlFlight": false,
+                            "IsDomesticFlightDepartFromInternationalTerminal": false,
+                            "IsAnyLegsSubjectToGovtApproval": false,
+                            "IsNotEnoughInfantsSSR": false,
+                            "IsNoWheelChairAvailable": false,
+                            "IsInValidPassengerCountForQf": false,
+                            "IsRoundTrip": false,
+                            "IsNotAllAircraftWithBusinessCabin": true,
+                            "IsEconomyFlightDiscounted": false,
+                            "IsBusinessFlightDiscounted": false,
+                            "ShouldShowWaiveFlightChangeFeeTip": false,
+                            "IsMultiAirportCity": false,
+                            "TransitCustomMessageType": null
+                        },
+                        "OriginAirport": "上海 (浦東)",
+                        "DestinationAirport": "宮崎",
+                        "StandardTimeOfDeparture": "2025-04-21T02:15:00",
+                        "StandardTimeOfArrival": "2025-04-21T14:45:00",
+                        "TravelTime": "11:30:00",
+                        "RouteName": "上海 (浦東) 至 宮崎"
+                    },
+                    "EconomyPriceBreakdown": "{\r\n  \"JourneyType\": \"OutBound\",\r\n  \"TotalAmountDue\": 1219.5600000000000,\r\n  \"TotalFare\": 1110.6600000000000,\r\n  \"TotalCharges\": 108.9000000000000,\r\n  \"TotalPaxCount\": 1.0,\r\n  \"TotalBusinessMaxFare\": 0.0,\r\n  \"BusinessMaxFare\": 0.0,\r\n  \"PriceBreakdown\": [\r\n    {\r\n      \"PaxType\": \"ADT\",\r\n      \"PaxTypeCount\": 1,\r\n      \"PerPaxAmount\": 1110.6600000000000,\r\n      \"Label\": \"成人\",\r\n      \"Fees\": [\r\n        {\r\n          \"ChargeCode\": \"HJ\",\r\n          \"PerPaxAmount\": 18.9000000000000,\r\n          \"Label\": \"成人 - 乘客安檢費\",\r\n          \"PaxTypeCount\": 1\r\n        },\r\n        {\r\n          \"ChargeCode\": \"CN\",\r\n          \"PerPaxAmount\": 90.00,\r\n          \"Label\": \"成人 - 機場服務費\",\r\n          \"PaxTypeCount\": 1\r\n        }\r\n      ]\r\n    }\r\n  ]\r\n}",
+                    "BusinessPriceBreakdown": null,
+                    "EconomyMemberPriceBreakdown": null,
+                    "BusinessMemberPriceBreakdown": null,
+                    "IsEconomyFarePreselected": false,
+                    "IsBusinessFarePreselected": false,
+                    "EconomyClassSalePillInfo": {
+                        "IsShow": false,
+                        "Variant": null,
+                        "PromoText": null,
+                        "Source": null
+                    },
+                    "BusinessClassSalePillInfo": {
+                        "IsShow": false,
+                        "Variant": null,
+                        "PromoText": null,
+                        "Source": null
+                    },
+                    "FareClassOfServices": [
+                        "E1",
+                        "EP1",
+                        "EB1",
+                        "EY1"
+                    ]
+                }
+            ],
+            "Lobs": [
+                {
+                    "Lob": "GKINT",
+                    "JourneyStations": "PVG-NRT-KMI",
+                    "Bundles": [
+                        {
+                            "BundleLabel": "基本票",
+                            "ProductClass": null,
+                            "BundleCode": "S000",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "基本加值套票",
+                            "ProductClass": null,
+                            "BundleCode": "P200",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "Flex",
+                            "ProductClass": null,
+                            "BundleCode": "F200",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "彈性加值",
+                            "ProductClass": null,
+                            "BundleCode": "M200",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "Flex",
+                            "ProductClass": null,
+                            "BundleCode": "F000",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "加值",
+                            "ProductClass": null,
+                            "BundleCode": "P000",
+                            "Inclusions": null
+                        },
+                        {
+                            "BundleLabel": "頂級",
+                            "ProductClass": null,
+                            "BundleCode": "M000",
+                            "Inclusions": null
+                        }
+                    ],
+                    "Disclaimers": {
+                        "CombinedBundleTC": "NGBE.FlightSelect.Bundles.FareRules.Disclaimer",
+                        "BusinessClassCombinedBundleTC": "NGBE.Bundles.BusinessClassLegalDisclaimer",
+                        "QFFPointsTC": "NGBE.Bundles.BundleRules.Qantas",
+                        "EKPointsTC": "NGBE.Bundles.BundleRules.Emirates",
+                        "JALPointsTC": "NGBE.Bundles.BundleRules.JAL",
+                        "SavingBundleTC": "NGBE.FlightSelect.BundlesMobile.InclusionsExplained.BundleSavingsDisclaimer"
+                    }
+                }
+            ],
+            "IsServiceBundle": true,
+            "CityPair": "PVGKMI",
+            "SelectedFareKey": null,
+            "IsReturningTrip": false
+        }
+    ],
+    "BookingInfo": null,
+    "DynamicBundleOnFlight": {
+        "BundlesInFlights": [
+            {
+                "JourneySellKey": "GK~  36~ ~~PVG~04/21/2025 02:15~NRT~04/21/2025 06:20~~^GK~ 631~ ~~NRT~04/21/2025 12:40~KMI~04/21/2025 14:45~~",
+                "Bundles": [
+                    {
+                        "Id": {
+                            "ServiceBundleCode": "F200",
+                            "BundleSsrCode": "FLXN",
+                            "FareSellKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~"
+                        },
+                        "InclusionRefIds": [
+                            "PgmDQDA29lNhh1x6eWEP+w==",
+                            "WAljjBUGWn1F/4Aux51Nmw==",
+                            "hUqf5jNQtcK/cAonxhTSJg==",
+                            "NINy80MZbJIY9F/X7EAatA==",
+                            "paelhZ9HXNaMCj/1OcPGBw==",
+                            "zEV7981MJBEmNT22hu1jkA==",
+                            "Iq3TUCj8Mj8YSjJCVTaqWw==",
+                            "/0QKU8uPz3OjR17NBllGWQ==",
+                            "fiiEljeP/MrsA9ZoTTibTg==",
+                            "CaqcKnF27ciyIsRVivcm5A=="
+                        ],
+                        "IsMemberFare": false,
+                        "CabinType": "Economy",
+                        "Title": "Flex",
+                        "SubTitle": "積分與彈性",
+                        "JclColorVariant": "bundle-300"
+                    },
+                    {
+                        "Id": {
+                            "ServiceBundleCode": "M200",
+                            "BundleSsrCode": "FPLS",
+                            "FareSellKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~"
+                        },
+                        "InclusionRefIds": [
+                            "PgmDQDA29lNhh1x6eWEP+w==",
+                            "m/I9bLk4RlkrSeWhHf9HiQ==",
+                            "qJ/pbMNV8DS5A2IOHNaXkg==",
+                            "hcU/sG5cwAw7wXHHktvRlg==",
+                            "paelhZ9HXNaMCj/1OcPGBw==",
+                            "zEV7981MJBEmNT22hu1jkA==",
+                            "Iq3TUCj8Mj8YSjJCVTaqWw==",
+                            "4hM7b5KEA7sSPm3cj+dbIw==",
+                            "Eb+ydtDs/t1mHDDfn2dv3Q==",
+                            "CaqcKnF27ciyIsRVivcm5A=="
+                        ],
+                        "IsMemberFare": false,
+                        "CabinType": "Economy",
+                        "Title": "彈性加值",
+                        "SubTitle": "新增彈性 + 附加項目",
+                        "JclColorVariant": "bundle-400"
+                    },
+                    {
+                        "Id": {
+                            "ServiceBundleCode": "P200",
+                            "BundleSsrCode": "STPL",
+                            "FareSellKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~"
+                        },
+                        "InclusionRefIds": [
+                            "PgmDQDA29lNhh1x6eWEP+w==",
+                            "m/I9bLk4RlkrSeWhHf9HiQ==",
+                            "p2ZbfTFp93on6OZEmvSM+A==",
+                            "hcU/sG5cwAw7wXHHktvRlg==",
+                            "HxyP2sgcEoNPJG/Pew60bQ==",
+                            "T9DWQCiTqlVfNkxThie8Vw==",
+                            "Gf5F7nNl9bVlMhfu+mYTaA==",
+                            "/0QKU8uPz3OjR17NBllGWQ==",
+                            "skjgAOyXx+yXe71m2AFbrg==",
+                            "CaqcKnF27ciyIsRVivcm5A=="
+                        ],
+                        "IsMemberFare": false,
+                        "CabinType": "Economy",
+                        "Title": "基本加值套票",
+                        "SubTitle": "行李 + 座位 + 餐膳",
+                        "JclColorVariant": "bundle-200"
+                    },
+                    {
+                        "Id": {
+                            "ServiceBundleCode": "S000",
+                            "BundleSsrCode": "STRT",
+                            "FareSellKey": "2~E1~~JQ~ELECOE1~7200~~0~1~~X^1~H~~JQ~HLECOH~7000~~0~6~~"
+                        },
+                        "InclusionRefIds": [
+                            "PgmDQDA29lNhh1x6eWEP+w==",
+                            "WAljjBUGWn1F/4Aux51Nmw==",
+                            "hfmW7rDTv6BA5r35PZqXeQ==",
+                            "NINy80MZbJIY9F/X7EAatA==",
+                            "HxyP2sgcEoNPJG/Pew60bQ==",
+                            "T9DWQCiTqlVfNkxThie8Vw==",
+                            "Gf5F7nNl9bVlMhfu+mYTaA==",
+                            "/0QKU8uPz3OjR17NBllGWQ==",
+                            "yKllSRBGWvGXMjRuYK87Bw==",
+                            "CaqcKnF27ciyIsRVivcm5A=="
+                        ],
+                        "IsMemberFare": false,
+                        "CabinType": "Economy",
+                        "Title": "基本票",
+                        "SubTitle": "我們的基本票價",
+                        "JclColorVariant": "bundle-100"
+                    }
+                ],
+                "Disclaimers": {
+                    "QFFPointsTC": "NGBE.Bundles.BundleRules.Qantas",
+                    "EKPointsTC": "NGBE.Bundles.BundleRules.Emirates",
+                    "JALPointsTC": "NGBE.Bundles.BundleRules.JAL",
+                    "SavingBundleTC": "NGBE.FlightSelect.BundlesMobile.InclusionsExplained.BundleSavingsDisclaimer"
+                },
+                "MerchandiseMessagesInfo": [
+                    {
+                        "Message": "超值優惠",
+                        "Bundle": "FPLS",
+                        "Position": "top"
+                    },
+                    {
+                        "Message": "節省附加項目費用!^",
+                        "Bundle": "FPLS",
+                        "Position": "bottom"
+                    }
+                ],
+                "BundleInFocusSsrCode": "STPL",
+                "BundlePreselections": [
+                    {
+                        "PreselectedBundleSsrCode": "STRT",
+                        "CabinType": "Economy",
+                        "DeviceType": "mobile"
+                    }
+                ]
+            }
+        ],
+        "Inclusions": [
+            {
+                "ProductName": "CarryOnBaggage",
+                "IsIncluded": true,
+                "DisplayText": "7 公斤",
+                "Title": "手提行李",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 1,
+                "CabinType": "Economy",
+                "RefId": "PgmDQDA29lNhh1x6eWEP+w==",
+                "IconVariant": "economy-carry-on-baggage"
+            },
+            {
+                "ProductName": "CheckedBaggage",
+                "IsIncluded": false,
+                "DisplayText": "稍後添加",
+                "Title": "託運行李",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 2,
+                "CabinType": "Economy",
+                "RefId": "WAljjBUGWn1F/4Aux51Nmw==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "Seat",
+                "IsIncluded": true,
+                "DisplayText": "前艙或標準",
+                "Title": "選位",
+                "SubTitle": null,
+                "SsrCode": "FXS2",
+                "SortOrder": 3,
+                "CabinType": "Economy",
+                "RefId": "hUqf5jNQtcK/cAonxhTSJg==",
+                "IconVariant": "economy-seat"
+            },
+            {
+                "ProductName": "Meals",
+                "IsIncluded": false,
+                "DisplayText": "稍後添加",
+                "Title": "機上餐飲",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 4,
+                "CabinType": "Economy",
+                "RefId": "NINy80MZbJIY9F/X7EAatA==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "DateTimeChange",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "日期和時間更改*",
+                "SubTitle": "我們或會收取票價差額",
+                "SsrCode": "DCHG",
+                "SortOrder": 5,
+                "CabinType": "Economy",
+                "RefId": "paelhZ9HXNaMCj/1OcPGBw==",
+                "IconVariant": "economy-date-time-change"
+            },
+            {
+                "ProductName": "SameDayChange",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "免費即日更改*",
+                "SubTitle": null,
+                "SsrCode": "SDCH",
+                "SortOrder": 6,
+                "CabinType": "Economy",
+                "RefId": "zEV7981MJBEmNT22hu1jkA==",
+                "IconVariant": "same-day-change"
+            },
+            {
+                "ProductName": "CancelFlight",
+                "IsIncluded": true,
+                "DisplayText": "消費額現金券",
+                "Title": "取消你的航班*",
+                "SubTitle": null,
+                "SsrCode": "CVHR",
+                "SortOrder": 7,
+                "CabinType": "Economy",
+                "RefId": "Iq3TUCj8Mj8YSjJCVTaqWw==",
+                "IconVariant": "economy-cancel-flight"
+            },
+            {
+                "ProductName": "OriginDestinationChange",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "出發地/目的地更改*",
+                "SubTitle": "我們或會收取票價差額",
+                "SsrCode": null,
+                "SortOrder": 8,
+                "CabinType": "Economy",
+                "RefId": "/0QKU8uPz3OjR17NBllGWQ==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "FrequentFlyer",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "忠誠獎勵",
+                "SubTitle": null,
+                "SsrCode": "LOYT",
+                "SortOrder": 9,
+                "CabinType": "Economy",
+                "RefId": "fiiEljeP/MrsA9ZoTTibTg==",
+                "IconVariant": "economy-loyalty-points"
+            },
+            {
+                "ProductName": "QantasBusinessReward",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "澳航商務獎勵",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 10,
+                "CabinType": "Economy",
+                "RefId": "CaqcKnF27ciyIsRVivcm5A==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "CheckedBaggage",
+                "IsIncluded": true,
+                "DisplayText": "20 公斤",
+                "Title": "託運行李",
+                "SubTitle": null,
+                "SsrCode": "BG20",
+                "SortOrder": 2,
+                "CabinType": "Economy",
+                "RefId": "m/I9bLk4RlkrSeWhHf9HiQ==",
+                "IconVariant": "economy-checked-baggage"
+            },
+            {
+                "ProductName": "Seat",
+                "IsIncluded": true,
+                "DisplayText": "任何適用座位",
+                "Title": "選位",
+                "SubTitle": null,
+                "SsrCode": "FXS3",
+                "SortOrder": 3,
+                "CabinType": "Economy",
+                "RefId": "qJ/pbMNV8DS5A2IOHNaXkg==",
+                "IconVariant": "economy-seat"
+            },
+            {
+                "ProductName": "Meals",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "機上餐飲",
+                "SubTitle": null,
+                "SsrCode": "ML01",
+                "SortOrder": 4,
+                "CabinType": "Economy",
+                "RefId": "hcU/sG5cwAw7wXHHktvRlg==",
+                "IconVariant": "economy-meals"
+            },
+            {
+                "ProductName": "OriginDestinationChange",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "出發地/目的地更改*",
+                "SubTitle": "我們或會收取票價差額",
+                "SsrCode": "OCHG",
+                "SortOrder": 8,
+                "CabinType": "Economy",
+                "RefId": "4hM7b5KEA7sSPm3cj+dbIw==",
+                "IconVariant": "economy-origin-destination-change"
+            },
+            {
+                "ProductName": "FrequentFlyer",
+                "IsIncluded": true,
+                "DisplayText": "包括",
+                "Title": "忠誠獎勵",
+                "SubTitle": null,
+                "SsrCode": "LOYT",
+                "SortOrder": 9,
+                "CabinType": "Economy",
+                "RefId": "Eb+ydtDs/t1mHDDfn2dv3Q==",
+                "IconVariant": "economy-loyalty-points"
+            },
+            {
+                "ProductName": "Seat",
+                "IsIncluded": true,
+                "DisplayText": "一般",
+                "Title": "選位",
+                "SubTitle": null,
+                "SsrCode": "FXS1",
+                "SortOrder": 3,
+                "CabinType": "Economy",
+                "RefId": "p2ZbfTFp93on6OZEmvSM+A==",
+                "IconVariant": "economy-seat"
+            },
+            {
+                "ProductName": "DateTimeChange",
+                "IsIncluded": false,
+                "DisplayText": "需支付更改費用",
+                "Title": "日期和時間更改*",
+                "SubTitle": "我們或會收取票價差額",
+                "SsrCode": null,
+                "SortOrder": 5,
+                "CabinType": "Economy",
+                "RefId": "HxyP2sgcEoNPJG/Pew60bQ==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "SameDayChange",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "免費即日更改*",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 6,
+                "CabinType": "Economy",
+                "RefId": "T9DWQCiTqlVfNkxThie8Vw==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "CancelFlight",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "取消你的航班*",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 7,
+                "CabinType": "Economy",
+                "RefId": "Gf5F7nNl9bVlMhfu+mYTaA==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "FrequentFlyer",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "忠誠獎勵",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 9,
+                "CabinType": "Economy",
+                "RefId": "skjgAOyXx+yXe71m2AFbrg==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "Seat",
+                "IsIncluded": false,
+                "DisplayText": "稍後添加或獲得免費分配座位",
+                "Title": "選位",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 3,
+                "CabinType": "Economy",
+                "RefId": "hfmW7rDTv6BA5r35PZqXeQ==",
+                "IconVariant": "clear-circle"
+            },
+            {
+                "ProductName": "FrequentFlyer",
+                "IsIncluded": false,
+                "DisplayText": "不適用",
+                "Title": "忠誠獎勵",
+                "SubTitle": null,
+                "SsrCode": null,
+                "SortOrder": 9,
+                "CabinType": "Economy",
+                "RefId": "yKllSRBGWvGXMjRuYK87Bw==",
+                "IconVariant": "clear-circle"
+            }
+        ]
+    }
+}

+ 82 - 0
3.31Gk航司/其他/控制流平坦化-状态机为变量/ast.js

@@ -0,0 +1,82 @@
+const fs = require("fs");//文件读写
+const parse = require("@babel/parser"); //解析为ast
+const traverse = require('@babel/traverse').default;//遍历节点
+const t = require('@babel/types');//类型
+const generator = require('@babel/generator').default;//ast解析为代码
+
+
+//读取混淆js文件
+const jsCode = fs.readFileSync('./encode.js', {encoding: 'utf-8'});
+
+
+const visitor = {
+    WhileStatement(path) {                // 处理 While 循环语句
+        const {test, body} = path.node;   // 解构循环条件和循环体
+
+        // 硬编码状态变量名和初始值(需后续从代码动态提取)
+        let init_name = 'index';           // 状态变量名(示例值)
+        let init_value = 0;                // 初始状态值(示例值)
+
+        const switch_body = body.body[0];  // 提取循环体内的第一个()语句
+
+        // 验证是否为 Switch 语句,否则终止处理
+        if (!t.isSwitchStatement(switch_body)) return;
+
+        const {discriminant, cases} = switch_body;  // 解构 Switch 的条件和分支列表
+
+        // 验证 Switch 条件是否为指定状态变量
+        if (!t.isIdentifier(discriminant, {name: init_name})) return;
+
+        const ret_body = [];               // 存储最终生成的代码块集合
+        let end_flag = false;              // 终止循环处理标志
+
+        while (true) {                     // 循环处理所有状态分支
+            if (end_flag) break;            // 检测终止条件
+
+            for (const each_case of cases) { // 遍历 Switch 的所有 case 分支
+                const {test, consequent} = each_case;
+
+                // 跳过非当前状态的 case 分支
+                if (init_value !== test.value) continue;
+
+                // 移除分支末尾的 continue 语句
+                if (t.isContinueStatement(consequent[consequent.length - 1])) {
+                    consequent.pop();
+                }
+
+                // 处理状态变量更新逻辑
+                if (t.isExpressionStatement(consequent[consequent.length - 1])) {
+                    const {expression} = consequent[consequent.length - 1];
+
+                    // 解析状态变量赋值表达式
+                    if (t.isAssignmentExpression(expression)) {
+                        const {left, right} = expression;
+
+                        // 更新状态变量值并移除赋值语句
+                        if (t.isIdentifier(left, {name: init_name})) {
+                            init_value = right.value;
+                            consequent.pop();
+                        }
+                    }
+                }
+
+                // 检测 return 语句作为终止信号
+                if (t.isReturnStatement(consequent[consequent.length - 1])) {
+                    end_flag = true;
+                }
+
+                ret_body.push(...consequent);  // 合并处理后的代码块
+                break;                         // 退出当前分支处理循环
+            }
+        }
+
+        path.replaceInline(ret_body);      // 用线性代码替换原循环结构
+    }
+};
+
+let ast = parse.parse(jsCode);//js转ast
+traverse(ast, visitor)  // 处理控制流平坦化
+
+let {code} = generator(ast)
+
+console.log(code)

+ 33 - 0
3.31Gk航司/其他/控制流平坦化-状态机为变量/encode.js

@@ -0,0 +1,33 @@
+function test() {
+    var index = 0;
+    while (1) {
+        switch (index) {
+            case 0:
+                console.log('this is case-block 0');
+                index = 3
+                continue
+            case 1:
+                console.log('this is case-block 1');
+                return;
+                index = 5
+                continue
+            case 2:
+                console.log('this is case-block 2');
+                index = 1
+                continue
+            case 3:
+                console.log('this is case-block 3');
+                index = 4
+                continue
+            case 4:
+                console.log('this is case-block 4');
+                index = 2
+                continue
+        }
+    }
+}
+
+test()
+
+
+

+ 100 - 0
3.31Gk航司/其他/控制流平坦化-状态机为变量/test.js

@@ -0,0 +1,100 @@
+const parser = require('@babel/parser');
+const traverse = require('@babel/traverse').default;
+const fs = require('fs');
+
+const code = `
+let state = 0, x = 5;
+while (1) {
+    switch (state) {
+        case 0:
+            console.log('执行块 0 操作')
+            state = 1;
+            break;
+        case 1:
+            state = (x > 0) ? 2 : 3;
+            console.log('执行块 1 操作')
+            break;
+        case 2:
+            console.log('执行块 2 操作')
+            state = 4;
+            break;
+        case 3:
+            console.log('执行块 3 操作')
+            state = 4;
+            break;
+        case 4:
+            console.log('程序执行完毕');
+    }
+}
+`;
+
+const ast = parser.parse(code, { sourceType: 'module' });
+
+let initialState = null;
+let switchCases = {};
+
+traverse(ast, {
+  VariableDeclarator(path) {
+    if (path.node.id.name === 'state') {
+      initialState = path.node.init.value;
+    }
+  },
+  SwitchCase(path) {
+    const test = path.node.test.value;
+    const body = path.node.consequent;
+    let logs = [];
+    let nextState = null;
+
+    body.forEach(node => {
+      if (
+        node.type === 'ExpressionStatement' &&
+        node.expression.type === 'CallExpression' &&
+        node.expression.callee.object.name === 'console'
+      ) {
+        logs.push(node.expression.arguments[0].value);
+      }
+
+      if (
+        node.type === 'ExpressionStatement' &&
+        node.expression.type === 'AssignmentExpression' &&
+        node.expression.left.name === 'state'
+      ) {
+        nextState = node.expression.right;
+      }
+    });
+
+    switchCases[test] = { logs, nextState };
+  }
+});
+
+function formatNextState(nextState) {
+  if (nextState.type === 'ConditionalExpression') {
+    return `if (${generateCode(nextState.test)}) {
+  ${switchCases[nextState.consequent.value].logs.map(log => `console.log('${log}')`).join('\n  ')}
+} else {
+  ${switchCases[nextState.alternate.value].logs.map(log => `console.log('${log}')`).join('\n  ')}
+}`;
+  } else if (nextState.type === 'NumericLiteral') {
+    const logs = switchCases[nextState.value]?.logs || [];
+    return logs.map(log => `console.log('${log}')`).join('\n');
+  } else {
+    return '// 未识别的跳转';
+  }
+}
+
+function generateCode(node) {
+  if (node.type === 'BinaryExpression') {
+    return `${node.left.name} ${node.operator} ${node.right.value}`;
+  }
+  return '// 未识别表达式';
+}
+
+// 🌳 生成结构化代码
+let outputCode = '';
+outputCode += switchCases[0].logs.map(log => `console.log('${log}')`).join('\n') + '\n';
+
+outputCode += formatNextState(switchCases[1].nextState) + '\n';
+outputCode += switchCases[4].logs.map(log => `console.log('${log}')`).join('\n');
+
+console.log('\n✅ 结构化还原后的代码:\n');
+console.log(outputCode);

+ 20 - 0
3.31Gk航司/其他/获取加密cookie.py

@@ -0,0 +1,20 @@
+import requests
+
+
+headers = {
+    "accept": "*/*",
+    "accept-language": "zh-CN,zh;q=0.9",
+    "cache-control": "no-cache",
+    "content-type": "text/plain;charset=UTF-8",
+    "origin": "https://www.jetstar.com",
+    "pragma": "no-cache",
+    "priority": "u=1, i",
+    "referer": "https://www.jetstar.com/hk/zh/home?adults=1&children=0&flexible=1&flight-type=2&infants=0&origin=PVG&tab=1",
+    "sec-ch-ua": "\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"",
+    "sec-ch-ua-mobile": "?0",
+    "sec-ch-ua-platform": "\"Windows\"",
+    "sec-fetch-dest": "empty",
+    "sec-fetch-mode": "cors",
+    "sec-fetch-site": "same-origin",
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"
+}

+ 52 - 0
3.31Gk航司/分析

@@ -0,0 +1,52 @@
+第一次请求获取 bmsz  响应{"success": false}  可以不带任何参数。。不严格
+第二次携带bmsz 请求响应为{"success": true}  (响应只有一个abck) 才表示验证逻辑没问题,
+    但并没有通过风控验证(可能是指纹不对, 通过风控后才能请求数据)
+
+
+
+替换js时,只能替换当前最新的js文件, 用旧文件(如前一天)用作替换文件时,不会生效
+替换js后  也会返回  0值的abck
+
+
+// 新的akm js文件 搜索,可以搜  = {}; 从而快速定位 指纹数组生成位置 第一次请求时,里面有些值可能为空。。。观察下
+
+
+!!每次请求都有可能请求超时,这不是cookie不对,是网络问题
+
+
+2次请求的 startTs 一致
+
+开 fiddler 抓包工具获取的cookie 请求数据成功率是100%, 反之 可能请求超时/ 重定向到验证码 页面   =》 因为 tls指纹
+
+有 tls 指纹检测,同一个指纹请求过多会导致请求超时 (要换 tls指纹) 获取 0 值的abck同理
+
+
+0 abck
+    请求3次接口 第3次才返回真cookie ??
+
+    回响契机:
+        ajr
+        din
+            hal
+            ran
+            dme
+            doe
+        mev
+        mst
+            mevl
+            devl
+            dmvl
+            tovl
+            delt
+            sts
+            fct
+            mc
+            ssts
+            tst
+            jsrf1
+            jsrf2
+            dvc
+        vev
+        wsl
+
+

+ 163 - 0
3.31Gk航司/请求-curl_cffi.py

@@ -0,0 +1,163 @@
+from datetime import datetime, timedelta
+
+from curl_cffi import requests
+# import requests
+from requests.exceptions import Timeout
+import retrying
+import execjs
+import json
+import time
+from loguru import logger
+
+
+class GK:
+
+    def __init__(self):
+        self.search_flights_api = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+        self.headers = {
+            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+            "accept-language": "zh-CN,zh;q=0.9",
+            "cache-control": "no-cache",
+            "pragma": "no-cache",
+            "priority": "u=0, i",
+            "referer": "https://booking.jetstar.com/",
+            "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "document",
+            "sec-fetch-mode": "navigate",
+            "sec-fetch-site": "same-origin",
+            "sec-fetch-user": "?1",
+            "upgrade-insecure-requests": "1",
+            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
+        }
+        with open('./akm逆向/逆向.js', encoding='utf-8') as f:
+            js = f.read()
+        self.ctx = execjs.compile(js)
+        self.session = requests.Session()
+
+    def get_cookie(self):
+        # akm js file url
+        akm_url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+
+        data = {
+            'sensor_data': self.ctx.call('encrypt1')
+        }
+        response = self.session.post(akm_url, headers=self.headers, verify=False, data=data,
+                                     impersonate='chrome101',
+                                     # 不指定 impersonate 时,TLS 指纹是 curl 原生的,而非浏览器指纹(依旧过不了检测)。需显式设置该参数以绕过 TLS 指纹检测
+                                     http_version=2
+                                     )
+
+        print(response.text)
+        bmsz = response.cookies.get_dict()['bm_sz']
+        print('bmsz =>', bmsz)
+
+        data2 = {
+            "sensor_data": self.ctx.call('encrypt2', bmsz)
+        }
+
+        data2 = json.dumps(data2)
+        response2 = self.session.post(akm_url, headers=self.headers, data=data2, verify=False,
+                                      impersonate='chrome101',
+                                      http_version=2
+                                      )
+        print(response2.text)
+        print(response2.status_code)
+        print(response2.cookies.get_dict())
+
+    @retrying.retry(stop_max_attempt_number=3)
+    def send_get(self, url, params):
+
+        try:
+            response = self.session.get(
+                url,
+                headers=self.headers, params=params,
+                timeout=15,
+                verify=False,
+                # proxies=proxies
+                impersonate='chrome101',
+                http_version=2
+            )
+            response.raise_for_status()
+            return response
+        # 捕获超时请求,可能是cookie不行了,更新后报错触发重试
+        except Timeout as e:
+            print(f"请求超时,重新更换cookie: {e}")
+            # # 清除旧 Cookie
+            # self.session.cookies.clear()
+            # print(self.session.cookies.get_dict())
+            # self.get_cookie()
+            raise
+
+        # except Exception as e:
+        #     logger.error(e)
+        #
+        #     return None
+
+    def get_data(self, datetime_str):
+        params = {
+            "s": "true",
+            "adults": "1",  # 成年人
+            "children": "0",  # 儿童
+            "infants": "0",  # 婴儿
+            "selectedclass1": "economy",  # 选择类型:经济舱
+            "currency": "CNY",  # 货币
+            "mon": "true",
+            "channel": "DESKTOP",
+            "origin1": "PVG",  # 出发地
+            "destination1": "NRT",  # 目的地
+            "departuredate1": datetime_str  # 出发时间
+        }
+
+        response = self.send_get(self.search_flights_api, params)
+        if not response:
+            return
+
+        # print(response.text)
+        print(response)
+
+        from lxml import etree
+        import json
+
+        html = etree.HTML(response.text)
+        data = html.xpath("//script[@id='bundle-data-v2']/text()")
+        if data:
+            json_data = json.loads(data[0])
+            print(datetime_str, ' => ', json_data)
+        else:
+            print(response.text)
+
+    @staticmethod
+    def gen_datetime(start_date, end_date):
+        """生成抓取日期: 2025-03-09 传入这种格式"""
+        # 将字符串转换为 datetime 对象
+        current_date = datetime.strptime(start_date, '%Y-%m-%d')
+        end_date = datetime.strptime(end_date, '%Y-%m-%d')
+
+        # 初始化一个空列表来存储日期
+        date_list = []
+
+        # 使用 timedelta 循环遍历每一天
+        while current_date <= end_date:
+            date_list.append(current_date.strftime('%Y-%m-%d'))  # 转换为字符串格式存储
+            current_date += timedelta(days=1)
+
+        return date_list
+
+    def run(self, start_date, end_date):
+        self.get_cookie()
+        # 获取采集时间
+        for num, datetime_str in enumerate(self.gen_datetime(start_date, end_date), start=1):
+            # if num % 5 == 0:
+            #     self.session = requests.Session()
+            #     self.get_cookie()
+
+            self.get_data(datetime_str)
+            # time.sleep(1)
+
+
+if __name__ == '__main__':
+    gk = GK()
+    gk.run(start_date='2025-05-15', end_date='2025-05-27')

+ 169 - 0
3.31Gk航司/请求-httpx.py

@@ -0,0 +1,169 @@
+import httpx
+
+import time
+from datetime import datetime, timedelta
+
+import retrying
+import execjs
+from lxml import etree
+import json
+from loguru import logger
+
+import threading
+from queue import Queue
+import requests
+
+class GK:
+
+    def __init__(self):
+        self.search_flights_api = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+        with open('./akm逆向/逆向.js', encoding='utf-8') as f:
+            js = f.read()
+        self.ctx = execjs.compile(js)
+        ja3 = "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,5-10-11-17613-45-43-0-23-18-65037-27-35-13-51-65281-16-41,4588-29-23-24,0"
+
+        self.client = httpx.Client(
+            http2=True,
+            verify=False
+        )
+
+
+        # self.session = requests.Session()
+        self.headers = {
+            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+            "accept-language": "zh-CN,zh;q=0.9",
+            "cache-control": "no-cache",
+            "pragma": "no-cache",
+            "priority": "u=0, i",
+            "referer": "https://booking.jetstar.com/",
+            "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "document",
+            "sec-fetch-mode": "navigate",
+            "sec-fetch-site": "same-origin",
+            "sec-fetch-user": "?1",
+            "upgrade-insecure-requests": "1",
+            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
+        }
+
+    def get_cookie(self):
+        logger.debug('正在获取 cookie bm-sz...')
+
+        # akm js file url
+        akm_url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+
+        data = {
+            'sensor_data': self.ctx.call('encrypt1')
+        }
+        response = self.client.post(akm_url, headers=self.headers, data=data,
+                                     # proxies=self.proxies
+                                     )
+        # print(response.http_version)  # 应该显示 "HTTP/2"
+
+        # print(response.text)
+        bmsz = response.cookies.get('bm_sz')
+
+        data2 = {
+            "sensor_data": self.ctx.call('encrypt2', bmsz)
+        }
+
+        data2 = json.dumps(data2)
+        response2 = self.client.post(akm_url, headers=self.headers, data=data2,
+                                      # proxies=self.proxies
+                                      )
+        # print(response2.text)
+        # print(response2.status_code)
+        logger.debug(f'成功获取到 bm-sz :{bmsz}')
+
+
+    @retrying.retry(stop_max_attempt_number=2)
+    def send_get(self, url, params):
+        print(dict(self.client.cookies))
+        response = self.client.get(
+            url,
+            headers=self.headers,
+            params=params,
+        )
+        print(response.status_code)
+        print(response.text)
+        if response.status_code == 302:
+            url = 'https://booking.jetstar.com/hk/zh/booking/select-flights'
+            response = self.client.get(url, headers=self.headers)
+
+        print(response.status_code)
+        print(response.text)
+        return response
+
+    @retrying.retry(stop_max_attempt_number=3)
+    def get_data(self, datetime_str):
+        params = {
+            "s": "true",
+            "adults": "1",  # 成年人
+            "children": "0",  # 儿童
+            "infants": "0",  # 婴儿
+            "selectedclass1": "economy",  # 选择类型:经济舱
+            "currency": "CNY",  # 货币
+            "mon": "true",
+            "channel": "DESKTOP",
+            "origin1": "PVG",  # 出发地
+            "destination1": "NRT",  # 目的地
+            "departuredate1": datetime_str  # 出发时间
+        }
+        logger.info(f'正在采集 {datetime_str} 航班数据...')
+        try:
+            response = self.send_get(self.search_flights_api, params)
+
+            if not response:
+                return
+
+            return datetime_str, response
+            # print(response.text)
+
+        except Exception as e:
+            logger.error(e)
+            # self.ip += 1
+            self.get_cookie()
+            raise
+            # return datetime_str, None
+
+    def parse_data(self, datetime_str, response):
+        if not response:
+            return
+
+        html = etree.HTML(response.text)
+        data = html.xpath("//script[@id='bundle-data-v2']/text()")
+        if data:
+            json_data = json.loads(data[0])
+            print(datetime_str, ' => ', json_data)
+        else:
+            logger.warning(f'{datetime_str} 当天暂无数据 / 触发验证码')
+            print(response.text)
+
+    @staticmethod
+    def gen_datetime(start_date, end_date):
+        current_date = datetime.strptime(start_date, '%Y-%m-%d')
+        end_date = datetime.strptime(end_date, '%Y-%m-%d')
+        date_list = []
+        while current_date <= end_date:
+            date_list.append(current_date.strftime('%Y-%m-%d'))  # 转换为字符串格式存储
+            current_date += timedelta(days=1)
+        return date_list
+
+    def run(self, start_date, end_date):
+        self.get_cookie()
+        # 获取采集时间
+        for num, datetime_str in enumerate(self.gen_datetime(start_date, end_date)):
+            # if num % 4 == 0:
+            #     self.session = requests.Session()
+            #     self.get_cookie()
+
+            datetime_str, response = self.get_data(datetime_str)
+            self.parse_data(datetime_str, response)
+            time.sleep(2)
+
+
+if __name__ == '__main__':
+    gk = GK()
+    gk.run(start_date='2025-05-15', end_date='2025-05-27')

+ 176 - 0
3.31Gk航司/请求-requests版.py

@@ -0,0 +1,176 @@
+from datetime import datetime, timedelta
+
+import requests
+
+from requests.exceptions import Timeout
+import retrying
+import execjs
+from lxml import etree
+import json
+from loguru import logger
+
+import threading
+from queue import Queue
+
+#
+
+# 禁用SSL相关警告 (推荐)
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
+import warnings
+
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
+warnings.filterwarnings("ignore", category=DeprecationWarning)  # 可选:过滤其他警告
+
+
+class GK:
+
+    def __init__(self):
+        self.search_flights_api = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+        self.headers = {
+            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',
+            'Accept-Encoding': 'gzip, deflate, br',
+            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
+            'Connection': 'keep-alive',
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'accept-language': 'zh-CN,zh;q=0.9',
+            'cache-control': 'no-cache',
+            'pragma': 'no-cache',
+            'priority': 'u=0, i',
+            'referer': 'https://booking.jetstar.com/',
+            'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
+            'sec-ch-ua-mobile': '?0',
+            'sec-ch-ua-platform': '"Windows"',
+            'sec-fetch-dest': 'document',
+            'sec-fetch-mode': 'navigate',
+            'sec-fetch-site': 'same-origin',
+            'sec-fetch-user': '?1',
+            'upgrade-insecure-requests': '1'
+        }
+        with open('./akm逆向/逆向.js', encoding='utf-8') as f:
+            js = f.read()
+        self.ctx = execjs.compile(js)
+        self.session = requests.Session()
+        # self.ip = 100000000000
+        # self.proxies = {
+        #     'http': f'http://B_3351_HK___5_ss-{self.ip}:ev2pjj@proxy.renlaer.com:7778',
+        #     'https': f'http://B_3351_HK___5_ss-{self.ip}:ev2pjj@proxy.renlaer.com:7778'
+        # }
+        # self.proxies = {
+        #     'http': f'127.0.0.1:8888',
+        #     'https': f'127.0.0.1:8888'
+        # }
+        self.cookies_queue = Queue()
+
+    def get_cookie(self):
+        logger.debug('正在获取 cookie bm-sz...')
+
+        # akm js file url
+        akm_url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+
+        data = {
+            'sensor_data': self.ctx.call('encrypt1')
+        }
+        response = self.session.post(akm_url, headers=self.headers, verify=False, data=data,
+                                     # proxies=self.proxies
+                                     )
+
+        # print(response.text)
+        bmsz = response.cookies.get_dict()['bm_sz']
+
+        data2 = {
+            "sensor_data": self.ctx.call('encrypt2', bmsz)
+        }
+
+        data2 = json.dumps(data2)
+        response2 = self.session.post(akm_url, headers=self.headers, data=data2, verify=False,
+                                      # proxies=self.proxies
+                                      )
+        # print(response2.text)
+        # print(response2.status_code)
+        logger.debug(f'成功获取到 bm-sz :{bmsz}')
+
+    @retrying.retry(stop_max_attempt_number=2)
+    def send_get(self, url, params):
+        response = self.session.get(
+            url,
+            headers=self.headers, params=params,
+            timeout=15,
+            verify=False,
+        )
+        response.raise_for_status()
+        return response
+
+    @retrying.retry(stop_max_attempt_number=3)
+    def get_data(self, datetime_str):
+        params = {
+            "s": "true",
+            "adults": "1",  # 成年人
+            "children": "0",  # 儿童
+            "infants": "0",  # 婴儿
+            "selectedclass1": "economy",  # 选择类型:经济舱
+            "currency": "CNY",  # 货币
+            "mon": "true",
+            "channel": "DESKTOP",
+            "origin1": "PVG",  # 出发地
+            "destination1": "NRT",  # 目的地
+            "departuredate1": datetime_str  # 出发时间
+        }
+        logger.info(f'正在采集 {datetime_str} 航班数据...')
+        try:
+            response = self.send_get(self.search_flights_api, params)
+
+            if not response:
+                return
+
+            return datetime_str, response
+            # print(response.text)
+
+        except Exception as e:
+            logger.error(e)
+            self.session = requests.Session()
+            # self.ip += 1
+            self.get_cookie()
+            raise
+            # return datetime_str, None
+
+    def parse_data(self, datetime_str, response):
+        if not response:
+            return
+
+        html = etree.HTML(response.text)
+        data = html.xpath("//script[@id='bundle-data-v2']/text()")
+        if data:
+            json_data = json.loads(data[0])
+            print(datetime_str, ' => ', json_data)
+        else:
+            logger.warning(f'{datetime_str} 当天暂无数据 / 触发验证码')
+            print(response.text)
+
+    @staticmethod
+    def gen_datetime(start_date, end_date):
+        current_date = datetime.strptime(start_date, '%Y-%m-%d')
+        end_date = datetime.strptime(end_date, '%Y-%m-%d')
+        date_list = []
+        while current_date <= end_date:
+            date_list.append(current_date.strftime('%Y-%m-%d'))  # 转换为字符串格式存储
+            current_date += timedelta(days=1)
+        return date_list
+
+    def run(self, start_date, end_date):
+        self.get_cookie()
+        # 获取采集时间
+        for num, datetime_str in enumerate(self.gen_datetime(start_date, end_date)):
+            # if num % 4 == 0:
+            #     self.session = requests.Session()
+            #     self.get_cookie()
+
+            datetime_str, response = self.get_data(datetime_str)
+            self.parse_data(datetime_str, response)
+            # time.sleep(2)
+
+
+if __name__ == '__main__':
+    gk = GK()
+    gk.run(start_date='2025-05-15', end_date='2025-05-27')
+

+ 168 - 0
3.31Gk航司/请求-tls_client.py

@@ -0,0 +1,168 @@
+import time
+from datetime import datetime, timedelta
+
+from tls_client import Session
+
+from requests.exceptions import Timeout
+import retrying
+import execjs
+from lxml import etree
+import json
+from loguru import logger
+
+import threading
+from queue import Queue
+import requests
+
+class GK:
+
+    def __init__(self):
+        self.search_flights_api = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+        with open('./akm逆向/逆向.js', encoding='utf-8') as f:
+            js = f.read()
+        self.ctx = execjs.compile(js)
+        ja3 = "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,5-10-11-17613-45-43-0-23-18-65037-27-35-13-51-65281-16-41,4588-29-23-24,0"
+
+        # 基础配置(指定浏览器指纹)
+        self.session = Session(
+            client_identifier="Chrome_120",  # 预设浏览器指纹
+            random_tls_extension_order=True,  # 随机tls指纹
+        )
+        self.session.http2 = True
+
+
+        # self.session = requests.Session()
+        self.headers = {
+            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+            "accept-language": "zh-CN,zh;q=0.9",
+            "cache-control": "no-cache",
+            "pragma": "no-cache",
+            "priority": "u=0, i",
+            "referer": "https://booking.jetstar.com/",
+            "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+            "sec-ch-ua-mobile": "?0",
+            "sec-ch-ua-platform": "\"Windows\"",
+            "sec-fetch-dest": "document",
+            "sec-fetch-mode": "navigate",
+            "sec-fetch-site": "same-origin",
+            "sec-fetch-user": "?1",
+            "upgrade-insecure-requests": "1",
+            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
+        }
+
+    def get_cookie(self):
+        logger.debug('正在获取 cookie bm-sz...')
+
+        # akm js file url
+        akm_url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+
+        data = {
+            'sensor_data': self.ctx.call('encrypt1')
+        }
+        response = self.session.post(akm_url, headers=self.headers, data=data,
+                                     # proxies=self.proxies
+                                     )
+        # print(response.http_version)  # 应该显示 "HTTP/2"
+
+        # print(response.text)
+        bmsz = response.cookies.get_dict()['bm_sz']
+
+        data2 = {
+            "sensor_data": self.ctx.call('encrypt2', bmsz)
+        }
+
+        data2 = json.dumps(data2)
+        response2 = self.session.post(akm_url, headers=self.headers, data=data2,
+                                      # proxies=self.proxies
+                                      )
+        # print(response2.text)
+        # print(response2.status_code)
+        logger.debug(f'成功获取到 bm-sz :{bmsz}')
+
+    @retrying.retry(stop_max_attempt_number=2)
+    def send_get(self, url, params):
+
+        response = self.session.get(
+            url,
+            headers=self.headers,
+            params=params,
+        )
+        if response.status_code == 302:
+            url = 'https://booking.jetstar.com/hk/zh/booking/select-flights'
+            response = self.session.get(url, headers=self.headers)
+        print(response.status_code)
+        print(response.text)
+        return response
+
+    @retrying.retry(stop_max_attempt_number=3)
+    def get_data(self, datetime_str):
+        params = {
+            "s": "true",
+            "adults": "1",  # 成年人
+            "children": "0",  # 儿童
+            "infants": "0",  # 婴儿
+            "selectedclass1": "economy",  # 选择类型:经济舱
+            "currency": "CNY",  # 货币
+            "mon": "true",
+            "channel": "DESKTOP",
+            "origin1": "PVG",  # 出发地
+            "destination1": "NRT",  # 目的地
+            "departuredate1": datetime_str  # 出发时间
+        }
+        logger.info(f'正在采集 {datetime_str} 航班数据...')
+        try:
+            response = self.send_get(self.search_flights_api, params)
+
+            if not response:
+                return
+
+            return datetime_str, response
+            # print(response.text)
+
+        except Exception as e:
+            logger.error(e)
+            # self.ip += 1
+            self.get_cookie()
+            raise
+            # return datetime_str, None
+
+    def parse_data(self, datetime_str, response):
+        if not response:
+            return
+
+        html = etree.HTML(response.text)
+        data = html.xpath("//script[@id='bundle-data-v2']/text()")
+        if data:
+            json_data = json.loads(data[0])
+            print(datetime_str, ' => ', json_data)
+        else:
+            logger.warning(f'{datetime_str} 当天暂无数据 / 触发验证码')
+            print(response.text)
+
+    @staticmethod
+    def gen_datetime(start_date, end_date):
+        current_date = datetime.strptime(start_date, '%Y-%m-%d')
+        end_date = datetime.strptime(end_date, '%Y-%m-%d')
+        date_list = []
+        while current_date <= end_date:
+            date_list.append(current_date.strftime('%Y-%m-%d'))  # 转换为字符串格式存储
+            current_date += timedelta(days=1)
+        return date_list
+
+    def run(self, start_date, end_date):
+        self.get_cookie()
+        # 获取采集时间
+        for num, datetime_str in enumerate(self.gen_datetime(start_date, end_date)):
+            # if num % 4 == 0:
+            #     self.session = requests.Session()
+            #     self.get_cookie()
+
+            datetime_str, response = self.get_data(datetime_str)
+            self.parse_data(datetime_str, response)
+            time.sleep(2)
+
+
+if __name__ == '__main__':
+    gk = GK()
+    gk.run(start_date='2025-05-15', end_date='2025-05-27')

+ 234 - 0
3.31Gk航司/请求requests 多线程.py

@@ -0,0 +1,234 @@
+import time
+from datetime import datetime, timedelta
+
+import requests
+
+from requests.exceptions import Timeout
+import retrying
+import execjs
+from lxml import etree
+import json
+from loguru import logger
+
+import threading
+from queue import Queue
+
+import pandas as pd
+
+# 禁用SSL相关警告 (推荐)
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
+import warnings
+
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
+warnings.filterwarnings("ignore", category=DeprecationWarning)  # 可选:过滤其他警告
+
+
+class GK:
+
+    def __init__(self):
+        self.search_flights_api = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+        self.headers = {
+            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',
+            'Accept-Encoding': 'gzip, deflate, br',
+            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
+            'Connection': 'keep-alive',
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'accept-language': 'zh-CN,zh;q=0.9',
+            'cache-control': 'no-cache',
+            'pragma': 'no-cache',
+            'priority': 'u=0, i',
+            'referer': 'https://booking.jetstar.com/',
+            'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
+            'sec-ch-ua-mobile': '?0',
+            'sec-ch-ua-platform': '"Windows"',
+            'sec-fetch-dest': 'document',
+            'sec-fetch-mode': 'navigate',
+            'sec-fetch-site': 'same-origin',
+            'sec-fetch-user': '?1',
+            'upgrade-insecure-requests': '1'
+        }
+        with open('./akm逆向/逆向.js', encoding='utf-8') as f:
+            js = f.read()
+        self.ctx = execjs.compile(js)
+        self.session = requests.Session()
+        # self.ip = 100000000000
+        # self.proxies = {
+        #     'http': f'http://B_3351_HK___5_ss-{self.ip}:ev2pjj@proxy.renlaer.com:7778',
+        #     'https': f'http://B_3351_HK___5_ss-{self.ip}:ev2pjj@proxy.renlaer.com:7778'
+        # }
+        # self.proxies = {
+        #     'http': f'127.0.0.1:8888',
+        #     'https': f'127.0.0.1:8888'
+        # }
+        self.lock = threading.Lock()
+        self.cookies_queue = Queue(maxsize=10)
+        self.task_queue = Queue()
+        self.resp_data_queue = Queue()
+
+    @retrying.retry(stop_max_attempt_number=3,  wait_fixed=4000)
+    def get_cookie(self):
+        logger.debug('正在获取 cookie bm-sz...')
+
+        # akm js file url
+        akm_url = "https://booking.jetstar.com/MkuYlo/pcp/LD0/PPluEQ/1ik7QcJffXbmL53i/QTcvXmg7/KS5kC3N/VRQcB"
+
+        data = {
+            'sensor_data': self.ctx.call('encrypt1')
+        }
+        response = self.session.post(akm_url, headers=self.headers, verify=False, data=data,
+                                 # proxies=self.proxies
+                                 )
+
+        print(response.text)
+        bmsz = response.cookies.get_dict()['bm_sz']
+
+        data2 = {
+            "sensor_data": self.ctx.call('encrypt2', bmsz)
+        }
+
+        data2 = json.dumps(data2)
+        response2 = self.session.post(akm_url, headers=self.headers, data=data2, verify=False,
+                                  )
+        print(response2.text)
+        print(response2.status_code)
+        with self.lock:
+            logger.debug(f'成功获取到 bm-sz :{bmsz}')
+
+        return bmsz
+
+    def get_cookie_thread(self):
+        while True:
+            if self.cookies_queue.qsize() < 1:
+                new_cookie = self.get_cookie()
+                cookies = {
+                    "bm_sz": new_cookie
+                }
+                self.cookies_queue.put(cookies)
+
+            time.sleep(15)
+
+    def gen_city(self):
+        """提取Excel表格的城市对信息, 用set去重"""
+        # 只读取Excel的Sheet1的航段信息, 将读取的数据存储在 df(DataFrame 对象)中。
+        df = pd.read_excel(
+            self.excel_path,
+            sheet_name="Sheet1",
+            usecols=["出发机场", "到达机场"]  # 只读取 "出发机场" 和 "到达机场" 两列。
+        )
+
+        segment_info = set()
+        segment_info.add('YNT,XIY')
+
+        # 遍历 DataFrame 的每一行
+        # for row in df.itertuples(index=True, name='Pandas'):
+        #     # 访问行中的数据
+        #     segment_info.add(row.出发机场 + ',' + row.到达机场)
+        # logger.info(f'去重后的航段长度: {len(segment_info)}, {segment_info}')
+        return segment_info
+
+    def gen_task(self, start_date, end_date):
+        """将每个城市对与日期组合生成独立任务, 上传到任务队列"""
+        # 获取采集城市对
+        # for city_code in self.gen_city():
+        # 获取采集时间
+        for datetime_str in self.gen_datetime(start_date, end_date):
+            # self.task_queue.put((city_code, datetime_str))
+            self.task_queue.put((datetime_str))
+
+    @retrying.retry(stop_max_attempt_number=2)
+    def send_get(self, url, params, cookies):
+        response = requests.get(
+            url,
+            headers=self.headers, params=params, cookies=cookies,
+            timeout=15,
+            verify=False,
+        )
+        # print(response)
+        # print(response.text)
+        response.raise_for_status()
+        self.cookies_queue.put(cookies)
+        return response
+
+    @retrying.retry(stop_max_attempt_number=3)
+    def get_data(self):
+        while True:
+            datetime_str = self.task_queue.get()
+            cookies = self.cookies_queue.get()
+            params = {
+                "s": "true",
+                "adults": "1",  # 成年人
+                "children": "0",  # 儿童
+                "infants": "0",  # 婴儿
+                "selectedclass1": "economy",  # 选择类型:经济舱
+                "currency": "CNY",  # 货币
+                "mon": "true",
+                "channel": "DESKTOP",
+                "origin1": "PVG",  # 出发地
+                "destination1": "NRT",  # 目的地
+                "departuredate1": datetime_str  # 出发时间
+            }
+            logger.info(f'正在采集 {datetime_str} 航班数据...')
+            try:
+                response = self.send_get(self.search_flights_api, params, cookies)
+                self.resp_data_queue.put((datetime_str, response))
+
+            except Exception as e:
+                logger.error(e)
+                self.task_queue.put(datetime_str)
+                raise
+
+            finally:
+                self.task_queue.task_done()
+                self.cookies_queue.task_done()
+
+    def parse_data(self):
+        while True:
+            datetime_str, response = self.resp_data_queue.get()
+
+            html = etree.HTML(response.text)
+            data = html.xpath("//script[@id='bundle-data-v2']/text()")
+            if data:
+                json_data = json.loads(data[0])
+                print(datetime_str, ' => ', json_data)
+            else:
+                logger.warning(f'{datetime_str} 当天暂无数据 / 触发验证码')
+                print(response.text)
+
+    @staticmethod
+    def gen_datetime(start_date, end_date):
+        current_date = datetime.strptime(start_date, '%Y-%m-%d')
+        end_date = datetime.strptime(end_date, '%Y-%m-%d')
+        date_list = []
+        while current_date <= end_date:
+            date_list.append(current_date.strftime('%Y-%m-%d'))  # 转换为字符串格式存储
+            current_date += timedelta(days=1)
+        return date_list
+
+    def run(self, start_date, end_date):
+        thread_list = []
+
+        self.gen_task(start_date, end_date)
+
+        for _ in range(1):
+            t_get_cookie = threading.Thread(target=self.get_cookie_thread)
+            thread_list.append(t_get_cookie)
+
+        for _ in range(1):
+            t_get_data = threading.Thread(target=self.get_data)
+            thread_list.append(t_get_data)
+
+        t_parse_data = threading.Thread(target=self.parse_data)
+        thread_list.append(t_parse_data)
+
+        for t_obj in thread_list:
+            t_obj.setDaemon(True)
+            t_obj.start()
+
+        for q in [self.task_queue, self.resp_data_queue]:
+            q.join()
+
+
+if __name__ == '__main__':
+    gk = GK()
+    gk.run(start_date='2025-06-15', end_date='2025-06-27')

+ 72 - 0
3.31Gk航司/请求测试.py

@@ -0,0 +1,72 @@
+# import requests
+from curl_cffi import requests
+import retrying
+
+
+headers = {
+    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+    "accept-language": "zh-CN,zh;q=0.9",
+    "cache-control": "no-cache",
+    "pragma": "no-cache",
+    "priority": "u=0, i",
+    "referer": "https://booking.jetstar.com/",
+    "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
+    "sec-ch-ua-mobile": "?0",
+    "sec-ch-ua-platform": "\"Windows\"",
+    "sec-fetch-dest": "document",
+    "sec-fetch-mode": "navigate",
+    "sec-fetch-site": "same-origin",
+    "sec-fetch-user": "?1",
+    "upgrade-insecure-requests": "1",
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
+}
+cookies = {
+
+    "bm_sz": "80764634952076F4EC0668CAE470DF02~YAAQh6InF+vHy7OWAQAAPBkxtBvjipCr2+Be8lQpPuukMutGdZhmvPLcnZxIE0H2SW8teLqWp1Pvw21yJC+5YdaIKtxfxi0OuJ8v+NYVJhYGUTIhe0PpH/U5LLuwLSHz3U/e4AhvEklMvEWDUPGyGsBVUktXU8G4WhSk0rur3qSc/ytEzR8U/oP3quyUwtlFgX8liYL6uhvWEY+4yRjnhaJykTIt7Fw+BhWNVvF8jKtn7usSkqm6oi+S3zSEZD8iBZolfvNCsmuZ3lD+PNlG8zH3hSiQAvC5vCPcskk6AONlJP2URQVkirgZzORWdM0+Uit7lyqEmossKcSdxITkS4amRpXnUN97PSG1Lji0j0JrytJAC2PP0VUlqtSgn0k/iTLz2+L498HNB0VpoSrW8lTry8jtixmFJ+c/iUiFWW6jvqZWAG6p01J+v95zmkX3vmkN2aR5p74UHxyBxm/Y4ZRlbgSj34TS+Z6erY/ezT0Xp9coSt7+mf2LntSVpSlxj4ZA54Pn5pN9oaPqtm1/Xz6kkYH43DIKXhoUghwV/YcKUeeF2bowXCWCbGVGkg==~3425331~3687985",
+
+}
+url = "https://booking.jetstar.com/hk/zh/booking/search-flights"
+
+
+
+
+@retrying.retry(stop_max_attempt_number=1)
+def req(i):
+    params = {
+        "s": "true",
+        "adults": "1",
+        "children": "0",
+        "infants": "0",
+        "selectedclass1": "economy",
+        "currency": "CNY",
+        "mon": "true",
+        "channel": "DESKTOP",
+        "origin1": "PVG",
+        "destination1": "NRT",
+        "departuredate1": f"2025-05-{i}"
+    }
+    response = requests.get(url, headers=headers, cookies=cookies, params=params,
+                            timeout=15,
+                            verify=False,
+                            # proxies=proxies
+                            # allow_redirects=False
+                            http_version=2
+
+                            )
+
+    # print(response.text)
+    print(response)
+
+
+    from lxml import etree
+    import json
+
+    html = etree.HTML(response.text)
+    data = html.xpath("//script[@id='bundle-data-v2']/text()")[0] if html.xpath(
+        "//script[@id='bundle-data-v2']/text()") else '{}'
+    json_data = json.loads(data)
+    print(json_data)
+
+
+for i in range(9, 31):
+    req(i)

Vissa filer visades inte eftersom för många filer har ändrats