马上要过年了,最近有很多小伙伴私信我关于“如何通过技术手段实现抢火车票、抢红包?”,今天就针对大家关心的问题,给大家分享一下相关技术的实现,让大家通过学习利用技术手段大大提升抢火车票、红包的成功率!
一、抢火车票
1、抢火车票软件的技术原理
目前主流的抢票软件是安装在浏览器上的插件,像猎豹、360浏览器等,用于在12306 站上抢票。
常规情况下,使用12306 站订票时,如果刷新页面就需要再次填写个人信息,这就耽误了不少时间。这一耽误,可能需要“秒杀”的热门火车票就已经落入他人之手,而查看剩余车票时也需要在计算机前不断地点击刷新页面。
人工操作效率远不如刷票软件
而抢票软件能够记录个人信息,自动重复登录,直到登录成功,代替缓慢的人工操作。并通过对12306 站的不断刷新和监控,一旦有人退票,抢票软件能立即发现。此外,部分软件从查询到下单可以直接勾选,不需再填写任何信息。有了这些便利功能,抢票软件确实可以将抢票成功率大大提高。
2、教大家一个自动抢票技术脚本
1)先准备好工具:
代码用的Python+Splinter开发,Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互。
Splinter执行的时候会自动打开你指定的浏览器,访问指定的URL。然后你所开发的模拟的任何行为,都会自动完成,你只需要坐在电脑面前,像看电影一样看着屏幕上各种动作自动完成然后收集结果即可。
2)基本实现原理:
找到相应URL,找到控件模拟登录、查询、订票操作。关键是找到控件名称,难点是起始地不是直接输入的页面值,需要在cookie中查出。
Python代码打开URL,找到控件填充值:
def login(self): self.driver.visit(self.login_url) # 填充用户名 self.driver.fill("loginUserDTO.user_name", self.username) # 填充密码 self.driver.fill("userDTO.password", self.passwd) print u"等待验证码,自行输入..."
找到用户名密码控件名
找到起始地控件名 :
确定起始地的值,方法Chrome浏览器中的“检查”功能(按F12),Network —> Cookies中找到:
cookie中起始地的值
拷贝起始地的cookie值,我把几个常用的城市拷出来,放到了字典中:
cities= {'成都':'%u6210%u90FD%2CCDW', '重庆':'%u91CD%u5E86%2CCQW', '北京':'%u5317%u4EAC%2CBJP', '广州':'%u5E7F%u5DDE%2CGZQ', '杭州':'%u676D%u5DDE%2CHZH', '宜昌':'%u5B9C%u660C%2CYCN', '郑州':'%u90D1%u5DDE%2CZZF', '深圳':'%u6DF1%u5733%2CSZQ', '西安':'%u897F%u5B89%2CXAY', '大连':'%u5927%u8FDE%2CDLT', '武汉':'%u6B66%u6C49%2CWHN', '上海':'%u4E0A%u6D77%2CSHH', '南京':'%u5357%u4EAC%2CNJH', '合肥':'%u5408%u80A5%2CHFH'}
查询车票代码:
print u”购票页面开始…”
# 加载查询信息
self.driver.cookies.add({"_jc_save_fromStation": self.starts}) self.driver.cookies.add({"_jc_save_toStation": self.ends}) self.driver.cookies.add({"_jc_save_fromDate": self.dtime}) self.driver.find_by_text(u"查询").click()
运行代码:
python tickets.py 上海 广州 2018-12-25
最后手动点一下的12306验证码,抢到票后确认支付就行啦。
以上就是自动抢票的方法,小伙伴抓紧试试吧!有疑问可以随时私信我!
二、抢红包
1、实现微信自动抢红包
微信自动抢红包的实现方法,主要实现以下几个功能:
实现原理:
最终界面:
抢红包核心代码:
AccessibilityService配置
android:accessibilityEventTypes 设置触发监听回调的事件类型;android:packageNames 设置监听的应用,这里监听的是微信,因此填上微信的包名com.tencent.mm<accessibility-service xmlns_android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged" android_accessibilityFeedbackType="feedbackGeneric" android_accessibilityFlags="flagDefault" android_canRetrieveWindowContent="true" android_description="@string/accessibility_description" android_notificationTimeout="100" android_packageNames="com.tencent.mm" android_settingsActivity="com.oden.annotations.app.activity.ManActivity" />
在AndroidManifest.xml中声明:
<service android_name=".app.service.HongbaoService_" android_enabled="true" android_exported="true" android_label="@string/app_name" android_permission="android.permission.BIND_ACCESSIBILITY_SERVICE" > <intent-filter> <action android_name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android_name="android.accessibilityservice" android_resource="@xml/accessibility_service_config" /> </service>
抢红包实现代码
接收系统发送来的AccessibilityEvent
private static final String GET_RED_PACKET = "领取红包";private static final String CHECK_RED_PACKET = "查看红包";private static final String RED_PACKET_PICKED = "手慢了,红包派完了";private static final String RED_PACKET_PICKED2 = "手气";private static final String RED_PACKET_PICKED_DETAIL = "红包详情";private static final String RED_PACKET_SAVE = "已存入零钱";private static final String RED_PACKET_NOTIFICATION = "[微信红包]"; @Overridepublic void onAccessibilityEvent(AccessibilityEvent event) { L.d("RECEIVE EVENT!"); if (watchedFlags == null) return; /* 检测通知消息 */ if (!mMutex) { if (watchedFlags.get("pref_watch_notification") && watchNotifications(event)) return; if (watchedFlags.get("pref_watch_list") && watchList(event)) return; } if (!watchedFlags.get("pref_watch_chat")) return; this.rootNodeInfo = event.getSource(); if (rootNodeInfo == null) return; mReceiveNode = null; mUnpackNode = null; checkNodeInfo(); /* 如果已经接收到红包并且还没有戳开 */ if (mLuckyMoneyReceived && !mLuckyMoneyPicked && (mReceiveNode != null)) { mMutex = true; AccessibilityNodeInfo cellNode = mReceiveNode; cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK); mLuckyMoneyReceived = false; mLuckyMoneyPicked = true; L.d("正在打开!"); } /* 如果戳开但还未领取 */ if (mNeedUnpack && (mUnpackNode != null)) { AccessibilityNodeInfo cellNode = mUnpackNode; cellNode.performAction(AccessibilityNodeInfo.ACTION_CLICK); mNeedUnpack = false; L.d("正在领取!"); } if (mNeedBack) { performGlobalAction(GLOBAL_ACTION_BACK); mMutex = false; mNeedBack = false; L.d("正在返回!"); //总次数和金额统计 if (isGetMoney) { T.showShort(this, "抢到一个红包: " + gotMoney + "元!"); totalMoney = totalMoney + gotMoney; totalSuccessNum++; myPrefs.totalMoney().put(totalMoney); myPrefs.successNum().put(totalSuccessNum); L.d("totalMoney: " + totalMoney); L.d("totalSuccessNum: " + totalSuccessNum); saveToLog(hongbaoInfo); isGetMoney = false; } }}
检测监听事件的节点信息
private void checkNodeInfo() { L.d("checkNodeInfo!"); if (this.rootNodeInfo == null) return; /* 聊天会话窗口,遍历节点匹配“领取红包”和"查看红包" */ List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{ GET_RED_PACKET, CHECK_RED_PACKET}); if (!nodes1.isEmpty()) { L.d("!nodes1.isEmpty()"); AccessibilityNodeInfo targetNode = nodes1.get(nodes1.size() - 1); if ("android.widget.LinearLayout".equals(targetNode.getParent().getClassName()))//避免被文字干扰导致外挂失效 { if (this.signature.generateSignature(targetNode)) { mLuckyMoneyReceived = true; mReceiveNode = targetNode; L.d("signature:" + this.signature.toString()); } } else { L.d("this is text"); } return; } List<AccessibilityNodeInfo> nodes2 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{ "拆红包"}); if (!nodes2.isEmpty()) { L.d("node2 != null"); for (AccessibilityNodeInfo nodeInfo : nodes2) { if (nodeInfo.getClassName().equals("android.widget.Button")) nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } else { /* 戳开红包,红包还没抢完,遍历节点匹配“拆红包” */ AccessibilityNodeInfo node2 = (this.rootNodeInfo.getChildCount() > 3) ? this.rootNodeInfo.getChild(3) : null; if (node2 != null && node2.getClassName().equals("android.widget.Button")) { mUnpackNode = node2; mNeedUnpack = true; isToGetMoney = true; L.d("find red packet!"); return; } } /* 戳开红包,红包已被抢完,遍历节点匹配“已存入零钱”和“手慢了” */ if (mLuckyMoneyPicked) { List<AccessibilityNodeInfo> nodes3 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{ RED_PACKET_PICKED, RED_PACKET_SAVE, RED_PACKET_PICKED2, RED_PACKET_PICKED_DETAIL}); if (!nodes3.isEmpty()) { L.d("!nodes3.isEmpty()"); if (rootNodeInfo.getChildCount() > 1) { L.d("RED_PACKET_PICKED!"); } else { L.d("nodes3.get(0).toString(): " + nodes3.get(0).getText().toString()); if (!nodes3.get(0).getText().toString().equals(RED_PACKET_PICKED_DETAIL)) { AccessibilityNodeInfo targetNode = nodes3.get(nodes3.size() - 1); hongbaoInfo.getInfo(targetNode); if (isToGetMoney) { isGetMoney = true; isToGetMoney = false; gotMoney = hongbaoInfo.getMoney(); L.d("gotMoney: " + gotMoney); } L.d("RED_PACKET_SAVE!"); L.d("hongbaoInfo: " + hongbaoInfo.toString()); } else { L.d("this packet is myself!"); } } mNeedBack = true; mLuckyMoneyPicked = false; } } }
主要通过检测“领取红包”等关键文字信息来判断是否有新红包
检测收到红包时判断是否”
android.widget.LinearLayout”,屏蔽聊天信息中的文字干扰
拆红包时,由于微信版本可能不同,同时进行两种判断,以兼容部分版本
拆完红包需自动返回,有以下几种情况:抢到了,手慢了,以及该红包是自己发出的红包
下面是监听聊天列表的代码:
private boolean watchList(AccessibilityEvent event) { // Not a message if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || event.getSource() == null) return false; List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(RED_PACKET_NOTIFICATION); if (!nodes.isEmpty()) { AccessibilityNodeInfo nodeToClick = nodes.get(0); CharSequence contentDescription = nodeToClick.getContentDescription(); if (contentDescription != null && !lastContentDescription.equals(contentDescription)) { nodeToClick.performAction(AccessibilityNodeInfo.ACTION_CLICK); lastContentDescription = contentDescription.toString(); return true; } } return false; }
下面是监听通知信息的代码:
private boolean watchNotifications(AccessibilityEvent event) { // Not a notification if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) return false; // Not a hongbao String tip = event.getText().toString(); if (!tip.contains(RED_PACKET_NOTIFICATION)) return true; Parcelable parcelable = event.getParcelableData(); if (parcelable instanceof Notification) { Notification notification = (Notification) parcelable; try { notification.contentIntent.send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } } return true;}
红包信息的获取,及日志的存储:
通过获取节点的子信息,分别获得红包发送者及抢到的金额、抢红包时间等信息,建立简单的表单分别记录该信息。
@Table(name = "HongbaoInfos")public class HongbaoInfo extends Model { private int month; private int day; private int hour; private int min; private int sec; @Column(name = "sender") public String sender; @Column(name = "money") public String money; @Column(name = "time") public String time; public void getInfo(AccessibilityNodeInfo node) { AccessibilityNodeInfo hongbaoNode = node.getParent(); sender = hongbaoNode.getChild(0).getText().toString(); money = hongbaoNode.getChild(2).getText().toString(); time = getStringTime(); } private String getStringTime() { Calendar c = Calendar.getInstance(); month = c.get(Calendar.MONTH) + 1; day = c.get(Calendar.DAY_OF_MONTH); hour = c.get(Calendar.HOUR_OF_DAY); min = c.get(Calendar.MINUTE); sec = c.get(Calendar.SECOND); return month+"月"+day+"日 "+hour+":"+min+":"+sec; } @Override public String toString() { return "HongbaoInfo [sender=" + sender + ", money=" + money + ", time=" + time + "]"; } public static List<HongbaoInfo> getAll() { return new Select() .from(HongbaoInfo.class) .orderBy("Id ASC") .execute(); } public static void deleteALL() { new Delete().from(HongbaoInfo.class).execute(); } public float getMoney() { return Float.parseFloat(money); } public String getSender() { return sender; } public String getTime() { return time; }}
存储操作:
private void saveToLog(HongbaoInfo hongbaoInfo) { if (watchedFlags.get("pref_etc_log")) { HongbaoInfo hongbaoInfo1 = new HongbaoInfo(); hongbaoInfo1 = hongbaoInfo; hongbaoInfo1.save(); } else { L.d("log closed!"); }}
以上是微信自动抢红包方法
2、实现QQ自动抢红包
(一)抢红包流程:
- 通知栏收到QQ的消息,发现是QQ红包,模拟点击消息进入聊天页面
- 检索页面上的所有元素,发现有包含“点击拆开”的字眼,就模拟点击打开红包窗口
- 一两秒后执行Back操作,关闭红包窗口。
- 继续等待消息来到。
(二)实现功能:
- 锁屏抢红包(不可以有密码或者图案之类的锁屏)
- 口令红包,自动输入口令并且发送
- 抢完红包后,自动回复感谢语,可在红包设置里自行设置内容
- 其他的功能就没继续往下做了,知道方法,其他都可能慢慢研究出来。
(三)利用抢红包辅助功能类完成QQ抢红包,类中有用到QQConstant类,代码如下:
(四)QQ辅助服务里有用到的常量
public class QQConstant { //QQ的应用包名 public static final String QQ_PACKAGE_NAME = "com.tencent.mobileqq"; //状态栏红包关键字 public static final String QQ_ENVELOPE_KEYWORD = "[QQ红包]"; //QQ聊天页面 public static final String QQ_IM_CHAT_ACTIVITY = "com.tencent.mobileqq.activity.SplashActivity"; //点击拆开 public static final String QQ_CLICK_TAKE_APART = "点击拆开"; //口令红包 public static final String QQ_CLICK_PASSWORD_DIALOG = "口令红包"; //聊天页面,输入框ID public static final String QQ_CHAT_MESSAGE_INPUT = "com.tencent.mobileqq:id/input"; //聊天页面,发送按钮 public static final String QQ_CHAT_MESSAGE_SEND = "com.tencent.mobileqq:id/fun_btn"; }
以上就是QQ自动拆红包的方法,需要源码的小伙伴可以在看完文章后留言或者私信我!
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!