diff --git a/common.py b/common.py index 7a30d87..21fbd7b 100644 --- a/common.py +++ b/common.py @@ -7,7 +7,8 @@ def format_dictionary_to_string(data): for key, value in data.items(): if isinstance(value, list) or isinstance(value, dict): formatted_string_parts.append( - f"{quote(key)}={quote(json.dumps(value, separators=(',', ':'), ensure_ascii=False))}") + f"{quote(key)}={quote(json.dumps(value, separators=(',', ':'), ensure_ascii=False))}" + ) else: formatted_string_parts.append(f"{quote(key)}={quote(str(value))}") diff --git a/config.py b/config.py index 8a649d5..aaa6620 100644 --- a/config.py +++ b/config.py @@ -4,7 +4,7 @@ # 获取图标文件的路径 def get_application_path(): - if getattr(sys, 'frozen', False): + if getattr(sys, "frozen", False): application_path = sys._MEIPASS else: application_path = os.path.dirname(os.path.abspath(__file__)) @@ -12,6 +12,6 @@ def get_application_path(): return application_path -cookies_config_path = os.path.join(get_application_path(), 'cookies.json') +cookies_config_path = os.path.join(get_application_path(), "cookies.json") issue_please_text = " (如果还无法解决, 请提交issue到仓库, 十分感谢)" sleep_seconds = 1 diff --git a/main.py b/main.py index 975b973..c2330a9 100644 --- a/main.py +++ b/main.py @@ -1,518 +1,34 @@ -import inspect -import json -import logging -import os -import sys -import time -from datetime import datetime -from urllib.parse import urlencode +from loguru import logger import gradio as gr -import qrcode -from common import format_dictionary_to_string -from config import cookies_config_path -from util.BiliRequest import BiliRequest -from util.error import errnoDict -from util.order_qrcode import get_qrcode_url +from tab.go import go_tab +from tab.settings import setting_tab +from tab.train import train_tab -buyer_value = [] -addr_value = [] -ticket_value = [] -isRunning = False -gt = "" -challenge = "" -geetest_validate = "" -geetest_seccode = "" +header = """ +# B 站会员购抢票🌈 -# test_geetest_validate = "" -# test_geetest_seccode = "" +⚠️此项目仅用于个人参考学习,切勿进行盈利,所造成的后果与本人无关。 +""" +short_js = """ + + +""" -def onSubmitTicketId(num): - global buyer_value - global addr_value - global ticket_value +if __name__ == "__main__": + logger.add("app_{time}.log") - try: - num = int(num) - _request = BiliRequest(cookies_config_path=cookies_config_path) - res = _request.get( - url=f"https://show.bilibili.com/api/ticket/project/getV2?version=134&id={num}&project_id={num}") - ret = res.json() - logging.info(ret) - - ticket_str_list = [] - project_id = ret["data"]["id"] - project_name = ret["data"]["name"] - project_start_time_unix = ret["data"]["start_time"] - project_end_time_unix = ret["data"]["end_time"] - project_start_time = datetime.fromtimestamp(project_start_time_unix).strftime("%Y-%m-%d %H:%M:%S") - project_end_time = datetime.fromtimestamp(project_end_time_unix).strftime("%Y-%m-%d %H:%M:%S") - venue_info = ret["data"]["venue_info"] - venue_name = venue_info["name"] - venue_address = venue_info["address_detail"] - for screen in ret["data"]["screen_list"]: - screen_name = screen["name"] - screen_id = screen["id"] - for ticket in screen["ticket_list"]: - ticket_desc = ticket['desc'] - ticket_price = ticket['price'] - - ticket["screen"] = screen_name - ticket["screen_id"] = screen_id - ticket_can_buy = "可购买" if ticket['clickable'] else "无法购买" - ticket_str = f"{screen_name} - {ticket_desc} - ¥{ticket_price / 100} - {ticket_can_buy}" - ticket_str_list.append(ticket_str) - ticket_value.append({"project_id": project_id, "ticket": ticket}) - - buyer_json = _request.get( - url=f"https://show.bilibili.com/api/ticket/buyer/list?is_default&projectId={project_id}").json() - logging.info(buyer_json) - addr_json = _request.get(url="https://show.bilibili.com/api/ticket/addr/list").json() - logging.info(addr_json) - - buyer_str_list = [f"{item['name']}-{item['personal_id']}" for item in buyer_json["data"]["list"]] - buyer_value = [item for item in buyer_json["data"]["list"]] - addr_str_list = [f"{item['addr']}-{item['name']}-{item['phone']}" for item in addr_json["data"]["addr_list"]] - addr_value = [item for item in addr_json["data"]["addr_list"]] - - return [gr.update(choices=ticket_str_list), gr.update(choices=buyer_str_list), - gr.update(choices=buyer_str_list), gr.update(choices=addr_str_list), gr.update(visible=True), - gr.update( - value=f"获取票信息成功:\n展会名称: {project_name}\n开展时间: {project_start_time} - {project_end_time}\n" - f"场馆地址: {venue_name} {venue_address}", - visible=True)] - except Exception as e: - return [gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(value=e, visible=True)] - - -def onSubmitAll(ticket_number, ticket_info, people, people_buyer, address): - try: - if ticket_number != len(people): - return gr.update(value="生成配置文件失败,保证选票数目和购买人数目一致", visible=True) - ticket_cur = ticket_value[ticket_info] - people_cur = [buyer_value[item] for item in people] - people_buyer_cur = buyer_value[people_buyer] - - address_cur = addr_value[address] - config_dir = {"count": ticket_number, "screen_id": ticket_cur["ticket"]["screen_id"], - "project_id": ticket_cur["project_id"], "sku_id": ticket_cur["ticket"]["id"], "order_type": 1, - "buyer_info": people_cur, "buyer": people_buyer_cur["name"], "tel": people_buyer_cur["tel"], - "deliver_info": {"name": address_cur["name"], "tel": address_cur["phone"], - "addr_id": address_cur["id"], - "addr": address_cur["prov"] + address_cur["city"] + address_cur["area"] + - address_cur["addr"]}} - return gr.update(value=json.dumps(config_dir), visible=True) - except Exception as e: - logging.info(e) - return gr.update(value="生成错误,仔细看看你可能有哪里漏填的", visible=True) - - -def start_go(tickets_info_str, time_start, interval, mode, total_attempts): - global isRunning, geetest_validate, geetest_seccode - global gt - global challenge - result = "" - request_result = {"errno": "未知状态码", "msg": "配置文件有错"} - isRunning = True - left_time = total_attempts - - while isRunning: - try: - if time_start != '': - time_difference = datetime.strptime(time_start, "%Y-%m-%dT%H:%M").timestamp() - time.time() - if time_difference > 0: - logging.info(f'等待中') - yield [gr.update(value="等待中", visible=True), gr.update(visible=False), gr.update(), gr.update(), - gr.update(), gr.update()] - time.sleep(time_difference) # 等待到指定的开始时间 - tickets_info = json.loads(tickets_info_str) - _request = BiliRequest(cookies_config_path=cookies_config_path) - token_payload = {"count": tickets_info["count"], "screen_id": tickets_info["screen_id"], "order_type": 1, - "project_id": tickets_info["project_id"], "sku_id": tickets_info["sku_id"], "token": "", - "newRisk": True} - request_result_normal = _request.post( - url=f"https://show.bilibili.com/api/ticket/order/prepare?project_id={tickets_info['project_id']}", - data=token_payload) - request_result = request_result_normal.json() - logging.info(f"prepare header: {request_result_normal.headers}") - logging.info(f"prepare: {request_result}") - - code = int(request_result["code"]) - ## https://github.com/fsender/Bilibili_show_ticket_auto_order/blob/18b3cf6cb539167153f1d2dd847006c9794ac9af/api.py#L237 - if code == -401: - _url = "https://api.bilibili.com/x/gaia-vgate/v1/register" - _payload = urlencode(request_result["data"]["ga_data"]["riskParams"]) - _data = _request.post(_url, _payload).json() - gt = _data["data"]["geetest"]["gt"] - challenge = _data["data"]["geetest"]["challenge"] - token = _data["data"]["token"] - # https://passport.bilibili.com/x/passport-login/captcha?source=main_web - # challenge = "7e4a9557299685fb82c41972b63a42fc" - # gt = "ac597a4506fee079629df5d8b66dd4fe" - yield [gr.update(value="进行验证码验证", visible=True), gr.update(), gr.update(), - gr.update(visible=True), gr.update(value=gt), gr.update(value=challenge)] - while geetest_validate == "" or geetest_seccode == "": - continue - logging.info(f"geetest_validate: {geetest_validate},geetest_seccode: {geetest_seccode}") - _url = "https://api.bilibili.com/x/gaia-vgate/v1/validate" - csrf = _request.cookieManager.get_cookies_value("bili_jct") - - _payload = { - "challenge": challenge, - "token": token, - "seccode": geetest_seccode, - "csrf": csrf, - "validate": geetest_validate - } - _data = _request.post(_url, urlencode(_payload)).json() - geetest_validate = "" - geetest_seccode = "" - if _data["code"] == 0: - logging.info("极验GeeTest认证 成功") - else: - logging.info(f"极验GeeTest验证失败。 {_data}") - yield [gr.update(value="极验GeeTest验证失败。重新验证", visible=True), gr.update(), gr.update(), - gr.update(), - gr.update(), gr.update()] - continue - request_result = _request.post( - url=f"https://show.bilibili.com/api/ticket/order/prepare?project_id={tickets_info['project_id']}", - data=token_payload).json() - tickets_info["token"] = request_result["data"]["token"] - request_result = _request.get( - url=f"https://show.bilibili.com/api/ticket/order/confirmInfo?token={tickets_info['token']}&voucher=&project_id={tickets_info['project_id']}").json() - logging.info(f"confirmInfo: {request_result}") - tickets_info["pay_money"] = request_result["data"]["pay_money"] - tickets_info["timestamp"] = int(time.time()) * 100 - payload = format_dictionary_to_string(tickets_info) - request_result = _request.post( - url=f"https://show.bilibili.com/api/ticket/order/createV2?project_id={tickets_info['project_id']}", - data=payload).json() - errno = int(request_result["errno"]) - left_time_str = '无限' if mode == 0 else left_time - logging.info( - f'错误码:{errno} 错误码解析: {errnoDict.get(errno, "未知错误码")}, 请求体: {request_result} 剩余次数: {left_time_str}') - yield [gr.update( - value=f"正在抢票,具体情况查看终端控制台。\n 剩余次数: {left_time_str} 当前状态码: {errno}, 当前错误信息:{errnoDict.get(errno, '未知错误码')}", - visible=True), gr.update(visible=True), gr.update(), gr.update(), gr.update(), gr.update()] - if errno == 0: - qrcode_url = get_qrcode_url(_request, request_result["data"]["token"], tickets_info['project_id'], - request_result["data"]['orderId']) - qr_gen = qrcode.QRCode() - qr_gen.add_data(qrcode_url) - qr_gen.make(fit=True) - qr_gen_image = qr_gen.make_image() - yield [gr.update(value="生成付款二维码"), gr.update(), - gr.update(value=qr_gen_image.get_image(), visible=True), gr.update(), gr.update(), - gr.update()] - time.sleep(interval / 1000.0) - if mode == 1: - left_time -= 1 - if left_time <= 0: - break - except Exception as e: - errno = request_result["errno"] - left_time_str = '无限' if mode == 0 else left_time - frame_info = inspect.stack()[0] - filename = frame_info.filename - line_number = frame_info.lineno - logging.info("An error occurred in file '%s' at line %d: %s", filename, line_number, e) - logging.info( - f'错误码:{errno} 错误码解析: {errnoDict.get(errno, "未知错误码")}, 请求体: {request_result},剩余次数: {left_time_str}') - yield [ - gr.update(value=f"错误, 错误码:{errno} 错误码解析: {errnoDict.get(errno, '未知错误码')}", visible=True), - gr.update(visible=False), gr.update(), gr.update(), gr.update(), gr.update()] - time.sleep(interval / 1000.0) - yield [gr.update(value="抢票结束", visible=True), gr.update(visible=False), gr.update(), gr.update(), - gr.update(), gr.update()] - - -def configure_global_logging(): - application_path = os.path.dirname(os.path.abspath(__file__)) - if hasattr(sys, "_MEIPASS"): - application_path = os.path.dirname(os.path.abspath(sys.argv[0])) - global_logger = logging.getLogger() - global_logger.setLevel(logging.INFO) - log_file_path = os.path.join(application_path, 'app.log') - file_handler = logging.FileHandler(log_file_path) - formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') - file_handler.setFormatter(formatter) - global_logger.addHandler(file_handler) - - -if __name__ == '__main__': - configure_global_logging() - short_js = """ - - """ with gr.Blocks(head=short_js) as demo: - gr.HTML(""" - - - - - Welcome to My GitHub - - - -
-

