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获取下载地址。

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

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

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

  1. python可视化拖拽平台_【技术解码】不用控制器,只拖拽模型面就可以做动画!很好玩的动画工具...

    文章转自公众号: cg世界 前两天在B站上看到一个有意思的视频,是新一代动画模型绑定控制技术的功能展示,小编看过之后挺好奇,就到网上找了一些相关介绍,想和小伙伴们分享一下. 这款3D动画软件名为Rum ...

  2. python实现链表的删除_删除链表中的元素,但是只能使用一个指针

    先用使用常规方法,两个指针: golang实现: type Node struct {value intnext *Node}type Link struct {head *Nodetail *Nod ...

  3. python发牌代码十点半_深夜十点半(一)——我的第一个Python程序“登录系统”...

    系统设计要求: (1)可以输入用户名和密码 (2)密码要密文显示 (3)输错三次要锁定对应的用户 首先,我们来完成要求1,设计一个可以输入用户名和密码的界面,输入正确或错误进行提示. _usernam ...

  4. 你距离家只差一个刷票脚本而已——12306刷票脚本升级版

    马上就要回家了,票还没有.你是否用到了我去年发布的刷票脚本呢.传送门~ 我也在刷票,不过发现12306还是发生了一些变化,在使用过程中,发现会自动退出登录.所以对脚本做了一些改动.顺便加了一些新的功能 ...

  5. linux实现命令解释器_想在Win10上安装Linux,只需一个命令即可实现

    尽管在Windows 10上,安装用于Linux 2的Windows子系统并不困难,但它需要很多步骤,如果你还想将WSL2设置为默认值,则需要更多步骤.但是,在将来的版本中,微软致力于简化安装过程,以 ...

  6. qtcreator下拉列表怎么制作_设置EXCEL动态下拉菜单,只需要一个组合键,新手也能快速掌握...

    操作版本:OFFICE365 在EXCEL制作一级下拉菜单有4种方法,你掌握几种?一文中,我提到了一级下拉菜单的制作方法,其中用公式法来制作下拉菜单可以实现内容增减后下拉菜单的内容也自动增减,这个方法 ...

  7. 你距离女朋友其实只差一个幽默的句子,python教你如何快速将有趣的句子收归数据库

    你可曾看见过这样的句子: "我爱的人也爱着我,对我来说这简直是个奇迹." 又或者是: "生活中若没有朋友,就像生活中没有阳光一样." 再或者这样: " ...

  8. 磁盘不见了只剩一个c盘_无损分区后 磁盘分区不见了只剩一个系统分区怎么办?...

    为了写经验,试试无损分区方法,原D盘80G,原C盘50G,计划把D盘中的10G容量分配给C盘,用的是DiskGenius分区软件,按软件的教程进行分区大小调整后,重新进入电脑,发现只剩一个分区了(主分 ...

  9. python数组重复数据去重_JS实现数组去重(重复的元素只保留一个)

    1.遍历数组法 它是最简单的数组去重方法(indexOf方法) 实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中: var arr=[,,,,,, ...

  10. Oracle、Mysql数据库编程开发基本操作命令语法脚本_基础篇(入门级)

    Oracle.Mysql数据库开发基本操作命令语法脚本_基础篇(入门级) 文章目录 Oracle.Mysql数据库开发基本操作命令语法脚本_基础篇(入门级) 一.数据库中常用的字段类型 二.操作数据库 ...

最新文章

  1. Thrift的服务器和客户端Python案例
  2. Python 数据类型
  3. python按概率输出分类结果_sklearn例程:多分类输出概率
  4. iOS开发之时间格式的转化
  5. SAP CDS view自学教程之九:cube view和query view的实现原理
  6. SAP ABAP实用技巧介绍系列之 ABAP XSLT 定义变量
  7. 江苏信息考试access_软考 信息处理技术员备考复习攻略
  8. 【渝粤教育】国家开放大学2018年春季 8622-22T社会调查研究与方法 参考试题
  9. 如何将 Linux 系统转移至 LVM 卷
  10. 精通 TensorFlow 1.x 中文版(初稿)
  11. c语言程序设计笔记手写图片,C语言程序设计笔记.pdf
  12. matlab实现带通滤波
  13. 什么是云渲染?云渲染应用场景有哪些?
  14. web服务器软件有哪些?带你快速了解
  15. manjaro yay查找搜索软件包
  16. 怎样使用计算机定时关机,详细教你电脑如何设置定时关机
  17. linux安装软路由,软路由安装设置教程【详细步骤】-太平洋IT百科手机版
  18. c语言规定对程序中所用的变量必须,【判断题】C语言程序中要用到的变量必须先定义,然后再使用...
  19. win7计算机搜索功能没有了,win7搜索功能不能用了怎么办|win7搜索功能不见了怎么解决? - 学无忧...
  20. 微信小程序 五 npm 包 、安装 vant组件、promise组件、全局数据共享、 分包!!!、自定义 tabBar 案例

热门文章

  1. windows7计算机不显示u盘,Win7系统U盘文件不显示的三种解决方法
  2. python声音模拟_5秒钟让python克隆别人的声音
  3. 使用JavaScript重定向到其他网页
  4. [程序员学英语]英语句子结构
  5. python 在线ide搭建_从头开始制作OJ-在线IDE的搭建
  6. 【无人机驾照】无人机驾驶员考试题库选择题1060道(带答案)
  7. opencv-contrib sfm扩展模块下载安装
  8. 群体智能优化算法介绍
  9. 【Elasticsearch源码】 更新性能分析
  10. Spring Cloud版本说明