python大麦抢票脚本_抢不到票?你离idol只差一个大麦抢票脚本。

20200816更新Olivia Wang:大麦脚本更新,辅助选座功能上线​zhuanlan.zhihu.comOlivia Wang:我要认真写脚本教程啦​zhuanlan.zhihu.com看完这个 Chat,人人都可以完成浏览器自动化​gitbook.cn

我不知道为什么js脚本总是刷新一下就停了,干脆更新了脚本。Olivia Wang:我知道你们又在找抢周杰伦演唱会门票的脚本了​zhuanlan.zhihu.com

热门演唱会门票不到一分钟就可能卖光,不知道要多快的手速才能一鼓作气点点点及时下单。走一下神可能就不得不选个差一点的区域,甚至只能高价求票了。

好朋友遇到了这样的烦恼,我一想这种比较机械的刷新其实很适合用脚本完成呀,所以就花了一个下午有了这个脚本。

目前还是比较有局限性的:稳定性没有100%保证,如果是很重要的票可能一边开着电脑用脚本,一边自己用手机刷新更保险一些,做好两手准备

需要手动在脚本中修改人数

只支持大麦演唱会,不支持歌剧话剧,比赛等

不支持选座

需要事先登录好,填好相关的地址,人员信息

UI太粗糙啦

根据自己和小伙伴的测试来看,如果是火到大麦会崩的演唱会(比如今天开票的张艺兴上海演唱会),那么有了脚本还是一样听天由命。没有这么夸张的使用起来暂时没问题。

如果你想直接使用现成的脚本 → 从安装Tampermonkey到成功抢到演唱会门票

如果你对怎么写脚本感兴趣 → 怎么写一个抢票脚本

从安装Tampermonkey到成功抢到演唱会门票

建议用Chrome浏览器使用这个脚本因为我就是在Chrome写的,其他浏览器没怎么测试,大家试用后有什么问题可以给我留言提意见反馈。

Tampermonkey可以很方便的开关脚本是否运行,抢完票后记得从Tampermonkey关掉脚本,不然浏览其他表演信息可能直接进入支付宝付账界面。

使用步骤

1. 用Chrome浏览器打开Tampermonkey官网,点击按钮下载安装

2. 关注公众号「伪装程序大佬」(wzcxdl_cs),发送dmtk取得脚本地址

3. 通过地址打开greasy fork的页面,点击安装按钮自动跳转到Tampermonkey

4. 点击安装按钮

5. 打开大麦网的页面,现在应该就可以看到按钮和提示了

6. 根据提示修改「大麦抢票-选场次票价人数」中people_num为相应人数

7. 刷新页面加载新版脚本

8. 点击想要的场次,票价

9. 点击“开始抢票”

10.等待提示音响起

11.支付宝付款

12.抢票成功~

如果报错

1. 可以打开开发者工具,如果报错一般是因为加载速度有点慢,可以适当放慢页面刷新速度或者换成更快的网络。

2. 如果出错建议运行前先清除localStorage中的isRunning。然后重新加载页面。

怎么写一个抢票脚本

开始前的准备:安装浏览器,比较推荐Chrome

安装Tampermonkey (详情见「从安装Tampermonkey到成功抢到演唱会门票」)

知道一点JavaScript

看看大麦网演唱会的网页是什么结构

观察大麦网购票流程

随便选一个演唱会页面看看。

观察大麦网演唱会购买网页我们可以发现当演唱会有票的时候,我们可以选择场次,选择票档,选择数量,点击「立即购买」(上图是预定票所以是「立即预订」),然后会跳转到确认页面,需要我们选择地址,观演人,支付方式然后按下按钮进行预订。如果只有一个默认地址,在确认页面实际需要我们做的只是点击选中观演人然后提交订单。

当票已经卖光或者还没有开始销售的时候按钮上的文字是「提交缺货登记」,「提交开售登记」,并且没有选择数量的地方。

思考抢票脚本流程用户登录,填写地址,观演人信息

用户手动点击选择场次,票档 (为什么没有数量?因为需要抢票的页面没有选择数量的地方),在脚本中修改数量

用户点击「开始抢票」,脚本读取当前选择的场次,票档,

刷新页面,脚本点击相应场次,票档

检查有没有调节数量的控件出现,如果没有,回到4

根据脚本中数量调成数量控件

检查购买按钮上是否是「立即购买」字样,如果不是,回到4

点击「立即购买」按钮,跳转到确认页面

选择观演人