B站会员购抢票🌈

-

⚠️此项目仅用于个人参考学习,切勿进行盈利,所造成的后果与本人无关。

-
- - """) - with gr.Tab("配置") as setting_tab: - info_ui = gr.TextArea(info="此窗口为输出信息", label="输出信息", interactive=False, visible=False) - with gr.Column() as first: - ticket_id_ui = gr.Textbox(label="票ID", interactive=True, - info="例如:要抢的网址是https://show.bilibili.com/platform/detail.html?id=84096\n" - "就要填写 84096 ") - ticket_id_btn = gr.Button("提交票id") - with gr.Column(visible=False) as inner: - with gr.Row(): - ticket_number_ui = gr.Number(label="票数目", value=1) - ticket_info_ui = gr.Dropdown(label="选票", interactive=True, type="index") - with gr.Row(): - people_ui = gr.CheckboxGroup(label="实名人", interactive=True, type="index", - info="用于身份证实名认证,请确保曾经在b站填写过购买人(哔哩哔哩客户端-会员购-个人中心-购票人信息)的实名信息,否则这个表单不会有任何信息") - people_buyer_ui = gr.Dropdown(label="联系人", interactive=True, type="index", - info="选一个作为联系人,请确保曾经在b站填写过购买人的实名信息,否则这个表单不会有任何信息") - address_ui = gr.Dropdown(label="地址", interactive=True, type="index", - info="请确保曾经在b站填写过地址,否则这个表单不会有任何信息") - - config_btn = gr.Button("生成配置") - config_output_ui = gr.Textbox(label="生成配置文件", show_copy_button=True, info="右上角粘贴", - visible=False) - config_btn.click(fn=onSubmitAll, - inputs=[ticket_number_ui, ticket_info_ui, people_ui, people_buyer_ui, address_ui], - outputs=config_output_ui, ) - - ticket_id_btn.click(fn=onSubmitTicketId, inputs=ticket_id_ui, - outputs=[ticket_info_ui, people_ui, people_buyer_ui, address_ui, inner, info_ui]) - - with gr.Tab("抢票") as go_tab: - with gr.Column() as second: - ticket_ui = gr.TextArea(label="填入配置", info="再次填入配置信息", interactive=True) - time_html = gr.HTML("""
- """, label="选择抢票的时间", show_label=True) - - with gr.Row(): - interval_ui = gr.Number(label="抢票间隔", value=1000, minimum=1, - info="设置抢票任务之间的时间间隔(单位:毫秒),建议不要设置太小") - mode_ui = gr.Radio(label="抢票模式", choices=["无限", "有限"], value="无限", - info="选择抢票的模式", - type="index", interactive=True) - total_attempts_ui = gr.Number(label="总过次数", value=100, minimum=1, info="设置抢票的总次数", - visible=False) - - mode_ui.change(fn=lambda x: gr.update(visible=True) if x == 1 else gr.update(visible=False), - inputs=[mode_ui], outputs=total_attempts_ui) - with gr.Row(): - go_btn = gr.Button("开始抢票") - stop_btn = gr.Button("停止", visible=False) - - with gr.Row(): - go_ui = gr.TextArea(info="此窗口为临时输出,具体请见控制台", label="输出信息", interactive=False, - visible=False, - show_copy_button=True, max_lines=10) - qr_image = gr.Image(label="使用微信或者支付宝扫码支付", visible=False) - - with gr.Row(visible=False) as gt_row: - gt_html_btn = gr.Button("点击打开抢票验证码(请勿多点!!)") - gt_html_finish_btn = gr.Button("完成验证码后点此此按钮") - - gt_html = gr.HTML(value=""" -
- -
-
-
""", label="验证码") - # data - time_tmp = gr.Textbox(visible=False) - geetest_validate_ui = gr.Textbox(visible=False) - geetest_seccode_ui = gr.Textbox(visible=False) - gt_ui = gr.Textbox(visible=False) - challenge_ui = gr.Textbox(visible=False) - - gt_html_finish_btn.click(None, None, geetest_validate_ui, - js='() => {return captchaObj.getValidate().geetest_validate}') - gt_html_finish_btn.click(None, None, geetest_seccode_ui, - js='() => {return captchaObj.getValidate().geetest_seccode}') - - - def update_geetest_validate(x): - global geetest_validate - geetest_validate = x - - - def update_geetest_seccode(x): - global geetest_seccode - geetest_seccode = x - - - geetest_validate_ui.change(fn=update_geetest_validate, inputs=geetest_validate_ui, outputs=None) - geetest_seccode_ui.change(fn=update_geetest_seccode, inputs=geetest_seccode_ui, outputs=None) - - gt_html_btn.click(fn=None, inputs=[gt_ui, challenge_ui], outputs=None, - js=f"""(x,y) => {{ initGeetest({{ - gt: x, - challenge: y, - offline: false, - new_captcha: true, - product: "popup", - width: "300px", - https: true - }}, function (captchaObj) {{ - window.captchaObj = captchaObj; - $('#captcha').empty(); - captchaObj.appendTo('#captcha'); - }})}}""") - - go_btn.click(fn=None, inputs=None, outputs=time_tmp, - js='(x) => {return (document.getElementById("datetime")).value;}') - - - def stop(): - global isRunning - isRunning = False - return [gr.update(value="抢票结束", visible=True), gr.update(visible=False), - gr.update(), gr.update()] - - - go_btn.click(fn=start_go, inputs=[ticket_ui, time_tmp, interval_ui, mode_ui, total_attempts_ui], - outputs=[go_ui, stop_btn, qr_image, gt_row, gt_ui, challenge_ui], ) - stop_btn.click(fn=stop, inputs=None, outputs=[go_ui, stop_btn, qr_image, gt_row], ) - with gr.Tab("训练你的验证码速度") as train_taq: - _request = BiliRequest(cookies_config_path=cookies_config_path) - gr.HTML(""" -
-

