python自动撸支付宝基金答题红包
背景
在一个套利撸羊毛群里,一群小伙伴每天在不懈地撸支付宝的基金红包,于是自己也加入了撸红包大军。
于是就重复地在不同的基金里面,看有没有答题红包,有的话就点进去,回答一个及其容易的题目,当然,答错了也会提示你让你选择另外一个答案的。
领完红包,还要看看这个红包能否买货币基金或者短期理财,或者退而求其次,能买债券基金也行的,前提得要它的红包金额能否覆盖手续费,而且波动不能太大。
于是玩了几次后,觉得动作重复,且枯燥无味,为啥那些小伙伴能否如此每天乐此不疲地刷呀刷呀。
看着这小羊毛,每天撸就有点费时费神了, 于是就祭出万能胶水器python,可以通过自动化解放自己的双手。
最终效果视频演示
知乎视频www.zhihu.compython appium自动化获取支付宝答题红包 (一) 获取所有财富号的红包
知乎视频www.zhihu.compython appium自动化获取支付宝答题红包 (二) 删除不能购买债基的红包
第一个视频进去每一个 财富号里面,找到有红包的,然后自动答题,领取红包。
第二个视频是对获取的所有红包进行过滤,把不能领取货币/债券基金的红包给删除,因为我们的目标是撸羊毛,不要7天后被套了,套成了长期好基友。 纪律性是第一原则,切记。 因为现在的基金(除了货基)一般7天内卖出会有高额的1.5%的手续费,一般就等到7天后卖出。
实现技术路径
有人看过我前面几个教程,说为啥不用autojs呢?
哎,个人觉得人生苦短,还是用python吧(python之禅)。其实主要考虑autojs用起来感觉像是一个玩具,控件查找不稳定,运行也不稳定,而且在手机上运行,一些业务逻辑写起来也复杂,缺乏中间件,调用起来挺麻烦的。比如想加个redis去重队列,或者加个验证码深度学习识别模型,写起来都挺复杂的,最终的实现也都是在电脑上用python写个接口,然后autojs通过网络传输调用我起的python服务。
那什么是appium呢? 直接百度第一条的答案。
appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web应用和混合应用。
- “移动原生应用”是指那些用iOS或者 Android SDK 写的应用(Application简称app)。
- “移动web应用”是指使用移动浏览器访问的应用(appium支持iOS上的Safari和Android上的 Chrome)。
- “混合应用”是指原生代码封装网页视图——原生代码和 web 内容交互。比如,像 Phonegap,可以帮助开发者使用网页技术开发应用,然后用原生代码封装,这些就是混合应用。
重要的是,appium是一个跨平台的工具:它允许测试人员在不同的平台(iOS,Android)使用同一套API来写自动化测试脚本,这样大大增加了iOS和Android测试套件间代码的复用性。
本次使用的是python+appium框架进行操作手机,而appium的部署也是挺麻烦的,不过有个门槛也好,不然羊毛都被撸光了。
1# coding=utf-82# 公众号:可转债量化分析34# core code56class Alipay(DriveBase):7 def __init__(self, deviceName, package, activity, resetKB=False):8 super(Alipay, self).__init__(deviceName, package, activity, resetKB)9 self.history_file = os.path.join(self.root_path(), 'redbag.txt')10 self.width, self.height = self.get_screen_size()1112 def fund_redbag(self, clear):13 '''14 答题红包15 '''16 if clear:17 self.clear_file(self.history_file)1819 self.history_result = self.read_histroy(self.history_file)20 self.click_by_text('理财')21 time.sleep(1)2223 search_points = [819 * self.width / 1080, 84 * self.height / 2207], [963 * self.width / 1080,24 228 * self.height / 2207]25 self.click(search_points)2627 # 输入28 input_btn = WebDriverWait(self.driver, 4).until(EC.presence_of_element_located(29 (By.XPATH, '//android.widget.EditText[@text="搜索"]')))30 input_btn.send_keys(u'财富号')31 time.sleep(1)3233 self.click_by_text('搜索')34 time.sleep(1)3536 # 向右滑动到最后37 self.move_right_to_end()38 self.click_by_text('查看更多')3940 while True:41 # 出现一个列表42 item_list = self.driver.find_elements_by_xpath(43 '//android.widget.TextView[contains(@text, "财富号")]')4445 for item in item_list[1:]:46 text = item.text4748 if text in self.history_result:49 continue5051 if re.search('信用卡财富号|储蓄卡财富号', text):52 self.history_result.append(text)53 self.save_hitory(self.history_file, self.history_result)54 # self.driver.back()55 continue5657 try:58 item.click()59 time.sleep(3)60 except Exception as e:61 pass62 else:63 # 基金详情页面64 try:65 self.swipe_scroll_horizion()66 has_redbag = self.driver.find_element_by_xpath(67 '//android.view.View[@text="答题领取"]')6869 except Exception as e:70 print(f'{text} ==>没有红包')71 self.history_result.append(text)72 self.save_hitory(73 self.history_file, self.history_result)74 time.sleep(1)75 else:76 self.going_redbag_page(text, has_redbag)77 time.sleep(1)7879 self.driver.back()80 print('点击返回')8182 time.sleep(1)8384 # 向下滑动85 self.scroll_down_next_page_fund_list()868788 @delay89 def click_by_text(self, text):90 broadcast_btn = WebDriverWait(self.driver, 3).until(91 EC.presence_of_element_located((By.XPATH, f'//android.widget.TextView[@text="{text}"]')))92 broadcast_btn.click()939495 @delay96 def swipe_scroll_vertical(self):97 self.driver.swipe(500, 2000, 500, 400, 4000)9899 def find_bond_redbag(self):
100 '''
101 寻找债基
102 '''
103 self.click_by_text('卡包')
104
105 result = set()
106 while True:
107
108 redbags = self.driver.find_elements_by_xpath('//android.widget.TextView[@text="去使用"]')
109 fund_num = len(redbags)
110 time.sleep(1)
111 for redbag_num in range(fund_num):
112 self.driver.find_elements_by_xpath('//android.widget.TextView[@text="去使用"]')[redbag_num].click()
113 time.sleep(2)
114 try:
115 name = self.driver.find_element_by_xpath('//android.widget.TextView[contains(@text, "财富号")]')
116 except Exception as e:
117 time.sleep(1)
118 self.driver.back()
119 time.sleep(1)
120 # print('return back')
121 continue
122
123 try:
124 is_bond = self.driver.find_element_by_xpath('//android.widget.TextView[contains(@text, "债") or contains(@text, "理财") or contains(@text, "货币")]')
125 except Exception as e:
126 # self.driver.find_element_by_xpath('//')
127 delete_img = [972, 84], [1044, 228]
128 self.click(delete_img)
129 delete_name = self.driver.find_element_by_xpath('//android.widget.TextView[@text="删除"]')
130 delete_name.click()
131 time.sleep(2)
132 delete_btn = self.driver.find_element_by_xpath('//android.widget.Button[@text="确定"]')
133 delete_btn.click()
134 time.sleep(2)
135
136 else:
137 print(f'{name.text} 可用标的债/货币: n{is_bond.text}n')
138 result.add(name.text)
139 self.driver.back()
140 time.sleep(1)
141
142 self.swipe_scroll_vertical()
143 self.save_hitory('used_bond.txt',list(result))
144
145
146def alipy_fund_redbag(clear=False,resetKB=False):
147 package = 'com.eg.android.AlipayGphone'
148 activity = 'com.eg.android.AlipayGphone.AlipayLogin'
149
150 app = Alipay(deviceName, package, activity,resetKB)
151 app.fund_redbag(clear)
152 # app.find_bond_redbag()
153
154def main(clear=False,resetKB=True):
155 alipy_fund_redbag(clear=clear,resetKB=resetKB)
156
157if __name__ == '__main__':
158 fire.Fire(main)
核心代码如上。
没什么高深的玩意,就按照手工怎么点击就怎么写,更多的是语法的使用与控件查找,异常处理的逻辑控制。
我把封装的基类抽离出去了,所以实际代码要比上面的多得多,以为篇幅原因就不把所有代码贴出来,而且我发现关注我的读者,一般也不怎么关心我的代码,大部分都是伸手党,即使我贴出来的代码里面出几个bug也没人发现哈。
友情提示:因为最近信用债危机,所以最近撸债有风险。
来看看这只凶险的广发债就知道啦
完整代码可以在公众号后台 留言: 支付宝红包python
就可以获取啦。