点击「同意以上协议并提交订单」 (同时发出声音提醒用户)

支付宝付款

成功抢到票~

需要我们写的是2-10的部分。Tampermonkey会根据url判断执行什么脚本,所以我们可以写两个文件。

大麦抢票-选场次票价人数 2-8

大麦抢票-确认 9-10

具体写法

大麦抢票-确认

从逻辑上来讲应该先写「大麦抢票-选场次票价人数」,但是「大麦抢票-确认」简单很多。所以先写这部分吧。

点击新建之后会出现一个模版文件。不要删掉上方的注释,非常重要。

// ==UserScript==// @name New Userscript// @namespace http://tampermonkey.net/// @version 0.1// @description try to take over the world!// @author You// @match https://www.example.com// @grant none// ==/UserScript==

具体每个字段的含义可以查询Tampermonkey官网。

// ==UserScript==// @name 大麦抢票-确认// @namespace https://www.jwang0614.top/scripts// @version 0.1// @description 辅助购买大麦网演唱会门票// @author Olivia Wang// @match https://buy.damai.cn/orderConfirm*// @grant none// ==/UserScript==

对我们来说最重要的是@match。其他@name,@description之类怎么填对我们要写的这个脚本执行都没有太大影响。@namespace是用来在@name相同时区分脚本的,可以用任何独特字符串,不过一般用自己个人主页url的比较多。

@match的重点是最后的*号通配符,这样只要url前面包含https://buy.damai.cn/orderConfirm, 无论Confirm之后跟的是什么有多长都能匹配上。不同网页的脚本@match的字符所规定的匹配规则会有变化。

具体代码:

(function() {

'use strict';

console.log("confirm");

// 点击观演人 var person = document.querySelector('#confirmOrder_1 > div.dm-ticket-buyer > div.ticket-buyer-select > div.next-row.next-row-no-padding.buyer-list > div > label > span.next-checkbox.isFirefox > span');

if (person) {

person.click();

}

// 播放提示音 var audio = new Audio("http://audio.marsupialgurgle.com/audio/successtrumpet.mp3");

audio.play();

// 提交订单 document.querySelector('#confirmOrder_1 > div.submit-wrapper > button').click();

})();

虽然应该先成功提交再放庆祝提示音,但是点击提交后页面就跳转到支付宝了,所以这里是先播放提示音再点击提交订单。

有的确认页不需要选择观演人,所以要做个判断,不然在这一步会报错。

querySelector的那一长串直接用Chrome的开发者工具就可以获得:

点击红框中的按钮,然后在页面中点击选中你需要查看的元素,html中相关的元素会高亮显示。右键相应的html元素,选择复制selector,就可以得到那一长串字符了。

用document.querySelector就可以获取相应元素。

需要注意的是有些页面中元素会有变化,比如多一个少一个场次或者多一个少一个div什么的,直接复制的selector字符串可能含有类似:nth-child(6)的部分,这个数字可能会有变化,需要找到更加有普遍性的写法。比如根据有唯一classname的sibling节点定位之类的,大家可以多检查一下看看不同状态不同网页上selector是不是都能适用。

大麦抢票-选场次票价人数

我们可以把这个脚本分成几个部分UI开始抢票按钮

结束抢票按钮

提示

从页面获取用户输入场次票价

刷新

根据用户输入填入数据

判断能不能购买,如果可以点击按钮,如果不行再次刷新

LocalStorage

我们希望能刷新后保存用户场次票价人数信息,所以用到LocalStorage。

var people_num = 2;

var isRunning = false;

var storage = window.localStorage;

storage.setItem("people_num", people_num);

storage.setItem("isRunning", isRunning);

还没开票的页面也没有数量控件,所以通过脚本控制购票数量,储存到LocalStorage中。isRunning用来判断是不是在运行。

有的浏览器可能不太支持LocalStorage,可以在程序最开始判断一下.

if(!window.localStorage){

alert('不支持这个浏览器,请换成Chrome或者Safari。');

}

UI

添加两个固定在页面上的按钮和一个提示栏。比如「开始抢票」按钮

// 创建一个p标签var start = document.createElement("P");

// 添加文字start.appendChild(document.createTextNode("开始抢票"));

// 设置格式,位置start.style.lineheight="50px";

start.style.color="white";

start.style.fontSize="30px";

start.style.padding="10px 20px";

start.style.background="green";

start.style.position="fixed";

start.style.right="30px";

start.style.top="100px";

// 保持在最上方start.style.zIndex="10000";