💪 在这里训练一下手过验证码的速度,提前演练一下

-
""") - test_go_btn = gr.Button("开始测试") - test_gt = "" - test_token = "" - test_csrf = "" - test_challenge = "" - test_geetest_validate = "" - test_geetest_seccode = "" - - - def test_go(): - global test_csrf - global test_gt - global test_challenge - global test_token - global test_geetest_validate - global test_geetest_seccode - test_res = _request.get("https://passport.bilibili.com/x/passport-login/captcha?source=main_web").json() - test_challenge = test_res["data"]["geetest"]["challenge"] - test_gt = test_res["data"]["geetest"]["gt"] - test_token = test_res["data"]["token"] - test_csrf = _request.cookieManager.get_cookies_value("bili_jct") - test_geetest_validate = "" - test_geetest_seccode = "" - return [gr.update(value=test_gt), gr.update(value=test_challenge), gr.update(visible=True), - gr.update(value="重新生成")] - - - short_js = """ - - """ - test_log = gr.TextArea(label="测试结果", info="描述当前的情况,验证码过期是正常现象") - with gr.Row(visible=False) as test_gt_row: - test_gt_html_start_btn = gr.Button("点击打开抢票验证码(请勿多点!!)") - test_gt_html_finish_btn = gr.Button("完成验证码后点此此按钮") - test_gt_html = gr.HTML(value=""" -
- -
-
-
""", label="验证码") - test_gt_ui = gr.Textbox(label="gt", visible=True) - test_challenge_ui = gr.Textbox(label="challenge", visible=True) - test_go_btn.click(fn=test_go, inputs=None, - outputs=[test_gt_ui, test_challenge_ui, test_gt_row, test_go_btn]) - test_gt_html_start_btn.click(fn=None, inputs=[test_gt_ui, test_challenge_ui], outputs=None, - js=f"""(x,y) => {{ initGeetest({{ - gt: x, - challenge: y, - offline: false, - new_captcha: true, - product: "popup", - width: "300px", - https: true - }}, function (test_captchaObj) {{ - window.test_captchaObj = test_captchaObj; - $('#captcha_test').empty(); - test_captchaObj.appendTo('#captcha_test'); - }})}}""") - test_geetest_validate_ui = gr.Textbox(label="validate", visible=True) - test_geetest_seccode_ui = gr.Textbox(label="eccode", visible=True) - test_gt_html_finish_btn.click(None, None, test_geetest_validate_ui, - js='() => {return test_captchaObj.getValidate().geetest_validate}') - test_gt_html_finish_btn.click(None, None, test_geetest_seccode_ui, - js='() => {return test_captchaObj.getValidate().geetest_seccode}') - - - def test_doing(): - while test_geetest_validate == "" or test_geetest_seccode == "": - continue - _url = "https://api.bilibili.com/x/gaia-vgate/v1/validate" - _payload = { - "challenge": test_challenge, - "token": test_token, - "seccode": test_geetest_seccode, - "csrf": test_csrf, - "validate": test_geetest_validate - } - test_data = _request.post(_url, urlencode(_payload)) - yield gr.update(value=test_data.json()) - - - test_gt_html_finish_btn.click(fn=test_doing, outputs=[test_log]) - - - def test_update_geetest_validate(x): - global test_geetest_validate - test_geetest_validate = x - - - def test_update_geetest_seccode(x): - global test_geetest_seccode - test_geetest_seccode = x - - - test_geetest_validate_ui.change(fn=test_update_geetest_validate, inputs=test_geetest_validate_ui, - outputs=None) - test_geetest_seccode_ui.change(fn=test_update_geetest_seccode, inputs=test_geetest_seccode_ui, outputs=None) - # 运行应用 + gr.Markdown(header) + with gr.Tab("配置"): + setting_tab() + with gr.Tab("抢票"): + go_tab() + with gr.Tab("训练你的验证码速度"): + train_tab() # 运行应用 print("点击下面的网址运行程序 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓") diff --git a/requirements.txt b/requirements.txt index be4099d..6d30530 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ -pyttsx3~=2.90 selenium~=4.9.0 requests~=2.31.0 -tkcalendar~=1.6.1 setuptools~=65.5.1 gradio~=4.27.0 -qrcode~=7.4.2 \ No newline at end of file +qrcode~=7.4.2 +loguru \ No newline at end of file diff --git a/tab/go.py b/tab/go.py new file mode 100644 index 0000000..1862fb3 --- /dev/null +++ b/tab/go.py @@ -0,0 +1,330 @@ +from datetime import datetime +import json +import time +from loguru import logger +import qrcode +from urllib.parse import urlencode +import gradio as gr + +from common import format_dictionary_to_string +from config import cookies_config_path +from util.bili_request import BiliRequest +from util.error import ERRNO_DICT +from util.order_qrcode import get_qrcode_url + + +isRunning = False +gt = "" +challenge = "" +geetest_validate = "" +geetest_seccode = "" + +def start_go(tickets_info_str, time_start, interval, mode, total_attempts): + global isRunning, geetest_validate, geetest_seccode + global gt + global challenge + request_result = {"errno": "未知状态码", "msg": "配置文件有错"} + isRunning = True + left_time = total_attempts + + while isRunning: + try: + if time_start != "": + time_difference = ( + datetime.strptime(time_start, "%Y-%m-%dT%H:%M").timestamp() + - time.time() + ) + if time_difference > 0: + logger.info("等待中") + yield [ + gr.update(value="等待中", visible=True), + gr.update(visible=False), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + ] + time.sleep(time_difference) # 等待到指定的开始时间 + tickets_info = json.loads(tickets_info_str) + _request = BiliRequest(cookies_config_path=cookies_config_path) + token_payload = { + "count": tickets_info["count"], + "screen_id": tickets_info["screen_id"], + "order_type": 1, + "project_id": tickets_info["project_id"], + "sku_id": tickets_info["sku_id"], + "token": "", + "newRisk": True, + } + request_result_normal = _request.post( + url=f"https://show.bilibili.com/api/ticket/order/prepare?project_id={tickets_info['project_id']}", + data=token_payload, + ) + request_result = request_result_normal.json() + logger.info(f"prepare header: {request_result_normal.headers}") + logger.info(f"prepare: {request_result}") + + code = int(request_result["code"]) + ## https://github.com/fsender/Bilibili_show_ticket_auto_order/blob/18b3cf6cb539167153f1d2dd847006c9794ac9af/api.py#L237 + if code == -401: + _url = "https://api.bilibili.com/x/gaia-vgate/v1/register" + _payload = urlencode(request_result["data"]["ga_data"]["riskParams"]) + _data = _request.post(_url, _payload).json() + gt = _data["data"]["geetest"]["gt"] + challenge = _data["data"]["geetest"]["challenge"] + token = _data["data"]["token"] + # https://passport.bilibili.com/x/passport-login/captcha?source=main_web + # challenge = "7e4a9557299685fb82c41972b63a42fc" + # gt = "ac597a4506fee079629df5d8b66dd4fe" + yield [ + gr.update(value="进行验证码验证", visible=True), + gr.update(), + gr.update(), + gr.update(visible=True), + gr.update(value=gt), + gr.update(value=challenge), + ] + while geetest_validate == "" or geetest_seccode == "": + continue + logger.info( + f"geetest_validate: {geetest_validate},geetest_seccode: {geetest_seccode}" + ) + _url = "https://api.bilibili.com/x/gaia-vgate/v1/validate" + csrf = _request.cookieManager.get_cookies_value("bili_jct") + + _payload = { + "challenge": challenge, + "token": token, + "seccode": geetest_seccode, + "csrf": csrf, + "validate": geetest_validate, + } + _data = _request.post(_url, urlencode(_payload)).json() + geetest_validate = "" + geetest_seccode = "" + if _data["code"] == 0: + logger.info("极验 GeeTest 验证成功") + else: + logger.info("极验 GeeTest 验证失败 {}", _data) + yield [ + gr.update(value="极验 GeeTest 验证失败。重新验证", visible=True), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + ] + continue + request_result = _request.post( + url=f"https://show.bilibili.com/api/ticket/order/prepare?project_id={tickets_info['project_id']}", + data=token_payload, + ).json() + tickets_info["token"] = request_result["data"]["token"] + request_result = _request.get( + url=f"https://show.bilibili.com/api/ticket/order/confirmInfo?token={tickets_info['token']}&voucher=&project_id={tickets_info['project_id']}" + ).json() + logger.info(f"confirmInfo: {request_result}") + tickets_info["pay_money"] = request_result["data"]["pay_money"] + tickets_info["timestamp"] = int(time.time()) * 100 + payload = format_dictionary_to_string(tickets_info) + request_result = _request.post( + url=f"https://show.bilibili.com/api/ticket/order/createV2?project_id={tickets_info['project_id']}", + data=payload, + ).json() + errno = int(request_result["errno"]) + left_time_str = "无限" if mode == 0 else left_time + logger.info( + f'状态码: {errno}({ERRNO_DICT.get(errno, "未知错误码")}), 请求体: {request_result} 剩余次数: {left_time_str}' + ) + yield [ + gr.update( + value=f"正在抢票,具体情况查看终端控制台。\n剩余次数: {left_time_str} 当前状态码: {errno}({ERRNO_DICT.get(errno, "未知错误码")})", + visible=True, + ), + gr.update(visible=True), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + ] + if errno == 0: + qrcode_url = get_qrcode_url( + _request, + request_result["data"]["token"], + tickets_info["project_id"], + request_result["data"]["orderId"], + ) + qr_gen = qrcode.QRCode() + qr_gen.add_data(qrcode_url) + qr_gen.make(fit=True) + qr_gen_image = qr_gen.make_image() + yield [ + gr.update(value="生成付款二维码"), + gr.update(), + gr.update(value=qr_gen_image.get_image(), visible=True), + gr.update(), + gr.update(), + gr.update(), + ] + time.sleep(interval / 1000.0) + if mode == 1: + left_time -= 1 + if left_time <= 0: + break + except Exception as e: + # errno = request_result["errno"] + # left_time_str = '无限' if mode == 0 else left_time + # frame_info = inspect.stack()[0] + # filename = frame_info.filename + # line_number = frame_info.lineno + # logger.info("An error occurred in file '%s' at line %d: %s", filename, line_number, e) + logger.exception(e) + # logger.info( + # f'错误码: {errno}({ERRNO_DICT.get(errno, "未知错误码")}), 请求体: {request_result}, 剩余次数: {left_time_str}') + # yield [ + # gr.update(value=f"错误, 错误码:{errno} 错误码解析: {ERRNO_DICT.get(errno, '未知错误码')}", visible=True), + # gr.update(visible=False), gr.update(), gr.update(), gr.update(), gr.update()] + # time.sleep(interval / 1000.0) + yield [ + gr.update(value="抢票结束", visible=True), + gr.update(visible=False), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + ] +def go_tab(): + with gr.Column(): + ticket_ui = gr.TextArea( + label="填入配置", info="再次填入配置信息", interactive=True + ) + gr.HTML( + """
+ """, + label="选择抢票的时间", + show_label=True, + ) + + with gr.Row(): + interval_ui = gr.Number( + label="抢票间隔", + value=1000, + minimum=1, + info="设置抢票任务之间的时间间隔(单位:毫秒),建议不要设置太小", + ) + mode_ui = gr.Radio( + label="抢票模式", + choices=["无限", "有限"], + value="无限", + info="选择抢票的模式", + type="index", + interactive=True, + ) + total_attempts_ui = gr.Number( + label="总过次数", + value=100, + minimum=1, + info="设置抢票的总次数", + visible=False, + ) + + mode_ui.change( + fn=lambda x: gr.update(visible=True) + if x == 1 + else gr.update(visible=False), + inputs=[mode_ui], + outputs=total_attempts_ui, + ) + with gr.Row(): + go_btn = gr.Button("开始抢票") + stop_btn = gr.Button("停止", visible=False) + + with gr.Row(): + go_ui = gr.TextArea( + info="此窗口为临时输出,具体请见控制台", + label="输出信息", + interactive=False, + visible=False, + show_copy_button=True, + max_lines=10, + ) + qr_image = gr.Image(label="使用微信或者支付宝扫码支付", visible=False) + + with gr.Row(visible=False) as gt_row: + gt_html_btn = gr.Button("点击打开抢票验证码(请勿多点!!)") + gt_html_finish_btn = gr.Button("完成验证码后点此此按钮") + + gr.HTML( + value=""" +
+ +
+
+
""", + label="验证码", + ) + + time_tmp = gr.Textbox(visible=False) + gt_ui = gr.Textbox(visible=False) + challenge_ui = gr.Textbox(visible=False) + gt_html_btn.click( + fn=None, + inputs=[gt_ui, challenge_ui], + outputs=None, + js=""" + (gt, challenge) => initGeetest({ + gt, challenge, + offline: false, + new_captcha: true, + product: "popup", + width: "300px", + https: true + }, function (captchaObj) { + window.captchaObj = captchaObj; + $('#captcha').empty(); + captchaObj.appendTo('#captcha'); + }) + """, + ) + + geetest_result = gr.JSON() + gt_html_finish_btn.click( + fn=None, + inputs=None, + outputs=geetest_result, + js="() => captchaObj.getValidate()", + ) + def receive_geetest_result(res): + global geetest_validate, geetest_seccode + geetest_validate = res["geetest_validate"] + geetest_seccode = res["geetest_seccode"] + geetest_result.change(fn=receive_geetest_result, inputs=geetest_result) + + + go_btn.click( + fn=None, + inputs=None, + outputs=time_tmp, + js='(x) => document.getElementById("datetime").value', + ) + + def stop(): + global isRunning + isRunning = False + return [ + gr.update(value="抢票结束", visible=True), + gr.update(visible=False), + gr.update(), + gr.update(), + ] + + go_btn.click( + fn=start_go, + inputs=[ticket_ui, time_tmp, interval_ui, mode_ui, total_attempts_ui], + outputs=[go_ui, stop_btn, qr_image, gt_row, gt_ui, challenge_ui], + ) + stop_btn.click( + fn=stop, + inputs=None, + outputs=[go_ui, stop_btn, qr_image, gt_row], + ) \ No newline at end of file diff --git a/tab/settings.py b/tab/settings.py new file mode 100644 index 0000000..16efbde --- /dev/null +++ b/tab/settings.py @@ -0,0 +1,208 @@ +from datetime import datetime +import json +from loguru import logger +import gradio as gr + +from config import cookies_config_path +from util.bili_request import BiliRequest + +buyer_value = [] +addr_value = [] +ticket_value = [] + + +def on_submit_ticket_id(num): + global buyer_value + global addr_value + global ticket_value + + try: + num = int(num) + bili_request = BiliRequest(cookies_config_path=cookies_config_path) + res = bili_request.get( + url=f"https://show.bilibili.com/api/ticket/project/getV2?version=134&id={num}&project_id={num}" + ) + ret = res.json() + logger.debug(ret) + + data = ret["data"] + ticket_str_list = [] + + project_id = data["id"] + project_name = data["name"] + + project_start_time = datetime.fromtimestamp(data["start_time"]).strftime( + "%Y-%m-%d %H:%M:%S" + ) + project_end_time = datetime.fromtimestamp(data["end_time"]).strftime( + "%Y-%m-%d %H:%M:%S" + ) + + venue_info = data["venue_info"] + venue_name = venue_info["name"] + venue_address = venue_info["address_detail"] + + for screen in data["screen_list"]: + screen_name = screen["name"] + screen_id = screen["id"] + for ticket in screen["ticket_list"]: + ticket_desc = ticket["desc"] + ticket_price = ticket["price"] + + ticket["screen"] = screen_name + ticket["screen_id"] = screen_id + ticket_can_buy = "可购买" if ticket["clickable"] else "无法购买" + ticket_str = f"{screen_name} - {ticket_desc} - ¥{ticket_price / 100} - {ticket_can_buy}" + ticket_str_list.append(ticket_str) + ticket_value.append({"project_id": project_id, "ticket": ticket}) + + buyer_json = bili_request.get( + url=f"https://show.bilibili.com/api/ticket/buyer/list?is_default&projectId={project_id}" + ).json() + logger.debug(buyer_json) + addr_json = bili_request.get( + url="https://show.bilibili.com/api/ticket/addr/list" + ).json() + logger.debug(addr_json) + + buyer_value = buyer_json["data"]["list"] + buyer_str_list = [ + f"{item['name']}-{item['personal_id']}" for item in buyer_value + ] + addr_value = addr_json["data"]["addr_list"] + addr_str_list = [ + f"{item['addr']}-{item['name']}-{item['phone']}" for item in addr_value + ] + + return [ + gr.update(choices=ticket_str_list), + gr.update(choices=buyer_str_list), + gr.update(choices=buyer_str_list), + gr.update(choices=addr_str_list), + gr.update(visible=True), + gr.update( + value=f"获取票信息成功:\n展会名称:{project_name}\n" + f"开展时间:{project_start_time} - {project_end_time}\n场馆地址:{venue_name} {venue_address}", + visible=True, + ), + ] + except Exception as e: + return [ + gr.update(), + gr.update(), + gr.update(), + gr.update(), + gr.update(), + gr.update(value=e, visible=True), + ] + + +def on_submit_all(ticket_info, people_indices, people_buyer_index, address_index): + try: + # if ticket_number != len(people_indices): + # return gr.update( + # value="生成配置文件失败,保证选票数目和购买人数目一致", visible=True + # ) + ticket_cur = ticket_value[ticket_info] + people_cur = [buyer_value[item] for item in people_indices] + people_buyer_cur = buyer_value[people_buyer_index] + + address_cur = addr_value[address_index] + config_dir = { + "count": len(people_indices), + "screen_id": ticket_cur["ticket"]["screen_id"], + "project_id": ticket_cur["project_id"], + "sku_id": ticket_cur["ticket"]["id"], + "order_type": 1, + "buyer_info": people_cur, + "buyer": people_buyer_cur["name"], + "tel": people_buyer_cur["tel"], + "deliver_info": { + "name": address_cur["name"], + "tel": address_cur["phone"], + "addr_id": address_cur["id"], + "addr": address_cur["prov"] + + address_cur["city"] + + address_cur["area"] + + address_cur["addr"], + }, + } + return gr.update(value=json.dumps(config_dir), visible=True) + except Exception as e: + logger.info(e) + return gr.update(value="生成错误,仔细看看你可能有哪里漏填的", visible=True) + + +def setting_tab(): + info_ui = gr.TextArea( + info="此窗口为输出信息", label="输出信息", interactive=False, visible=False + ) + with gr.Column(): + ticket_id_ui = gr.Textbox( + label="票 ID", + interactive=True, + info="例如:要抢的网址是 https://show.bilibili.com/platform/detail.html?id=84096 就要填写 84096", + ) + ticket_id_btn = gr.Button("获取票信息") + with gr.Column(visible=False) as inner: + with gr.Row(): + people_ui = gr.CheckboxGroup( + label="身份证实名认证", + interactive=True, + type="index", + info="在哔哩哔哩客户端-会员购-个人中心-购票人信息中添加", + ) + ticket_info_ui = gr.Dropdown( + label="选票", + interactive=True, + type="index", + info="此处的「无法购买」仅代表当前状态", + ) + with gr.Row(): + people_buyer_ui = gr.Dropdown( + label="联系人", + interactive=True, + type="index", + info="与实名认证同样在「购票人信息」中添加", + ) + address_ui = gr.Dropdown( + label="地址", + interactive=True, + type="index", + info="会员购收货地址", + ) + + config_btn = gr.Button("生成配置") + # config_output_ui = gr.Textbox( + # label="生成配置文件", + # show_copy_button=True, + # info="右上角粘贴", + # visible=False, + # ) + config_output_ui = gr.JSON( + label="生成配置文件(右上角复制)", + visible=False, + ) + config_btn.click( + fn=on_submit_all, + inputs=[ + ticket_info_ui, + people_ui, + people_buyer_ui, + address_ui, + ], + outputs=config_output_ui, + ) + + ticket_id_btn.click( + fn=on_submit_ticket_id, + inputs=ticket_id_ui, + outputs=[ + ticket_info_ui, + people_ui, + people_buyer_ui, + address_ui, + inner, + info_ui, + ], + ) diff --git a/tab/train.py b/tab/train.py new file mode 100644 index 0000000..5f921e3 --- /dev/null +++ b/tab/train.py @@ -0,0 +1,106 @@ +from urllib.parse import urlencode +import gradio as gr + +from config import cookies_config_path +from util.bili_request import BiliRequest + + +def train_tab(): + _request = BiliRequest(cookies_config_path=cookies_config_path) + + gr.Markdown("💪 在这里训练一下手过验证码的速度,提前演练一下") + test_get_challenge_btn = gr.Button("开始测试") + test_log = gr.JSON(label="测试结果(验证码过期是正常现象)") + + with gr.Row(visible=False) as test_gt_row: + test_gt_html_start_btn = gr.Button("点击打开抢票验证码(请勿多点!!)") + test_gt_html_finish_btn = gr.Button("完成验证码后点此此按钮") + gr.HTML( + value=""" +
+ +
+
+ """, + label="验证码", + ) + test_gt_ui = gr.Textbox(label="gt", visible=True) + test_challenge_ui = gr.Textbox(label="challenge", visible=True) + geetest_result = gr.JSON(label="validate") + + def test_get_challenge(): + global \ + test_challenge, \ + test_gt, \ + test_token, \ + test_csrf, \ + test_geetest_validate, \ + test_geetest_seccode + test_res = _request.get( + "https://passport.bilibili.com/x/passport-login/captcha?source=main_web" + ).json() + test_challenge = test_res["data"]["geetest"]["challenge"] + test_gt = test_res["data"]["geetest"]["gt"] + test_token = test_res["data"]["token"] + test_csrf = _request.cookieManager.get_cookies_value("bili_jct") + test_geetest_validate = "" + test_geetest_seccode = "" + return [ + gr.update(value=test_gt), # test_gt_ui + gr.update(value=test_challenge), # test_challenge_ui + gr.update(visible=True), # test_gt_row + gr.update(value="重新生成"), # test_get_challenge_btn + ] + + test_get_challenge_btn.click( + fn=test_get_challenge, + inputs=None, + outputs=[test_gt_ui, test_challenge_ui, test_gt_row, test_get_challenge_btn], + ) + test_gt_html_start_btn.click( + fn=None, + inputs=[test_gt_ui, test_challenge_ui], + outputs=None, + js=""" + (gt, challenge) => initGeetest({ + gt, challenge, + offline: false, + new_captcha: true, + product: "popup", + width: "300px", + https: true + }, function (test_captchaObj) { + window.test_captchaObj = test_captchaObj; + $('#captcha_test').empty(); + test_captchaObj.appendTo('#captcha_test'); + }) + """, + ) + + test_gt_html_finish_btn.click( + fn=None, + inputs=None, + outputs=geetest_result, + js="() => test_captchaObj.getValidate()", + ) + def receive_geetest_result(res): + global test_geetest_validate, test_geetest_seccode + test_geetest_validate = res["geetest_validate"] + test_geetest_seccode = res["geetest_seccode"] + geetest_result.change(fn=receive_geetest_result, inputs=geetest_result) + + def test_doing(): + while test_geetest_validate == "" or test_geetest_seccode == "": + continue + _url = "https://api.bilibili.com/x/gaia-vgate/v1/validate" + _payload = { + "challenge": test_challenge, + "token": test_token, + "seccode": test_geetest_seccode, + "csrf": test_csrf, + "validate": test_geetest_validate, + } + test_data = _request.post(_url, urlencode(_payload)) + yield gr.update(value=test_data.json()) + + test_gt_html_finish_btn.click(fn=test_doing, outputs=[test_log]) diff --git a/util/JsonUtil.py b/util/JsonUtil.py deleted file mode 100644 index 161a51f..0000000 --- a/util/JsonUtil.py +++ /dev/null @@ -1,30 +0,0 @@ -import json - - -class ProjectInfo: - def __init__(self, data): - self.data = data["data"] - - def get_name(self): - return self.data["name"] - - def get_screen_list(self): - return self.data["screen_list"] - - def get_ticket_info(self): - raw_list = self.data["screen_list"] - - -class ProfileInfo: - def __init__(self, data): - self.personList = data["data"]["list"] - - def get_persons(self): - return self.personList - -class AddrInfo: - def __init__(self, data): - self.addrList = data["data"]["addr_list"] - - def get_addrs(self): - return self.addrList \ No newline at end of file diff --git a/util/BiliRequest.py b/util/bili_request.py similarity index 51% rename from util/BiliRequest.py rename to util/bili_request.py index cd598d2..0580881 100644 --- a/util/BiliRequest.py +++ b/util/bili_request.py @@ -1,6 +1,6 @@ import requests -from util.configUtil import CookieManager +from util.config_util import CookieManager class BiliRequest: @@ -9,26 +9,26 @@ def __init__(self, headers=None, cookies=None, cookies_config_path=""): self.cookieManager = CookieManager(cookies_config_path) self._cookies = self.cookieManager.get_cookies_str() self.headers = headers or { - 'authority': 'show.bilibili.com', - 'accept': '*/*', - 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5,ja;q=0.4', - 'cookie': self._cookies, - 'referer': "https://show.bilibili.com/", - 'content-type': 'application/x-www-form-urlencoded', - 'sec-ch-ua': '"Microsoft Edge";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', - '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/119.0.0.0 Safari/537.36 Edg/119.0.0.0' + "authority": "show.bilibili.com", + "accept": "*/*", + "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5,ja;q=0.4", + "cookie": self._cookies, + "referer": "https://show.bilibili.com/", + "content-type": "application/x-www-form-urlencoded", + "sec-ch-ua": '"Microsoft Edge";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', + "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/119.0.0.0 Safari/537.36 Edg/119.0.0.0", } def get(self, url, data=None): response = self.session.get(url, data=data, headers=self.headers) response.raise_for_status() if response.json().get("msg", "") == "请先登录": - self.headers['cookies'] = self.cookieManager.get_cookies_str_force() + self.headers["cookies"] = self.cookieManager.get_cookies_str_force() self.get(url, data) return response @@ -36,13 +36,15 @@ def post(self, url, data=None): response = self.session.post(url, data=data, headers=self.headers) response.raise_for_status() if response.json().get("msg", "") == "请先登录": - self.headers['cookies'] = self.cookieManager.get_cookies_str_force() + self.headers["cookies"] = self.cookieManager.get_cookies_str_force() self.post(url, data) return response -if __name__ == '__main__': +if __name__ == "__main__": payload = {} _request = BiliRequest(cookies_config_path="../config/cookies.json") - res = _request.get(url="https://show.bilibili.com/api/ticket/project/get?version=134&id=77938&project_id=77938") + res = _request.get( + url="https://show.bilibili.com/api/ticket/project/get?version=134&id=77938&project_id=77938" + ) print(res.json()["data"]) diff --git a/util/configUtil.py b/util/config_util.py similarity index 63% rename from util/configUtil.py rename to util/config_util.py index 2de2065..5c6b992 100644 --- a/util/configUtil.py +++ b/util/config_util.py @@ -1,40 +1,43 @@ import json -import logging import time +import requests -from requests import utils +from loguru import logger from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait -logging.basicConfig(level=logging.INFO) # 设置日志级别 - class CookieManager: def __init__(self, config_file_path): self.config = {} self.config_file_path = config_file_path - self.cookie_jar = utils.cookiejar_from_dict(self.config) + self.cookie_jar = requests.utils.cookiejar_from_dict(self.config) - def _login_and_save_cookies(self, login_url="https://show.bilibili.com/platform/home.html"): - logging.info("启动浏览器中.....") + @logger.catch + def _login_and_save_cookies( + self, login_url="https://show.bilibili.com/platform/home.html" + ): + logger.info("启动浏览器中.....") try: - self.driver = webdriver.Edge() - except Exception as e: + self.driver = webdriver.Chrome() + except Exception: try: self.driver = webdriver.Chrome() - except Exception as e: - raise Exception("没有找到浏览器驱动,请根据自己的浏览器下载相应的驱动:\n" - "相关教程:https://blog.csdn.net/zz00008888/article/details/127903475\n" - "Edge: https://liushilive.github.io/github_selenium_drivers/md/IE.html\n" - "Chrome:https://liushilive.github.io/github_selenium_drivers/md/Chrome.html\n") + except Exception: + raise Exception( + "没有找到浏览器驱动,请根据自己的浏览器下载相应的驱动:\n" + "相关教程:https://blog.csdn.net/zz00008888/article/details/127903475\n" + "Edge: https://liushilive.github.io/github_selenium_drivers/md/IE.html\n" + "Chrome:https://liushilive.github.io/github_selenium_drivers/md/Chrome.html\n" + ) self.wait = WebDriverWait(self.driver, 0.5) self.driver.get(login_url) self.driver.maximize_window() time.sleep(1) self.driver.find_element(By.CLASS_NAME, "nav-header-register").click() - logging.info("浏览器启动, 进行登录.") + logger.info("浏览器启动, 进行登录.") while True: try: self.driver.find_element(By.CLASS_NAME, "nav-header-register") @@ -42,17 +45,20 @@ def _login_and_save_cookies(self, login_url="https://show.bilibili.com/platform/ break time.sleep(1) self.config["bilibili_cookies"] = self.driver.get_cookies() - with open(self.config_file_path, 'w') as f: - json.dump(self.config, f, indent=4) + self.dump_config() self.driver.quit() - logging.info("登录成功, 浏览器退出.") + logger.info("登录成功, 浏览器退出.") return self.config["bilibili_cookies"] + def dump_config(self): + with open(self.config_file_path, "w") as f: + json.dump(self.config, f, indent=4) + def get_cookies(self): try: - with open(self.config_file_path, 'r') as f: + with open(self.config_file_path, "r") as f: self.config = json.load(f) - except Exception as e: + except Exception: return self._login_and_save_cookies() if self.config == {}: @@ -85,4 +91,4 @@ def get_cookies_str_force(self): if __name__ == "__main__": cookie_manager = CookieManager("../config/cookies.json") - logging.info(str(cookie_manager.get_cookies_str())) + logger.info(str(cookie_manager.get_cookies_str())) diff --git a/util/error.py b/util/error.py index 75aa881..670eab7 100644 --- a/util/error.py +++ b/util/error.py @@ -1,5 +1,5 @@ # 欢迎补充错误码 -errnoDict = { +ERRNO_DICT = { 3: "速度过快,请慢一点", 100009: "库存不足,暂无余票", 100001: "无票", diff --git a/util/order_qrcode.py b/util/order_qrcode.py index a0f2cf1..d7f5325 100644 --- a/util/order_qrcode.py +++ b/util/order_qrcode.py @@ -2,8 +2,9 @@ def get_qrcode_url(_request, token, project_id, order_id): - url = "https://show.bilibili.com/api/ticket/order/createstatus?token=" + token + "×tamp=" + str( - int(round(time.time() * 1000))) + "&project_id=" + str(project_id) + "&orderId=" + str(order_id) + url = f"https://show.bilibili.com/api/ticket/order/createstatus?token={token}" + f"×tamp={int(round(time.time() * 1000))}" + f"&project_id={project_id}&orderId={order_id}" data = _request.get(url).json() if data["errno"] == 0: return data["data"]["payParam"]["code_url"] diff --git a/util/webUtil.py b/util/webUtil.py deleted file mode 100644 index f7612f5..0000000 --- a/util/webUtil.py +++ /dev/null @@ -1,25 +0,0 @@ -import json -import logging -import threading -import time - -from selenium import webdriver -from selenium.webdriver.support.ui import WebDriverWait - - -class WebUtil: - def __init__(self, cookie_dict): - self.initialized_event = threading.Event() - - initialization_thread = threading.Thread(target=self.initialize, args=(cookie_dict,)) - initialization_thread.start() - - def initialize(self, cookie_dict): - self.driver = webdriver.Edge() - self.driver.get("https://show.bilibili.com/platform/home.html") - - for cookie in cookie_dict["bilibili_cookies"]: - self.driver.add_cookie(cookie) - self.driver.refresh() - self.wait = WebDriverWait(self.driver, 0.5) - self.initialized_event.set()