一、抢火车票
1、抢火车票软件的技术原理
找到用户名密码控件名
找到起始地控件名 :
二、抢红包 1、实现微信自动抢红包
抢红包核心代码: AccessibilityService配置 android:accessibilityEventTypes设置触发监听回调的事件类型; android:packageNames设置监听的应用,这里监听的是微信,因此填上微信的包名com.tencent.mm <accessibility-servicexmlns: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> <actionandroid:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config"/> </service> 抢红包实现代码 接收系统发送来的AccessibilityEvent privatestaticfinalStringGET_RED_PACKET="领取红包"; privatestaticfinalStringCHECK_RED_PACKET="查看红包"; privatestaticfinalStringRED_PACKET_PICKED="手慢了,红包派完了"; privatestaticfinalStringRED_PACKET_PICKED2="手气"; privatestaticfinalStringRED_PACKET_PICKED_DETAIL="红包详情"; privatestaticfinalStringRED_PACKET_SAVE="已存入零钱"; privatestaticfinalStringRED_PACKET_NOTIFICATION="[微信红包]"; @Override publicvoidonAccessibilityEvent(AccessibilityEventevent){ L.d("RECEIVEEVENT!"); 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; AccessibilityNodeInfocellNode=mReceiveNode; cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK); mLuckyMoneyReceived=false; mLuckyMoneyPicked=true; L.d("正在打开!"); } /*如果戳开但还未领取*/ if(mNeedUnpack&&(mUnpackNode!=null)){ AccessibilityNodeInfocellNode=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; } } }
1、抢火车票软件的技术原理
目前主流的抢票软件是安装在浏览器上的插件,像猎豹、360浏览器等,用于在12306网站上抢票。
常规情况下,使用12306网站订票时,如果刷新页面就需要再次填写个人信息,这就耽误了不少时间。这一耽误,可能需要“秒杀”的热门火车票就已经落入他人之手,而查看剩余车票时也需要在计算机前不断地点击刷新页面。
人工操作效率远不如刷票软件而抢票软件能够记录个人信息,自动重复登录,直到登录成功,代替缓慢的人工操作。并通过对12306网站的不断刷新和监控,一旦有人退票,抢票软件能立即发现。此外,部分软件从查询到下单可以直接勾选,不需再填写任何信息。有了这些便利功能,抢票软件确实可以将抢票成功率大大提高。
2、教大家一个自动抢票技术脚本 1)先准备好工具: 12306网站用户名和密码 chrome浏览器及下载chromedriver python代码代码用的Python+Splinter开发,Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互。
Splinter执行的时候会自动打开你指定的浏览器,访问指定的URL。然后你所开发的模拟的任何行为,都会自动完成,你只需要坐在电脑面前,像看电影一样看着屏幕上各种动作自动完成然后收集结果即可。
2)基本实现原理:
找到相应URL,找到控件模拟登录、查询、订票操作。关键是找到控件名称,难点是起始地不是直接输入的页面值,需要在cookie中查出。
12306查询URL: https://kyfw.12306.cn/otn/leftTicket/init 12306登录URL: https://kyfw.12306.cn/otn/login/init 我的12306URL: https://kyfw.12306.cn/otn/index/initMy12306 购票确认URL: https://kyfw.12306.cn/otn/confirmPassenger/initDcPython代码打开URL,找到控件填充值:
deflogin(self): self.driver.visit(self.login_url) #填充用户名 self.driver.fill("loginUserDTO.user_name",self.username) #填充密码 self.driver.fill("userDTO.password",self.passwd) printu"等待验证码,自行输入..."找到用户名密码控件名
找到起始地控件名 :
确定起始地的值,方法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() 运行代码: pythontickets.py上海广州2018-12-25最后手动点一下的12306验证码,抢到票后确认支付就行啦。
二、抢红包 1、实现微信自动抢红包
微信自动抢红包的实现方法,主要实现以下几个功能:
自动拆开屏幕上出现的红包 处于桌面或聊天列表时接收到红包信息时自动进入聊天界面并拆红包 日志功能,记录抢红包的详细日志 实现原理: 利用AccessibilityService辅助服务,监测屏幕内容,实现自动拆红包的目的。 利用ActiveAndroid数据库简单记录红包日志 利用preference实现监控选项纪录 最终界面:抢红包核心代码: AccessibilityService配置 android:accessibilityEventTypes设置触发监听回调的事件类型; android:packageNames设置监听的应用,这里监听的是微信,因此填上微信的包名com.tencent.mm <accessibility-servicexmlns: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> <actionandroid:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config"/> </service> 抢红包实现代码 接收系统发送来的AccessibilityEvent privatestaticfinalStringGET_RED_PACKET="领取红包"; privatestaticfinalStringCHECK_RED_PACKET="查看红包"; privatestaticfinalStringRED_PACKET_PICKED="手慢了,红包派完了"; privatestaticfinalStringRED_PACKET_PICKED2="手气"; privatestaticfinalStringRED_PACKET_PICKED_DETAIL="红包详情"; privatestaticfinalStringRED_PACKET_SAVE="已存入零钱"; privatestaticfinalStringRED_PACKET_NOTIFICATION="[微信红包]"; @Override publicvoidonAccessibilityEvent(AccessibilityEventevent){ L.d("RECEIVEEVENT!"); 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; AccessibilityNodeInfocellNode=mReceiveNode; cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK); mLuckyMoneyReceived=false; mLuckyMoneyPicked=true; L.d("正在打开!"); } /*如果戳开但还未领取*/ if(mNeedUnpack&&(mUnpackNode!=null)){ AccessibilityNodeInfocellNode=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; } } }
检测监听事件的节点信息
privatevoidcheckNodeInfo(){ L.d("checkNodeInfo!"); if(this.rootNodeInfo==null)return; /*聊天会话窗口,遍历节点匹配“领取红包”和"查看红包"*/ List<AccessibilityNodeInfo>nodes1=this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo,newString[]{ GET_RED_PACKET,CHECK_RED_PACKET}); if(!nodes1.isEmpty()){ L.d("!nodes1.isEmpty()"); AccessibilityNodeInfotargetNode=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("thisistext"); } return; } List<AccessibilityNodeInfo>nodes2=this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo,newString[]{ "拆红包"}); if(!nodes2.isEmpty()){ L.d("node2!=null"); for(AccessibilityNodeInfonodeInfo:nodes2){ if(nodeInfo.getClassName().equals("android.widget.Button")) nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK); } }else{ /*戳开红包,红包还没抢完,遍历节点匹配“拆红包”*/ AccessibilityNodeInfonode2=(this.rootNodeInfo.getChildCount()>3)?this.rootNodeInfo.getChild(3):null; if(node2!=null&&node2.getClassName().equals("android.widget.Button")){ mUnpack