// 获取dom中body元素var container = document.querySelector('body');

// 将start按钮添加到dom中container.appendChild(start);

从页面获取用户选择的场次,票价信息

function get_numbers_from_page() {

var event_selections = document.querySelectorAll('body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div.perform__order__select.perform__order__select__performs > div.select_right > div > div');

// 这里就用了sibling node定位 div.perform__desc__info + div // “+ div” 代表下一个div sibling var price_selections = document.querySelectorAll('body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div.perform__desc__info + div > div.select_right > div > div');

for (var i= 0;i < event_selections.length;i++) {

// 通过class中是否含有active判断用户选择的是第几个选项,将结果数字保存在本地存储中 if (event_selections[i].classList.contains("active")) {

storage.setItem("event_ele_num", i);

}

}

for (var j= 0;j < price_selections.length;j++) {

if (price_selections[j].classList.contains("active")) {

storage.setItem("price_ele_num", j);

}

}

}

一段时间后刷新页面

function timedRefresh(timeoutPeriod) {

window.setTimeout("location.reload(true);",timeoutPeriod);

}

填写数据,判断当前能不能购买

function set_up_check_page() {

// 从storage中获取场次,票价,数量信息 var event_ele_num = storage.getItem("event_ele_num");

var price_ele_num = storage.getItem("price_ele_num");

var people_num = storage.getItem("people_num");

// 为了更直观地表现出“程序正在运行”,我把网页背景换了一个颜色 if (storage.getItem("isRunning") == "true") {

document.querySelector('body > div.perform').style.background="darksalmon";

}

// 获取所有的场次元素,点击相应元素选择 var event_selections = document.querySelectorAll('body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div.perform__order__select.perform__order__select__performs > div.select_right > div > div');

event_selections[event_ele_num].click();

var price_selections = document.querySelectorAll('body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div.perform__desc__info + div > div.select_right > div > div');

price_selections[price_ele_num].click();

// 判断有没有数量控件,如果有设定数量,如果没有继续刷新 var people_selection = document.querySelector(".cafe-c-input-number-input");

if (people_selection) {

// 这里我用的是点击增加按钮,其实可以通过修改value的值实现 var people_inc_btn = document.querySelector('body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div:nth-child(6) > div.number_right > div > div > a.cafe-c-input-number-handler.cafe-c-input-number-handler-up');

for (var i =1; i < people_num; i++) {

people_inc_btn.click();

}

// 判断有没有“立即购买“按钮 var btn = document.querySelector("body > div.perform > div > div.flex1 > div.hd > div > div.order > div.perform__order__box > div:last-child > div");

if (btn) {

if (btn.innerText == "立即购买") {

// 点击立即购买按钮跳转到确认页 storage.removeItem("isRunning");

storage.removeItem("price_ele_num");

storage.removeItem("event_ele_num");

storage.removeItem("people_num");

storage.clear();

btn.click();

}

}

}

// 如果正在抢票,0.4秒后刷新页面 if (storage.getItem("isRunning") == "true") {

timedRefresh(400);

}

}

通过按钮控制脚本的开始和停止

// 开始抢票按钮start.onclick = function() {

console.log('开始抢票!');

document.querySelector('body > div.perform').style.background="darksalmon";

storage.setItem("isRunning", true);

get_numbers_from_page();

timedRefresh(600);

};

// 停止抢票按钮stop.onclick = function() {

alert('停止抢票!');

document.querySelector('body > div.perform').style.background="white";

//storage.setItem("isRunning", false); storage.removeItem("isRunning");

};

因为怕刷新太快来不及按「停止抢票」,我加入了快捷键。每个字母的keyCode可以在网上找到。

document.onkeydown = function() {

var oEvent = window.event;

if (oEvent.keyCode == 69 && oEvent.ctrlKey) {

//alert("你按下了ctrl+E"); // start start.click();

}else if (oEvent.keyCode == 84 && oEvent.ctrlKey) {

//alert("你按下了ctrl+T"); // stop stop.click();

}

}

刷新

function reload_page() {

// console.log("reload"); window.setTimeout(set_up_check_page,800);

}

组合

将以上内容补全完整组合到一起就可以啦,完整的代码请关注公众号「伪装程序大佬」(wzcxdl_cs),输入dmtk获取下载地址。

现在代码已经更新了一些,具体更新了什么请看下篇文章,不过答题思路是没什么变化的。

有什么问题和意见欢迎大家在下面给我留言~如果脚本运行出了什么问题也可以告诉我,我看看能不能改一改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值