杭州亚运会余篇筛选

查看 47|回复 2
作者:天空宫阙   
杭州亚运会余篇筛选
不是抢票!不是抢票!不是抢票!
杭州亚运会的官方售票网站是 https://ticket.hangzhou2022.cn/
但是似乎没有筛选余票的功能,所有项目都标着可选座但是点进去却没有票,好烦,因此有了这个小项目。
核心判断逻辑是筛选 soldOut为False allowChooseSeat为True的项目存入Excel中
2023年9月27日晚的余票情况,按道理热门票已经没有了,但似乎部分项目有少量票会在比赛开始前几天才放出


Snipaste_2023-09-27_20-53-53.png (103.78 KB, 下载次数: 0)
下载附件
2023-9-27 20:54 上传

使用方法
安装依赖
pip install -r requirements.txt
运行
python ticket_hangzhou.py
运行后会生成 余票情况.xlsx 筛选left_num 大于1的项目即为有余票的项目
不准确的情况
本程序的核心判断逻辑是筛选 soldOut为False allowChooseSeat为True的项目
# 筛选soldOut为False allowChooseSeat为True的项目
if (not event['soldOut']) and event['allowChooseSeat']:
    seat_lefts.append(event['eventName'])
对于暂不可售的情况可能存在误判  
源码
github地址 https://github.com/skygongque/Spider/tree/master/24-%E6%9D%AD%E5%B7%9E%E4%BA%9A%E8%BF%90%E4%BC%9A%E4%BD%99%E7%A5%A8%E6%9F%A5%E8%AF%A2
ticket_hangzhou.py
import execjs
from functools import partial
import subprocess
import requests
import time
import json
import pandas as pd
import numpy as np
from tqdm import tqdm
subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")
with open('sign.js','r') as f:
    jscode = f.read()
ctx = execjs.compile(jscode)
def get_index(page):
    params = {
        'sortType' :'2',
        'page': str(page),
        'pageSize' :'36',
        'langType': '1'
    }
    url = 'https://gtpapi.hangzhou2022.cn/rest/guide/project/list/queryList' # sortType=2&page=2&pageSize=36&langType=1
    ts,sign = get_ts_sign(params)
    payload = {}
    headers = {
        'authority': 'gtpapi.hangzhou2022.cn',
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
        # 'cookie': 'cna=l/mlG/R1Q10CAXrugBH3OgNY; xlly_s=1; _trs_uv=lmzusca5_4982_edl7; Hm_lvt_9095c4973fefa1f89e883fab90d1ff1e=1695704684; Hm_lpvt_9095c4973fefa1f89e883fab90d1ff1e=1695704684; MZCONSUMERJSESSIONID17481=TICKETMZGTP0ac9530cad2040be80dba6b70a509337; XSRF-TOKEN=9190242d-76f0-4e26-9c9f-a0b52a55225e; isg=BKKiVM-kM-_9-C7MxI7PYLO98ygE86YNwPmUmuwbgZRsvzk51IKgHYR56_tDrx6l',
        'origin': 'https://ticket.hangzhou2022.cn',
        'referer': 'https://ticket.hangzhou2022.cn/',
        'sign': sign,
        'site': 'pc',
        'siteversion': 'standard',
        'timestamp': str(ts),
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
    }
    response = requests.get(url,params=params, headers=headers, data=payload)
    response.raise_for_status
    return response.json()
def parse_index(res_json):
    dataList = res_json['data']['projectPager']['dataList']
    projectId_list = [item['projectId'] for item in dataList]
    return projectId_list
def get_detail(params):
    url = "https://gtpapi.hangzhou2022.cn/rest/guide/project/detail/query" # ?projectId=216990009&langType=1
    ts,sign = get_ts_sign(params)
    payload = {}
    headers = {
        'authority': 'gtpapi.hangzhou2022.cn',
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
        # 'cookie': 'cna=l/mlG/R1Q10CAXrugBH3OgNY; xlly_s=1; _trs_uv=lmzusca5_4982_edl7; Hm_lvt_9095c4973fefa1f89e883fab90d1ff1e=1695704684; Hm_lpvt_9095c4973fefa1f89e883fab90d1ff1e=1695704684; MZCONSUMERJSESSIONID17481=TICKETMZGTP0ac9530cad2040be80dba6b70a509337; XSRF-TOKEN=9190242d-76f0-4e26-9c9f-a0b52a55225e; isg=BKKiVM-kM-_9-C7MxI7PYLO98ygE86YNwPmUmuwbgZRsvzk51IKgHYR56_tDrx6l',
        'origin': 'https://ticket.hangzhou2022.cn',
        'referer': 'https://ticket.hangzhou2022.cn/',
        'sign': sign,
        'site': 'pc',
        'siteversion': 'standard',
        'timestamp': str(ts),
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
    }
    response = requests.get(url,params=params, headers=headers, data=payload)
    response.raise_for_status
    return response.json()
def parse(res_json):
    data = res_json['data']
    projectId = data['projectId']
    projectName = data['projectName']
    # print(projectId,projectName)
    seat_lefts = []
    eventList = data['eventList']
    for event in eventList:
        # print(event['allowChooseSeat'])
        if (not event['soldOut']) and event['allowChooseSeat']: # 筛选soldOut为False allowChooseSeat为True的
            seat_lefts.append(event['eventName'])
    if len(seat_lefts) > 0:
        return {
            'projectId':projectId,
            'projectName':projectName,
            'left_num':len(seat_lefts),
            'seat_lefts':seat_lefts
        }
def get_ts_sign(u):
    """ 签名 """
    u = json.dumps(u)
    ts = int(time.time() * 1000) -91
    sign = ctx.call('get_sign',ts,u)
    return ts,sign
def main():
    # res_json = get_detail({'projectId':'216707002','langType':'1'})
    # left_info = parse(res_json)
    print('正在进行爬取请耐心等待....')
    all_projectId_list = []
    result = []
    for page in range(1,4): # 索引页一共就三页
        res_index = get_index(page)
        projectId_list = parse_index(res_index)
        all_projectId_list += projectId_list
    all_projectId_list = list(set(all_projectId_list))
    print(all_projectId_list)
    for projectId in tqdm(all_projectId_list):
        res_json = get_detail({'projectId':str(projectId),'langType':'1'})
        left_info = parse(res_json)
        if left_info:
            result.append(left_info)
        time.sleep(1)
        # break
    df = pd.DataFrame(result)
    df.to_excel('余票情况.xlsx')
    print('余票情况已存入 余票情况.xlsx')
if __name__ == "__main__":
    main()
sign.js
function h(t) {
    function e(t) {
        function e(t, e) {
            return t >> 32 - e
        }
        function r(t, e) {
            var r, n, o, i, a;
            return o = 2147483648 & t,
            i = 2147483648 & e,
            r = 1073741824 & t,
            n = 1073741824 & e,
            a = (1073741823 & t) + (1073741823 & e),
            r & n ? 2147483648 ^ a ^ o ^ i : r | n ? 1073741824 & a ? 3221225472 ^ a ^ o ^ i : 1073741824 ^ a ^ o ^ i : a ^ o ^ i
        }
        function n(t, e, r) {
            return t & e | ~t & r
        }
        function o(t, e, r) {
            return t & r | e & ~r
        }
        function i(t, e, r) {
            return t ^ e ^ r
        }
        function a(t, e, r) {
            return e ^ (t | ~r)
        }
        function c(t, o, i, a, c, u, s) {
            return t = r(t, r(r(n(o, i, a), c), s)),
            r(e(t, u), o)
        }
        function u(t, n, i, a, c, u, s) {
            return t = r(t, r(r(o(n, i, a), c), s)),
            r(e(t, u), n)
        }
        function s(t, n, o, a, c, u, s) {
            return t = r(t, r(r(i(n, o, a), c), s)),
            r(e(t, u), n)
        }
        function l(t, n, o, i, c, u, s) {
            return t = r(t, r(r(a(n, o, i), c), s)),
            r(e(t, u), n)
        }
        function p(t) {
            var e, r = t.length, n = r + 8, o = (n - n % 64) / 64, i = 16 * (o + 1), a = Array(i - 1), c = 0, u = 0;
            while (u >> 29,
            a
        }
        function h(t) {
            var e, r, n = "", o = "";
            for (r = 0; r >> 8 * r & 255,
                o = "0".concat(e.toString(16)),
                n += o.substr(o.length - 2, 2);
            return n
        }
        function f(t) {
            t = t.replace(/\r\n/g, "\n");
            for (var e = "", r = 0; r  127 && n > 6 | 192),
                e += String.fromCharCode(63 & n | 128)) : (e += String.fromCharCode(n >> 12 | 224),
                e += String.fromCharCode(n >> 6 & 63 | 128),
                e += String.fromCharCode(63 & n | 128))
            }
            return e
        }
        var d, v, y, g, m, _, w, b, x, O = [], L = 7, j = 12, E = 17, S = 22, k = 5, P = 9, C = 14, I = 20, N = 4, T = 11, G = 16, F = 23, A = 6, D = 10, M = 15, B = 21;
        for (t = f(t),
        O = p(t),
        _ = 1732584193,
        w = 4023233417,
        b = 2562383102,
        x = 271733878,
        d = 0; d  -1)
            return String(t);
        if (null === t)
            return "null";
        var n = JSON.parse(JSON.stringify(t))
          , o = Object.keys(n).sort()
          , i = "[object array]" === Object.prototype.toString.call(n).toLowerCase()
          , a = i ? [] : {};
        return o.forEach((t=>{
            if ("[object object]" === Object.prototype.toString.call(n[t]).toLowerCase())
                i ? a.push(r(n[t])) : a[t] = r(n[t]);
            else if ("[object array]" === Object.prototype.toString.call(n[t]).toLowerCase()) {
                var e = n[t].map((t=>r(t)));
                i ? a.push(e) : a[t] = e
            } else
                null === n[t] ? i ? a.push("null") : a[t] = "null" : i ? a.push(n[t].toString()) : a[t] = n[t].toString()
        }
        )),
        a
    }
    t.data = t.data || {},
    "string" === typeof t.data ? t.data = JSON.parse(t.data) : t.data = JSON.parse(JSON.stringify(t.data)),
    t.t = t.t || (new Date).getTime().toString();
    var n = r(t.data);
    return "[object object]" === Object.prototype.toString.call(n).toLowerCase() ? n[t.headerName] = String(t.t) : "[object array]" === Object.prototype.toString.call(n).toLowerCase() ? n.push(String(t.t)) : n += String(t.t),
    e(JSON.stringify(n))
}
var f = h;
function get_sign(ts,u){
    // var a = Number((new Date).getTime()) + Number(-91);
    // querySearchTerm=true&sortType=2&page=1&pageSize=36&langType=1
    // var u = {
    //     "querySearchTerm": true,
    //     "sortType": 2,
    //     "page": 1,
    //     "pageSize": 36,
    //     "langType": "1"
    // }
    var a = Number(ts);
    u = JSON.parse(u);
    var result = f({
        data: u,
        t: a,
        headerName: "timestamp"
    });
    return result;
}
// console.log(a)
// console.log(result)

情况, 项目

id1995   

压箱底的果然最后出场啊,女足值得一看男足是个代名词不说也罢
moruye   

支持原创,刚好捣鼓捣鼓
您需要登录后才可以回帖 登录 | 立即注册

返回顶部