如何用Python投机倒把几天“暴富”

本文涉及到的技术点有(多图预警!):

  • 1.Packet Capture和Charles抓包
  • 2.安卓AccessibilityService无障碍服务实现自动下注
  • 3.Python爬虫模拟下注
  • 4.Python Flask编写简单接口

行吧,别做梦了,暴富了,我还这里码字?标题党的感觉就是舒服,还是踏踏实实搬砖吧!关于赚大钱的捷径都写在刑法里,想具体了解的可以到逼乎自行查阅:都说最赚钱的方法都在刑法里面,那么宪法里面到底禁止了哪些暴利的赚钱方法?这些方法到底有多赚钱呢?我只能帮你们到这里了。投机倒把暴富的念想是挺美好的,但我投机倒把的真实的结果是:国庆短短几天,因为投机倒把我亏了7755块(截止目前亏了9073块)...

编写本文的出于下面几个初衷

  • 1.记录自己在投机倒把过程中运用到的一些开发技术
  • 2.记录这次投机倒把的经历,以此警示自己以后要踏踏实实做事;
  • 3.奉劝各位有这种念想的伙计引以为戒远离投机倒把保持身心健康

在真正开始本文之前,要严肃的强调几点:

  • 投机倒把,十有九,或者十!投机倒把中赚钱的永远是极少数的幸运儿。如果只为娱乐不为赢钱可以,参考过年家里常有的小赌怡情,玩个几百块,赢了和输了都收手。
  • 本文不是让你去投机倒把,所以不会提供任何APP下载外链或文件!

本文的讲解流程

先讲解一波投机倒把相关的概念,然后通过和两个好基友的沙雕聊天记录,引出一些开发相关的东西,分析一波投机倒把过程里的一些猫腻,希望各位看官会喜欢这个有()趣()的真实故事~


第零章:名词碎碎念

先来了解一波和投机倒把有关的名词吧~

0.1 赌徒心理(贪欲和侥幸心理)

赢了还想赢更多的钱,输了又想回本,反复告诉自己赢一把就收手,回本就收手,事实上,只有当自己的前输得精光的时候才会收手。

举个例子

  • 1.下注,输了10块,想着把10块赚回来,又压了10块,然后又输,又压20,再输压30...本没有回,钱却越输越多。
  • 2.输了10块,下把下注奖为5块,赢了患得患失,如果刚刚那把压多一点就赢好多了,输了暗自庆幸,幸好把下注少了,不然就亏大了。

赢钱的时候也不会见好就收,毕竟对于赌徒来说,收手是最难的。

0.2 大数法则

大数不是大叔,又称“平均法则”,即:在随机事件的大量重复中往往出现几乎必然的规律。在实验条件不变的情况下,重复实验多次,随机事件的频率近似于它的概率。举个例子,我们都知道的常识:抛硬币,正反面的概率各占50%。但是,现在让你去抛两次硬币,却很难出现刚好一正一反的情况。只在你重复了上千上万次后,正和反出现的次数接近持平。

看到这里,读者可能有这样的疑问:

既然最后是五五开,那我一直玩,为什么最后还是亏了,难道是有中间商赚差价了?

讲真,真的有中间商,尽管从概率上来说,是五五开的,但是有两点根本不平等。

首先,概率是建立在大量重复实验的基础上的,庄家有“用不完的钱”,可以进行无限次投机倒把,且没有赌徒心理,而反观赌徒的资金一般是有限的。然后呢,又有一个名词,概率波动论。

0.3 概率波动论

具备两面性的规律从概率来讲是对半的,但在一段时间内有可能多数呈一面性表现。
举个简单的三个骰子买大小的例子(1-9小,10-18大),10次的结果是这样的(连续3次大):

概率波动是概率发生的必然,因此投机倒把过程中可能出现连续输好几把的情况。

0.4 倍投法

接着是中间商赚差价的第二点,比如有一些买大小单双的赌局,胜率并不是1:2,比如1:1.96,或者1:1.82等,比如你一把玩1块,第一把输了,第二把也投1块,你中了,只赢1.96块,但是,其实你已经花了2块钱,亏4分钱。如果是1.86的,亏1毛4,看上去数额很少是吧,但是基本都不会只玩几把吧,一天下来可能玩了上千把,一个赌客就贡献了好几百,赌客肯定不止你一个,而且下注也肯定不会1块1块的来,所以说说为什么那么多投机倒把类的APP。而扭转这种亏损的一种简单而且赚钱的做法,就是倍投法。举个简单的例子,假如赔率是1:2的话,下注的金额是这样一个列表:[10,20,40,80,160,320,640,1280,2560...],第一把投10块,输了,第2把投20,赢了40,减去本金30,赚10,没中,第3把投40,赢了80,减去本金70,赚10块,就是保证每一轮赢10块。我们写个简单的Python代码来生成一个倍投收益的表格。代码如下(prettytable库用于生成表格):

from prettytable import PrettyTable

purchase_base = 10  # 购买基数
ratio = 2  # 中奖倍率
price_list = []  # 投入金额


def init_purchase_list():
    x = PrettyTable(['投入', '投入总额', '获利', '净利润'])
    cost = 0
    price_list.append(purchase_base)
    # 其他进行动态计算
    print("初始化投入金额表格...")
    for i in range(0, 10):
        cost += purchase_base * (2 ** i)    # 花费
        bonus = purchase_base * (2 ** i) * ratio    # 奖金
        x.add_row([purchase_base * (2 ** i), cost, bonus, bonus - cost])
    print(x)


if __name__ == '__main__':
    init_purchase_list()

运行下程序,可以得出一个倍投的结果列表:

初始化投入金额表格...
+------+----------+-------+--------+
| 投入 | 投入总额 |  获利 | 净利润 |
+------+----------+-------+--------+
|  10  |    10    |   20  |   10   |
|  20  |    30    |   40  |   10   |
|  40  |    70    |   80  |   10   |
|  80  |   150    |  160  |   10   |
| 160  |   310    |  320  |   10   |
| 320  |   630    |  640  |   10   |
| 640  |   1270   |  1280 |   10   |
| 1280 |   2550   |  2560 |   10   |
| 2560 |   5110   |  5120 |   10   |
| 5120 |  10230   | 10240 |   10   |
+------+----------+-------+--------+

每一轮才挣10块,有点少是吧,你可以试试赚更多的3倍投,把上面的代码改一下:

    for i in range(0, 10):
        cost += purchase_base * (3 ** i)    # 花费
        bonus = purchase_base * (3 ** i) * ratio    # 奖金
        x.add_row([purchase_base * (3 ** i), cost, bonus, bonus - cost])

输出结果如下:

初始化投入金额表格...
+--------+----------+--------+--------+
|  投入  | 投入总额 |  获利  | 净利润 |
+--------+----------+--------+--------+
|   10   |    10    |   20   |   10   |
|   30   |    40    |   60   |   20   |
|   90   |   130    |  180   |   50   |
|  270   |   400    |  540   |  140   |
|  810   |   1210   |  1620  |  410   |
|  2430  |   3640   |  4860  |  1220  |
|  7290  |  10930   | 14580  |  3650  |
| 21870  |  32800   | 43740  | 10940  |
| 65610  |  98410   | 131220 | 32810  |
| 196830 |  295240  | 393660 | 98420  |
+--------+----------+--------+--------+

卧槽,刺激是吧,如果有30W的本金,三倍投,不中的次数越多,你赚的钱越多。如果连续不中到10次,中了,一轮1将近10W,这种是敢死队倍投法,很难很难挂一次,但是一旦出现一次直接跌入18层地狱永不超生!(笔者试过好几次...等下细讲)。这种是平台比例1:2的情况,有些中间商赚差价的平台的赔率是1.96这样,上面的代码生成的结果就变成了(2倍投,ratio改为1.96):

初始化投入金额表格...
+------+----------+---------+---------------------+
| 投入 | 投入总额 |   获利  |        净利润       |
+------+----------+---------+---------------------+
|  10  |    10    |   19.6  |  9.600000000000001  |
|  20  |    30    |   39.2  |  9.200000000000003  |
|  40  |    70    |   78.4  |  8.400000000000006  |
|  80  |   150    |  156.8  |  6.800000000000011  |
| 160  |   310    |  313.6  |  3.6000000000000227 |
| 320  |   630    |  627.2  | -2.7999999999999545 |
| 640  |   1270   |  1254.4 | -15.599999999999909 |
| 1280 |   2550   |  2508.8 |  -41.19999999999982 |
| 2560 |   5110   |  5017.6 |  -92.39999999999964 |
| 5120 |  10230   | 10035.2 | -194.79999999999927 |
+------+----------+---------+---------------------+

是的,普通的二倍投法越到后面反而越亏,而三倍投依旧是赚钱的,在本金不够充裕无法三倍投的情况下,要在二倍投的基础上加点,而且少于三倍投,保证我们每把赚的钱>购买基数,而且投入的金额最少,我们改下下我们的代码:

from prettytable import PrettyTable

purchase_base = 10  # 购买基数
ratio = 1.96  # 中奖倍率
price_list = []  # 投入金额


def init_purchase_list():
    x = PrettyTable(['投入', '投入总额', '获利', '净利润'])
    x.add_row([purchase_base, purchase_base, round(purchase_base * ratio, 2),
               round(purchase_base * ratio - purchase_base, 2)])
    cost = purchase_base
    price_list.append(purchase_base)
    # 其他进行动态计算
    print("初始化投入金额表格...")
    for i in range(10):
        purchase = 0
        # 购买价格其实区间(2倍)
        start_price = purchase_base * (2 ** i)
        # 购买价格极限区间(3倍)
        end_price = purchase_base * (3 ** i)
        # 保证没把不亏就行
        for j in range(start_price, end_price + 1):
            if j * ratio - cost - j > purchase_base:
                x.add_row([j, cost + j, round(j * ratio, 2), round(j * ratio - cost - j, 2)])
                cost += j
                price_list.append(j)
                break
    print(x)


if __name__ == '__main__':
    init_purchase_list()

输出下注金额列表如下:

初始化投入金额表格...
+------+----------+----------+--------+
| 投入 | 投入总额 |   获利   | 净利润 |
+------+----------+----------+--------+
|  10  |    10    |   19.6   |  9.6   |
|  21  |    31    |  41.16   | 10.16  |
|  43  |    74    |  84.28   | 10.28  |
|  88  |   162    |  172.48  | 10.48  |
| 180  |   342    |  352.8   |  10.8  |
| 367  |   709    |  719.32  | 10.32  |
| 749  |   1458   | 1468.04  | 10.04  |
| 1530 |   2988   |  2998.8  |  10.8  |
| 3123 |   6111   | 6121.08  | 10.08  |
| 6377 |  12488   | 12498.92 | 10.92  |
+------+----------+----------+--------+

以上就是通过Python计算倍投下注金额,关于更多的倍投方法可自行查阅:倍投的方案全面讲解如何倍投,关于投机倒把的名词就科普那么多,正式开始这个令人悲伤的故事吧~


第一章:引子

和往常一样,下午等电梯去吃饭,好基友小A又掏出他的小锤子在那里把玩,抱着好奇心的
我用眼角的余光瞄了一下他在看什么,em...竟然不是那种不堪入目的东西?

在我的威逼利诱(Y威)下全盘托出:别人介绍玩的一款赚钱APP(买彩票)。但是,我记得错网络售彩不是从15年就开始命令禁止了吗。行吧,看了下,私庄(私人庄家)。然后大概看了看APP:

页面非常简单,四个部分:

  • 1.顶部最新一期下注倒计时+用户余额
  • 2.每期开奖结果
  • 3.房间里赌客的投注记录
  • 4.下注面板

规则就是下注结果和出的结果一样就中,根据买的种类有不同的倍率,三分钟开一把,下注最小金额10元宝(10块),数据来源加拿大28彩票的出奖结果。这种算是公彩吧,不是私彩。区分的最简单依据就是有这个项目的多个平台是不是开奖的结果都是一样的,相比起私彩,公彩稍微稍微公平一点。私彩的话,后台是可以调的!!!好吧,一向对于投机倒把不怎么感冒的我就没有过多的关注了。不过,他貌似从别人那里搞了个下注的投法,慢慢从20奋斗到102,成功引起了我的注意。

这个所谓靠谱的投法就是:

  • 1.历史记录里,单跟双,多就买谁。
  • 2.历史记录里面,大跟小,少就买谁。
  • 3.每一次亏了下一把就把下注金额在上一把基础上翻倍,每一次赚了下一把下注金额就还原到最低值。
    4.循环上面三步骤。如果遇到异常流:当前步骤应该买大小或者单双时,出现历史记录里他们数量相同,则停止一局。

后面果然给他撸到200了:

啧啧,竟然真的从20撸到200,不心动是假的...

但是作为一个从不相信天上掉馅饼的开发仔有着自己的矜持,不模拟一下,打死我也不信,于是我盘算着,自己写个脚本按照这个投法去模拟,模拟一段时间后,看看最后是不是真的赚了。先来抓一波APP的包看看吧,这里用到的是手机抓包工具:Packet Capture

行吧,token和sign,后面另外抓了下注的接口,一大串,加密,所以基本可以放弃了。然后想逆向找下APP的代码,直接apktool反编译后看到qihoo的包名,擦,360加固,这就触及到我的知识盲区了,我还不会脱壳...

幸运的是,这是公彩,有很多网站会直接公布每一期的结果,比如:
https://www.kandandan.com/yuce/jnd.html,接着打开Chrome抓下包,先看下页面节点:

可以,看下Network也可以找到这些节点,不是JS加载的,nice,所有要做的就是写一个定时器,每隔3分40秒左右(延时问题)访问一下这个站点,提取一波数据。行吧,直接用Python请求库Requests模拟一波请求就行了,定时任务用apscheduler库,最后加上投注相关的算法就可以了,直接给代码,就不解释那么多了。

import requests as r
from bs4 import BeautifulSoup
from apscheduler.schedulers.blocking import BlockingScheduler

current_buy = '单双'  # 当前买的类型
current_buy_type = '单'  # 当前下注类型
current_buy_money = 10  # 当前投注金额
is_buy_flag = False  # 此轮是否购买
first_buy = True  # 是否第一次下注
balance = 300  # 剩余金额
sched = BlockingScheduler()


def fetch_result():
    global first_buy
    resp = r.get('https://m.99yuce.com/yuce/jnd.html').text
    bs = BeautifulSoup(resp, 'lxml')
    tr_s = bs.find("table", attrs={'id': 'tbe'}).find_all('tr')
    # 获取数字列表
    num_list = []
    for tr in tr_s[2:12]:
        num_list.append(int(tr.find('td', attrs={'class': 'tbe_3'}).text))
    print(num_list)
    # 构建数字文字列表
    num_str_list = []
    for num in num_list:
        if num % 2 == 0:
            num_str_list.append('双')
        else:
            num_str_list.append('单')
        if num > 13:
            num_str_list.append('大')
        else:
            num_str_list.append('小')
    if first_buy:
        first_buy = False
        print("当前余额:", balance, " 当前投注金额:", current_buy_money, "当前买的类型:", current_buy)
    else:
        calculate(num_list[0])
    predict(num_str_list)


# 预判
def predict(num_str_list):
    global balance
    global current_buy_money
    global current_buy
    global current_buy_type
    global is_buy_flag
    single_count = 0  # 单出现的次数
    big_count = 0  # 大出现的次数
    for num_str in num_str_list:
        if num_str == '单':
            single_count += 1
        if num_str == '大':
            big_count += 1
    print('单:', single_count, ' 大:', big_count)
    # 如果当前这把应该买单双
    if current_buy == '单双':
        if single_count > 5:
            current_buy_type = "单"
            balance -= current_buy_money
            is_buy_flag = True
            print("押单")
        elif single_count < 5:
            current_buy_type = "双"
            balance -= current_buy_money
            is_buy_flag = True
            print("押双")
        else:
            # 相等则跳过
            print("单双相等,跳过这一局,不买")
            is_buy_flag = False

    # 如果当前这把应该买大小
    elif current_buy == '大小':
        if big_count < 5:
            current_buy_type = "大"
            balance -= current_buy_money
            is_buy_flag = True
            print("押大")
        elif big_count > 5:
            current_buy_type = "小"
            balance -= current_buy_money
            is_buy_flag = True
            print("押小 ")
        else:
            # 相等则跳过
            print("大小相等,跳过这一局,不买")
            is_buy_flag = False


# 结算,传入最新的数字
def calculate(latest_num):
    global balance
    global current_buy_money
    global current_buy
    global current_buy_type
    global is_buy_flag
    # 如果没有买直接跳过结算
    if is_buy_flag:
        result_list = []
        if latest_num % 2 == 0:
            result_list.append('双')
        else:
            result_list.append('单')
        if latest_num > 13:
            result_list.append('大')
        else:
            result_list.append('小')
        print('开奖结果:', result_list)
        # 中了(加余额,重置下注金额)
        if current_buy_type in result_list:
            balance += current_buy_money * 2
            current_buy_money = 10
            print("中了!")
        # 没中(下注金额加倍)
        else:
            current_buy_money *= 2
            print("没中~")
        # 无论中没中,切换下一把的下注类型
        if current_buy == '单双':
            current_buy = '大小'
        else:
            current_buy = '单双'
    else:
        print("没有下注,跳过当前轮")
    print("当前余额:", balance, " 当前投注金额:", current_buy_money, "当前买的类型:", current_buy)


if __name__ == '__main__':
    sched.add_job(fetch_result, 'interval', minutes=3, seconds=40)
    fetch_result()
    sched.start()

接着把脚本挂着模拟下注就可以,而且小A玩的时候不用自己去统计,看着投就好了。

经过两个小时的艰辛等待,300跑到390了,卧槽,稳得不行,什么都不干,每小时多50块左右,一天跑个10小时,500进口袋,搞十个号,一天不得5000?,500030 = 150000,卧槽,一个月什么都不干15W,有本金了买一堆手机,挂着跑100个号,卧槽,深圳买房不是梦。我还盘算着公司附近哪租个小地方来做机房,就一个架子然后放一堆手机就好了。 在不知不觉中我已经着道了,但还保留着一丝理智,无本生利的事情怎么别人想不到,庄家都是傻逼吗?万一卷款跑路了,于是我谷歌搜了一波是不是骗局,在逼乎看到了这篇文章:
腾讯彩票游戏幸运28是不是个骗局?,现在提是能提现,最怕是做了什么限制,比如次数,或者限额,钱根本搞不出来,抱着先试试,300而已,赚够本金就提出来,后面的就真的是无本生利了(事实是,
我们想多了*,这么点钱,对人家平台来说真的不算什么,而且本金就没提出来过,最后都是血本无归...)


第二章:如火如荼

贫穷使人勤劳,一想到可以暴富,我比任何时候都勤快,真·撸起袖子加油干。所谓的自动化就是不用自己点点点,方法也很简单,使用的Android的无障碍服务——AccessibilityService实现,原生的Android页面都可以用这个点点点,如果是内嵌网页的就无能为力了。如果你想了解AccessibilityService可以查阅我以前写的两篇文章:

简单点说就是利用工具,根据ID或者TEXT文本找到对应的控件进行一些操作比如最常见的点击传入文本等。而这个找ID的工具可以使用android-sdk里自带的monitor来查找,如果你的手机有root还可以下载使用开发者助手,如图所示,可以直接拿到控件ID。

模拟点,进入到这个页面,然后把Python写的算法搬运到Android上,用Okhttp模拟下请求。代码比较多,而且本节主要是将Python,就只贴下大概的样子。

花了一早上的的时间撸出了这个自动点点点,自动下注演示:

行吧,自动下注的点点点弄好了,接着就是挂机测试了,因为觉得稳赚的,于是我注册了两个账号,分别充了300,挂着运行:

在一段小测后发现挺稳定的,于是乎把脚本打成APK,让基友也用起来,然后开始说各种幻想暴富的骚话。

接着就是挂机,BUG修复,和不断的程序优化了,短短几天迭代了十几个版本。接着把基友小B也忽悠进来。

为了早日实现完全自动化,在狗东买了本逆向的书,打算利用国庆破解一波接口,把脚本挂到服务器上,暴富似乎指日可待了,实际上却是一步一步在将自己推向深渊...


第三章:噩耗

2018.9.30号晚上,看着挂了一整天的脚本余额1380元宝,不禁心中窃喜,毕竟有什么比得上看着钱一点点变多令人愉悦么,一想到把脚本挂一晚上,第二天起来就可以2000+了,梦里都会笑醒吧。

2018.10.1号的早上,没有像往常那样睡懒觉到十一二点,八点多就醒了,第一件事迫不及待的去看余额,但是等待我的,却不是如期的2000多,而是340。怎么会这样???不是很稳的吗。立马去翻历史下注记录:

排查后是下注操作有问题,大概的原因可能是:
APP开奖延迟,时间并不准确,爬取开奖站点存在一定的延时,有时获到的前十期的结果并不是最新的。
一想到:挂了好几天,钱一下子就没了:

本金用了900,减去剩下的340,我亏了560啊,怎么行,必须得回本,昨晚是因为自动挂着才会这样,手动就可以,但是340可以
抗的波数不多,需要更多的本金,我犹豫着要不要充多940进去,凑够1280,在支付的页面停顿了一会儿,后面脑子一热手指一按,
就支付了。不得不说,越来越便捷的支付方式,让人对钱的感觉越来越没感觉,以前没钱了,还要跑银行ATM排队取,钱取出来拿在
手上还会掂量掂量,钱是有分量的。而快捷支付让人感觉钱就是一堆数字而已,越加容易冲动消费,在不知不觉中已经负债累累。
钱充之后,依旧挂着脚本,而基友小A则去问别人拿新策略了。一边继续挂着,一边开始排查程序错误,一开始还是挺稳健的,然而
就一下午的事情,我刚充的钱又败完了,而小A充1000用的新策略也输光了。

小A败光了就放弃了,而我像魔怔了一样,觉得是本金还是不够,而且抗的波数不够,既然害怕这种连续出现的情况,
为何我不直接跟连续呢,比如出现3次连续,我才开始继续买连续,我又充了2560进去,能够抗十三波一直不中。
同样,测试初期都是好的,又挂了一晚上,事实证明,我还是太naive了,早上六点多起来还是赚的,睡了个
回笼觉,八点多起,发现钱又输光了...心情一下跌落到谷底,唉,不知不觉就输了四千多,四千多啊!!!
难过得饭都吃不下,狗东给我打电话让我到楼下拿书都没接,我到底在干嘛啊?并立下各种Flag,再碰投机
倒把的东西,是狗。


第四章:真香

正当我想着算了,花4000多买个教训吧,以后别相信这种投机倒把的东西就好,剩下几天好好写书,别再折腾这些东西。
然而世间万物都离不开『真香定律』。

晚上小A又给我案例了一个新的APP

相比起之前的APP,这个是可以1块起投的(之前的10块)。

行吧,我又冲了2426进去,只是想回本...因为还没有出策略,所以我还是用的之前那个平台的策略买,
下注的基数小了,能抗的波数多了,就稳了,然而结果依旧是输得一干二净。

小A开始疯狂炫富:

在我的再三催促下下,小A终于把下注的策略画出了如下这个下注流程图。

行吧,流程图看上去很复杂,其实捋一捋就是下述这样的策略(只买单双):

  • 1.最新两条记录结果不一样,连续三次一样,连续八次一样,买相反。
  • 2.最新两条记录结果一样,连续四次一样,连续少于七次,买相同。

行吧,策略搞到手了,接着就是抓包和用Python编写爬虫来模拟下注了。


第五章:神兵加持

打开APP,开发者工具打开布局边界,内容面板没有出现边界,行吧不是原生Android,基本就是H5了。
打开Charlse抓包工具抓下包(抓包教程可自行百度),可以看到APP陆陆续续发出的请求。

点开其中一个lotteryOpenCache可以看到对应的响应的结果如下(浏览器插件JSON-Handle):

行吧,大概可以确定是每一把的开奖结果的接口了,接下来是看下传递的参数:

行吧,就是传递JSON数据,但是这个开奖结果要登录后才能访问,肯定是存在cookies或者token这里机制的,
果不其然,点击Cookies选项可以看到:

最后看下请求头如下:

行吧,参数啥的,都有了,我们用Python requests库来模拟一波请求吧,看是否能得到对应的结果。

import requests as r

headers = {
    'origin': 'https://m.sfcappwz4.com',
    'user-agent': 'Mozilla/5.0 (Linux; Android 8.1.0; OE106 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36',
    'content-type': 'application/json',
    'cookie':'JSESSIONID=BDCD384F2DAD64E83BC1A6EBFCADB479',
    'referer':'https://m.sfcappwz4.com/lottery/K3/OG1K3',
    'x-requested-with':'com.bright.aiwprtuon'
}


def get_result():
    resp = r.post('https://m.sfcappwz4.com/tools/_ajax/cache/lotteryOpenCache', headers=headers,
                  json={"requirement": ["OG1K3"]})
    print(resp.json())

if __name__ == '__main__':
    get_result()

运行后输出结果如下:

行吧,可以正确拿到数据,接着我们就该考虑如何获得这个Cookie了,这里后台比较顽皮,它不是在登录成功后
分配Cookies,而是在进去APP的时候就分配了,后续如果登录成功才会一直使用这个Cookie。

后续的所有请求都是带着这个cookie。

行吧,就是先访问这个getSiteInitData接口,拿到响应头里的set-cookie,保存,然后去执行登录,
接着我们来看下登录接口,也是传递的JSON字符串:

一看参数大概就能猜出什么了,依次是:账号,密码,有效码,时间,是否默认登录,除了密码,其他参数
都比较简单,固定字符串,时间戳,密码的话,猜测是MD5,复制下字符串往网上在线MD5解密网站一丢:
https://www.cmd5.com/,果不其然:

行吧,接着就是模拟登录了,这里用到hashlib库 进行md5加密:

import hashlib
hl = hashlib.md5()

def auto_login():
    global accountId
    hl.update(account_pawd.encode(encoding='utf-8'))
    json_params = {
        'loginName': account_name,
        'loginPwd': hl.hexdigest(),
        'validCode': '',
        'validateDate': str(int(round(time.time() * 1000))),
        'isdefaultLogin': 'true'
    }
    headers['referer'] = 'https://m.sfcappwz3.com/login'
    headers['x-requested-with'] = 'com.bright.aiwprtuon'
    resp = r.post('https://m.sfcappwz3.com/tools/_ajax/login', json=json_params, headers=headers)
    # 获取accountId
    accountId = resp.json()['data']['user']['userDetail']['accountId']

模拟登录成功后,带着Cookie就可以去访问所有的接口了,其他的接口也是如法炮制,设置请求头,传对应
的数据,这里就不重复复述了,都是些繁琐的操作,加上策略直接给完整脚本。

"""
自动投脚本
"""
import hashlib
import time

import requests as r
from apscheduler.schedulers.blocking import BlockingScheduler

cookies = ''
accountId = ''  # 用户id
playIds = ['K3002001010', 'K3002001011']  # 玩的种类,依次是大小和单双
is_first_open = True  # 是否刚打开
result_list = []  # 存储所有结果的数组
purchase_base = 100  # 购买基数
ratio = 1.96  # 中奖倍率
price_list = []  # 投入金额
cur_price_pos = 0  # 当前投入金额游标
cur_purchase_type = ''  # 当前下注的类别
account_name = ''  # 账号
account_pawd = ''  # 密码
cur_money = 0  # 当前余额
hl = hashlib.md5()

headers = {
    'origin': 'https://m.sfcappwz4.com',
    'user-agent': 'Mozilla/5.0 (Linux; Android 8.1.0; OE106 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36',
    'content-type': 'application/json',
    'accept': '*/*',
    'accept-language': 'zh-CN,en-US;q=0.9'
}


# 1.模拟访问拿到Cookies
def fetch_cookies():
    global cookies
    resp = r.post('https://m.sfcappwz4.com/tools/_ajax/getSiteInitData',
                  headers=headers,
                  json={"requirement": ["footerConfig", "helpConfig", "h5BannerList", "gradeList",
                                        "noticeData", "rankingList", "activityConfig", "defaultPhotoList",
                                        "lotteryConfig",
                                        "lotteryList", "rewardData", "config"], "cacheData": {}})
    cookies = resp.headers['set-cookie'].split(';')[0]
    headers['cookie'] = cookies


# 2.模拟登陆
def auto_login():
    global accountId
    hl.update(account_pawd.encode(encoding='utf-8'))
    json_params = {
        'loginName': account_name,
        'loginPwd': hl.hexdigest(),
        'validCode': '',
        'validateDate': str(int(round(time.time() * 1000))),
        'isdefaultLogin': 'true'
    }
    headers['referer'] = 'https://m.sfcappwz3.com/login'
    headers['x-requested-with'] = 'com.bright.aiwprtuon'
    resp = r.post('https://m.sfcappwz3.com/tools/_ajax/login', json=json_params, headers=headers)
    # 获取accountId
    accountId = resp.json()['data']['user']['userDetail']['accountId']


# 3.获得开奖结果
def get_result():
    global is_first_open
    global result_list
    headers['origin'] = 'https://m.sfcappwz4.com'
    headers['cookie'] = cookies
    headers['referer'] = 'https://m.sfcappwz4.com/lottery/K3/OG1K3'
    headers['x-requested-with'] = 'com.bright.aiwprtuon'
    resp = r.post('https://m.sfcappwz4.com/tools/_ajax/cache/lotteryOpenCache', headers=headers,
                  json={"requirement": ["OG1K3"]})
    num_list = []
    # 获取最新期数
    curissueNo = int(resp.json()['data']['backData']['lotteryOpen'][0]['issueNo']) + 1
    curissueNo_str = str(curissueNo)
    # 判断是不是最后一期,是的话更新为第二天的第一期
    if curissueNo_str[8:len(curissueNo_str)] == '1441':
        curissueNo = time.strftime('%Y%m%d') + '001'
    print("最新期数:", curissueNo)
    for n in resp.json()['data']['backData']['lotteryOpen']:
        num_list.append(n['count'])
    if len(result_list) == 0:
        result_list.extend(num_list)
    elif len(result_list) == 10:
        result_list.insert(0, num_list[0])
        result_list.pop()
    return curissueNo


# 4.获取当前余额的方法
def get_money():
    global cur_money
    headers['origin'] = 'https://m.sfcappwz4.com'
    headers['cookie'] = cookies
    headers['referer'] = 'https://m.sfcappwz4.com/userCenter/userCenterMenu'
    headers['x-requested-with'] = 'com.bright.aiwprtuon'
    resp = r.post('https://m.sfcappwz4.com/tools/_ajax//getUserBanlance', headers=headers,
                  json={"userName": account_name})
    cur_money = float(resp.json()['data']['money'])
    print("当前余额:", resp.json()['data']['money'])
    init_purchase_list()


# 5.自动下注的方法
def auto_buy(choose, curissueNo):
    global cur_purchase_type
    cur_purchase_type = choose
    playId = playIds[1]  # 下注类别id
    buy_price = purchase_base
    # 如果游标到达危险阀值,只投10块
    if cur_price_pos >= len(price_list) - 1:
        if len(price_list) == 1:
            buy_price = 1
        else:
            buy_price = 10
    else:
        buy_price = price_list[cur_price_pos]
    json_params = {
        'accountId': accountId,
        'clientTime': str(int(round(time.time() * 1000))),
        'gameId': 'OG1K3',
        'issue': str(curissueNo),
        'item': [str({
            'methodid': 'K3002001001',
            'nums': 1,
            'rebate': '0.00',
            'times': buy_price,
            'money': buy_price,
            'playId': [playId],
            'mode': '1',
            'issueNo': str(curissueNo),
            'codes': choose
        })]
    }
    headers['origin'] = 'https://m.sfcappwz3.com'
    headers['cookie'] = cookies
    headers['referer'] = 'https://m.sfcappwz3.com/lottery/K3/OG1K3'
    headers['x-requested-with'] = 'com.bright.aiwprtuon'
    resp = r.post('https://m.sfcappwz3.com/tools/_ajax/OG1K3/betSingle', headers=headers, json=json_params)
    if resp.json()['code'] != 'success':
        print(resp.text)
    print("下注【", choose, "】 金额【", buy_price, "】")
    print('=' * 50)


# 6.下注算法
def predict():
    global result_list
    global cur_price_pos
    global cur_purchase_type
    curissueNo = get_result()
    print("开奖数字:", result_list)
    size_str_list = []
    single_str_list = []
    for num in result_list:
        if num > 10:
            size_str_list.append('大')
        else:
            size_str_list.append('小')
        if num % 2 == 0:
            single_str_list.append('双')
        else:
            single_str_list.append('单')
    print("大小结果:", size_str_list)
    print("单双结果:", single_str_list)
    # 获取第一项
    size_first = size_str_list[0]
    single_first = single_str_list[0]
    # 判断上一把有没有中,中了重置投钱下标
    if cur_purchase_type == '':
        pass
    elif cur_purchase_type == size_first or cur_purchase_type == single_first:
        cur_price_pos = 0
        print("中了!!!")
        get_money()
    else:
        cur_price_pos += 1
        print("没中!!!")
    # 判断相同记录条数
    repeat_count = 1
    for single in single_str_list[1:8]:
        if single == single_first:
            repeat_count += 1
        else:
            break
    if repeat_count in [1, 3, 8]:
        if single_first == '单':
            auto_buy("双", curissueNo)
        else:
            auto_buy("单", curissueNo)
    elif repeat_count == 2:
        if single_str_list[2] == single_str_list[3]:
            if single_first == '单':
                auto_buy("双", curissueNo)
            else:
                auto_buy("单", curissueNo)
        else:
            auto_buy(single_first, curissueNo)
    elif repeat_count in [4, 5, 6, 7]:
        auto_buy(single_first, curissueNo)


# 构建倍率列表,保证赢前后收益 - 投入 > 购买基数
def init_purchase_list():
    global price_list
    cost = purchase_base
    price_list = [purchase_base]
    # 其他进行动态计算
    for i in range(10):
        # 购买价格其实区间(2倍)
        start_price = purchase_base * (2 ** i)
        # 购买价格极限区间(3倍)
        end_price = purchase_base * (3 ** i)
        # 保证没把不亏就行
        for j in range(start_price, end_price + 1):
            if j * ratio - cost - j > 1 and cost + j <= round(cur_money / 2):
                cost += j
                price_list.append(j)
                break
    print("生成投入金额列表:", price_list)


# 重新登录
def login_again():
    print("重新登录!")
    fetch_cookies()
    auto_login()


if __name__ == '__main__':
    init_purchase_list()
    fetch_cookies()
    auto_login()
    predict()
    scheduler = BlockingScheduler()
    # 每隔60s下注一次
    scheduler.add_job(predict, 'interval', max_instances=10, seconds=60)
    scheduler.start()

接着就可以把脚本丢到云服务上执行了,这里用的是nohup命令让脚本在后台运行。

nohup python3 -u xiaozheng.py > xiao.out 2>&1 &

然后执行tail -f xiao.out或者cat xiao.out可以查看到日志输出记录。

因为用的是官方的接口,也没有出现接口延迟的问题...一切貌似就这样顺理成章的执行着,
然而最后的结果,依旧躲不过输得一干二净。

我开始反省,为何剧本的最后结局都是输光,人投也是采用相同的策略,人赚,脚本投就亏。

  • 1.脚本24小时跑,策略固定,而彩票规律可能是不断变化的,人偶尔也会变通下;
  • 2.人不会一直买,而且出现连续不中的时候会停止观察,找稍微稳定一点的时间点切入;

既然这样固定策略必凉,为何不让别人在投的时候,顺道也帮我投了呢,爱屋及乌


第六章:爱屋及乌

在我输光输净后小A又疯狂的炫富:

既然小A那么稳,为何不让他投的时候帮我也投了呢,坐收渔翁之利。行吧,既然接口我都有了,为何不能
自己写个APP呢?所以有了下面这样的计划:

  • 1.先写一个APP,小A登录的时,顺带也登录下我的账号,然后下注的时候,我的账号也跟着下注。
  • 2.编写API接口给APP调用,小A下注的时候顺带调用这个接口,后台接收到下注信息,批量下注。

正当我准备打开自己写好的APP截个图的时候,发现自己写的APP竟然登录不了了,啧啧,应该是昨晚
维护了,把接口改了。

行吧,顽皮,批量替换下基地址,登录成功后,竟然又自动退出来了。利用Android Profiler 性能调优工具
抓一波包,login接口是success的,lotteryOpenCache的响应码竟然是nologin

猜测是Cookie变了,打开它们的APP登录,打开结果页,抓包看看:

果不其然,多了个sto-id-20480,左侧搜下这个串东西,在哪里拿到的,过滤下,只查看响应头:

定位下可以找到:

接着是另外一段:JSESSIONID=53287B9851CF658D255A029F1426C82A,如果炮制找出是在哪个接口
的响应头set-cookie的,如下:

总结下就是依次

后续所有访问请求头cookie设置为这两个字符串即可,同样贴出大概的代码,显示接口:

然后是调用页面:

APP的下注页面:

页面简陋,但是功能齐全,好吧,接着就把APP丢给小A先帮我投着先,接下来就是写接口给自己的APP调用了,
不然怎么弄成批量的方式,这里用到的Python轻量级Web库:Flask

直接通过pip命令进行安装即可:pip install flask,官方的一个最简单示例:

# coding=utf-8
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello Flask!"


if __name__ == "__main__":
    app.run()

运行后打开127.0.0.1:500可以看到返回了Hello Flask!

关于Flask的使用,这里不会讲解,因为也不涉及到什么高深内容,更多内容可以自行查阅官方文档:http://flask.pocoo.org/docs/1.0/
简单说下我们要做的事情,需要两个接口(传参用Json字符串)。

  • add_account添加账号POST,传参:用户名与密码,拿到数据后模拟登录,拿到对应的Cookies,存到MySQL数据库中;
  • bet下注POST,传参:下注类型与下注金额,拿到数据后批量调用下注方法。

行吧,官方貌似又改接口了,又重新抓了一波包(其实就是改了跟地址而已)...

限于篇幅,不太过具体的去讲解代码,显示工程的结构:

创建了一个app目录,下面有一个__init__.py文件:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)

from app import models, views

代码中初始化了一个Flask实例,读取配置文件,创建了一个SQLAlchemy实例,导入了models和views文件。
config.py内容如下:

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:Jay12345@localhost:3306/q9g'
SQLALCHEMY_TRACK_MODIFICATIONS = True

然后是定义数据结构:账户名+密码+Cookie+账户ID(下注用),这里并不使用原生SQL语句去操作MySQL数据库,而是使用ORM框架——SQLAlchemy,直接通过pip命令安装即可:pip install flask-sqlalchemy,model.py的代码如下:

from app import db


class User(db.Model):
    __tablename = 'user'
    __table_args__ = {'useexisting': True}
    _id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    account = db.Column(db.TEXT)
    pwd = db.Column(db.TEXT)
    cookies = db.Column(db.TEXT)
    accoutId = db.Column(db.TEXT)

    @property
    def id(self):
        return self.id


if __name__ == '__main__':
    db.create_all()

还有安装一个flask-script模块,用于通过命令行来操作Flask,同样可以通过pip命令进行安装:pip install flask-script,新建一个manager.py,在里面启用Flask项目。

from app import app
from flask_script import Manager

manager = Manager(app)

if __name__ == '__main__':
    manager.run()

准备工作差不多了,接着开始编写我们的登录接口:

import hashlib
import time

import requests as r
from flask import request, jsonify

from app import app, db
from app.models import User

headers = {
    'origin': 'https://m.suibianwanba3.com',
    'user-agent': 'Mozilla/5.0 (Linux; Android 8.1.0; OE106 Build/OPM1.171019.026; wv) AppleWebKit/537.36 '
                  '(KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36 ',
    'content-type': 'application/json',
    'x-requested-with': 'com.bright.extnetiop',
}


@app.route("/add_account", methods=['GET', 'POST'])
def add_account():
    account = ''
    pwd = ''
    if request.method == 'GET':
        account = request.args.get("account")
        pwd = request.args.get("pwd")
    elif request.method == 'POST':
        account = request.json['account']
        pwd = request.json['pwd']
    # 密码加密
    hl = hashlib.md5()
    hl.update(pwd.encode(encoding='utf-8'))
    # 实例化用户实例
    user = User()
    user.account = account
    user.pwd = hl.hexdigest()
    msg = auto_login(user)
    return jsonify(
        {'code': '200', 'data': [{'account': account, 'pwd': pwd}], 'msg': (msg if msg is not None else "登录成功")})


@app.route("/bet", methods=['GET', 'POST'])
def bet():
    choose = ''
    price = ''
    cur_no = ''
    if request.method == 'GET':
        choose = request.args.get("choose")
        price = request.args.get("price")
        cur_no = request.args.get("cur_no")
    elif request.method == 'POST':
        choose = request.json['choose']
        price = request.json['price']
        cur_no = request.json['cur_no']
    # 批量下注
    result_list = []
    users = User.query.all()
    for user in users:
        result_list.append(auto_bet(user, choose, price, cur_no))
    return jsonify({'code': '200', 'data': result_list, 'msg': '访问成功'})


# 获取Cookie
def fetch_cookies(user):
    if 'cookie' in headers:
        headers.pop("cookie")
    cookie_resp = r.post("https://m.suibianwanba3.com/tools/_ajax/cache/getSiteInitData",
                         headers=headers,
                         json={"requirement": ["footerConfig", "helpConfig", "h5BannerList", "gradeList",
                                               "noticeData", "rankingList", "activityConfig", "defaultPhotoList",
                                               "lotteryConfig",
                                               "lotteryList", "rewardData", "config"], "cacheData": {}})
    if cookie_resp is not None:
        cookie = cookie_resp.headers.get('set-cookie')
        if cookie is not None:
            headers['cookie'] = cookie.split(';')[0]
            user.cookies = cookie.split(';')[0]


# 模拟登录
def auto_login(user):
    fetch_cookies(user)
    json_params = {
        'loginName': user.account,
        'loginPwd': user.pwd,
        'validCode': '',
        'validateDate': str(int(round(time.time() * 1000))),
        'isdefaultLogin': 'true'
    }
    resp = r.post("https://m.suibianwanba3.com/tools/_ajax/login", headers=headers, json=json_params)
    if resp is not None:
        if resp.json()['code'] == 'success':
            user.accoutId = resp.json()['data']['user']['userDetail']['accountId']
            db.session.add(user)
            db.session.commit()
        else:
            print(resp.json()['msg'])
        return resp.json()['msg']

运行项目,然后使用浏览器或者PostMan模拟请求:

调用这个接口数次,获取账户名+密码+Cookie+账户ID,然后存入数据库,存入后的结果如图所示:

可以,都存到数据库里,接着我们来编写下注接口:

playIds = ['K3002001010', 'K3002001011']  # 下注种类,依次为大小和单双

@app.route("/bet", methods=['GET', 'POST'])
def bet():
    choose = ''
    price = ''
    cur_no = ''
    if request.method == 'GET':
        choose = request.args.get("choose")
        price = request.args.get("price")
        cur_no = request.args.get("cur_no")
    elif request.method == 'POST':
        choose = request.json['choose']
        price = request.json['price']
        cur_no = request.json['cur_no']
    # 批量下注
    result_list = []
    users = User.query.all()
    for user in users:
        result_list.append(auto_bet(user, choose, price, cur_no))
    return jsonify({'code': '200', 'data': result_list, 'msg': '访问成功'})
    
# 下注
def auto_bet(user, choose, price, cur_no):
    play_id = playIds[0]
    if choose in ['单', '双']:
        play_id = playIds[1]
    json_params = {
        'accountId': user.accoutId,
        'clientTime': str(int(round(time.time() * 1000))),
        'gameId': 'OG1K3',
        'issue': str(cur_no),
        'item': [str({
            'methodid': 'K3002001001',
            'nums': 1,
            'rebate': '0.00',
            'times': price,
            'money': price,
            'playId': [play_id],
            'mode': '1',
            'issueNo': str(cur_no),
            'codes': choose
        })]
    }
    headers['cookie'] = user.cookies
    resp = r.post('https://m.suibianwanba3.com/tools/_ajax/OG1K3/betSingle', headers=headers, json=json_params)
    print(resp.json())
    return resp.json()

同样模拟请求一波,看看响应的结果:

这里没有做cookie过期的相关处理逻辑,做的话也比较简单,对异常信息进行过滤,然后调用登录相关的
方法重新登录,更新一下数据库里账户对应的Cookie即可。行吧,本地接口跑通了,接下来把项目部署到服务器上,
让外网能够访问我们的接口,感觉用Docker部署就有点装逼了,所以这里还是只用FTP/SFTP工具把代码上传到云服务器上。
接着是安装Nginxuwsgi

apt-get install nginx   # 能很好处理高并发的反响代理软件
pip install uwsgi   # 把HTTP协议转为WSGI协议,让Python可以直接使用

安装完nginx,访问一波服务器的公网IP如果返回下述页面代表安装成功。

接着命令行键入:python3 manager.py runserver 启动脚本,缺什么库pip命令装什么库。
出现如下页面代表项目启动成功:

接着curl命令试着调用下登录接口:

可以看到数据库里成功添加对应的账号。

接着配置uwsgi,新建一个config.ini文件作为配置文件:

touch config.ini
vim config.ini

添加下述内容:

[uwsgi]                                                                       
                                                                              
# uwsgi 启动时所使用的地址与端口                                              
socket = 127.0.0.1:8001 # 可以使用其他端口                                                                                                                  
                                                                              
# 指向网站目录                                                                                                                                              
chdir = /var/www/Q9G                                                          
                                                                              
# python 启动程序文件                                                                                                                                       
wsgi-file = manager.py                                                                                                                                      
                                                                              
# python 程序内用以启动的 application 变量名                                                                                                                
callable = app                                                                                                                                              
                                                                              
# 处理器数                                                                                                                                                  
processes = 4                                                                                                                                               
                                                                              
# 线程数                                                                                                                                                    
threads = 2                                                                                                                                                 
                                                                              
#状态检测地址                                                                 
stats = 127.0.0.1:5000                                                        
                                                                              
# 使用flask项目默认的端口,可以换但必须是flask运行时使用的端口 

接着键入下述命令运行uwsgi:

uwsgi config.ini

终端输出下述结果代表运行成功:

接着配置nginx,键入下述命令修改:

vim /etc/nginx/sites-available/default

然后添加下述内容:

server {
      listen  80;
      server_name xxx.xxx.xxx.xxx; #云服务器的公网地址

      location / {
        include      uwsgi_params;
        uwsgi_pass   127.0.0.1:8001;  # 指向uwsgi 所应用的内部地址,所有请求将转发给uwsgi 处理
        uwsgi_param UWSGI_PYHOME /home/www/Q9G/venv; # 指向虚拟环境目录
        uwsgi_param UWSGI_CHDIR  /home/www/Q9G; # 指向网站根目录
        uwsgi_param UWSGI_SCRIPT manager:app; # 指定启动程序
      }
    }

配置完执行一波重载配置的命令:

nginx -s reload

重启完Nginx再去启动uwsgi,接着PostMan访问一波公网地址:

可以很舒服,域名解析就没弄了,毕竟只是自己APP用。写完接口后,暗暗窃喜,想着改下APP,然后让
小A继续买就好了,批量赚钱搞起来。但是小A近段时间比较忙,都没怎么投。我TM..

啧啧,我的时间可是非常值钱的,怎么能白耗在等待上呢?我之前输的原因是脚本24小时固定算法跑,
我要做的只需要找个靠谱的人带着我投就行了,我突然想起刚开始认识的女孩:助理-梦婷

啧啧,舔舔,等我暴富了,老子要...


第七章:言听计从

梦婷之前拉过我进一个什么高级VIP群,就是有所谓的老师,计划员出每期的计划,跟投躺着赚钱就行。

他们用的聊天工具是有点类似于TG的:潮信,然后我伪装成一个学生仔潜伏里面暗中观察,看下这所谓的
计划员是否可靠。在蹲守了两天后,觉得貌似挺准的。

潜伏几天,发现最多也是到72倍就中了,全是这幅王总牛逼的景象(不知道还以为进了邪教)

他们采用的是三倍投策略:1,3,8,24,72,216,648,1944,5832,17496,52488...:
江苏三这类和之前玩的一分快三有点不同,开奖的时间是10分钟一把。我需要没事就盯着
手机看看计划员有没有发新的计划,然后跟着下注,有时忙起来,经常错过下注,别人跟着买都赚了,
我TM还亏了,而且老盯着,很浪费时间和经历,有点影响工作了,em...照旧,想想有没有什么办法
可以自动化这个过程,毕竟接口我都有了,只要抓这个人的下注记录就可以了。手机抓了一波包,
完全看不懂的加密,貌似有网页端,同样抓一波包。

GG,又是无能为力的加密。

对于这种JS加载数据的网页,只能使出迫不得已才能用的最低效策略:用浏览器库来模拟访问,然后获取网页远吗,然后再提取数据,
这里用到的是Selenium + Chrome无头浏览器 来获取网页端潮信的信息。关于这里Selenium的使用可以自行查阅我以前写过的文章。
捋一捋具体的实现流程:

  • 1.打开潮信的登录页(https://web.chaoxin.com/)通过短信验证或者二维码登录。
    这里采用二维码登陆的方式,显示获得二维码的图片URL,接着使用PIL库显示出来。
  • 2.手机客户端扫码授权登录后,稍等片刻,获取页面结构,找到左侧群名对应的结点,点击。
  • 3.获取右侧中的每条信息,死循环,每隔1s获取一次页面数据,通过正则提取下注信息,同时要
    记录判断是否为最新一期,避免错误和重复下注。

页面结点怎么获取,就不说了,直接给出完整代码:

import requests as r
from selenium import webdriver
from PIL import Image
from io import BytesIO
from bs4 import BeautifulSoup
import re
import time

# 提取期号,下注内容,下注倍数的正则
bet_pattern = re.compile('(\d*)期.*?【(.*)】(\d*) 倍')
# 当前下注期号
cur_no = ''

if __name__ == '__main__':
    # 设置无头浏览器
    opt = webdriver.ChromeOptions()
    opt.add_argument('--headless')
    opt.add_argument('--disable-gpu')
    browser = webdriver.Chrome(options=opt)
    browser.get("https://web.chaoxin.com/")
    time.sleep(3)
    html = browser.page_source
    # 读取显示二维码
    bs = BeautifulSoup(html, "lxml")
    img_src = bs.find('div', attrs={'class': 'qrcode-picture'}).find('img').get('src')
    img_resp = r.get(img_src)
    qc_code_image = Image.open(BytesIO(img_resp.content))
    qc_code_image.show()
    # 上面的代码会堵塞进程,扫完二维码记得关掉页面
    time.sleep(5)
    # 找到左侧群名,点击特定群组
    browser.find_element_by_css_selector('a.avatar[title="开拓者团队VIP-9群"]').click()
    # 遍历获取信息
    while True:
        cur_html = browser.page_source
        bs = BeautifulSoup(cur_html, "lxml")
        divs = bs.find_all("div", attrs={'class': 'content'})
        bet_no = ""
        bet_type = ""
        bet_money = ""
        for div in divs:
            # 正则获取下注信息
            result = bet_pattern.search(div.text)
            if result is not None:
                bet_no = result.group(1)
                bet_type = result.group(2)
                bet_money = result.group(3)
        if cur_no != bet_no and bet_type != "":
            cur_no = bet_no
            print("当前下注内容:", bet_no, bet_type, bet_money)
            time.sleep(1)

输出结果如下:

啧啧,一个监控信息,接着要做的就是替换打印下注部分的代码,当接收到最新一期的下注信息时,
去批量调我们下注的接口,啧啧,美滋滋,这次终于可以躺着赚钱了,怒砸1000多本金,超膨胀!!!

然而,现实总是打脸无情,脚本没问题,到时计划员出问题了。

正当我稳稳当当的跟着计划员的计划下注,小赚两三百的时候,噩耗来了,计划员竟然连续11手没中,打包票十手以内:

是的,你没看错,翻到52488倍了,即使你是一元起投,你这把跟的话,要跟52488!!!一元起投就要投52488,
十块起投的52w,有些100块起投的520W!其实这个时候你就应该清醒的意识到,由始至终就是一个圈套!一个让人越
陷越深的圈套。

接下来让我一一来带你了解这个圈套。

1.计划员到底是何方神圣?

这种高倍是偶尔会出现的,然后出现这种高倍,意思甩锅给计划员,然后说辞退,换个计划员。

2333,有点脑子的人都知道,这个所谓的计划员可能就是同一个人,换个头像,换个名字,换个说话的模板,
就是一个新的计划员,然后呢那些所谓的助理其实也有可能是这个人,抠脚大汉,啧啧。接着是这个计划员的
身份,每当高倍出现的时候,赌徒都怨声载道的时候,不是安抚道歉,而是鼓励充钱,洗脑,发快速充值的渠道:

23333,这屌人,要么就是直接下属员工,要么就是最高级的代理,我觉得基本就是员工了,设这个局出来。

2.计划来源

知道了第一点,就不用说了吧,这种没有开奖过程公示的东西,结果是可以操作的,赌场老板想开什么,
就开什么,想割韭菜,就割韭菜。你跟计划,想让你不中,就不中!所以你还跟他的计划吗?

3.赌徒都是傻逼吗

(总不能说自己是傻逼吧),我只能说大部分是可怜人,因为穷,挣的每一块前都是血汗钱,这种不需要付出
劳动而又能获益的方式,让他们为止痴迷。下注中奖了,跟投到没钱又中了,这种快感会刺激赌徒产生更多的肾上腺素,
让使身体处于亢奋,久而久之还会上瘾。一般带你连赢几天,赚个几百,赌徒们就觉得是跟对人了,开始加注,1块变10块,
这个时候呢,来个小高倍,让你亏一点,让后让你输,刚好差一把就中了,这个时候赌徒就会开始患得患失,我就差几百块,
如果我充了的话,这把就赚多少多少了,都怪自己,本金不够,行吧,充多点本金,跟着老师回本就好了。然后跟着所谓的
计划又赢了一些,觉得坚持多久就能回本,而且开始盈利了,然而,事实是等待下一波的清洗,或者大收割(高倍不中)

就是出于这样的循环,钱没了,充,想回本,越充越多,知道倾家荡产,有做小生意的亏光了两个月的货款,有输光家里钱
和老公闹离婚的,有输太多要跳楼的...看起来挺惨的啊,是吧,但是,实际上,那些所谓的老师,计划员,并不会怜悯
你们,你们输得越多,赚得越多,就好像蛀虫一样,慢慢蚕食你的生活。根本不存在回血,只会越输越多,要止损的话,你只能
跳出这个圈套!!!但是大部分人,很难,很难跳出来,就好像舔狗一样,明知道舔到最后不得House,还是会去舔!唉,都是可怜人。

4.韭菜割完了怎么办

  • 问题来了:这样割韭菜总有一天会割完,怎么才能有更多的韭菜?
    答案很简单:让你的下线去发展更多的下线,就是我们常说的拉新。
  • 问题又来了:怎么让韭菜们心甘情愿,积极的帮你去拉新?
    答案也很简单:给点小甜头,比如拉进来的韭菜下注累计达到1W,你能拿到100块。

是哦,看上去挺好的,拉人进来你赚钱,下注都不用下就有钱收,你拉进来的韭菜倾家荡产
找谁?还不是找你?另外,发展下线的这种做法是违法的,哪天赌场老板被逮了,连带把你也捎进去了!

5.其他

除此之外,偶尔还穿插一些鸡汤,洗脑一波,啧啧,真的把韭菜玩弄于鼓掌之中:


第八章:屠龙计划(终章)

既然都知道了是一个圈套,就没有再去写脚本的必要了,所谓的屠龙计划,其实就是连续出现某个类型后,一直反买。
他们把连续出现8此以上的开奖结果称为龙,按他们的想法是,连续出现一样结果,下次出现相反的结果概率会越来越高。
比如出现了8个大,从第九次开始卖小,知道中了为止,称为一次屠龙,这样可以降低风险和投入的金额。所以要去盯
每个地方出的开奖结果,群里有人看到会发出上海有龙,广西有龙,北京有这样的信息。用Python来做,是非常简单的
定时,然后去模拟请求每个彩种的开奖结果,数据解析处理,当出现“龙”的时候开始反买。除此之外,还有什么逮豹子
计划等等。最后的结果,都是输...

呼...长舒一口气,到此,终于写完这篇文章了,并没有所谓的大团圆结局,我也没有暴富,没有会所嫩模,
也没有包养学生妹,在亏完钱后,我又恢复到正常生活,依旧是那个搬砖的代码仔。仅以此文记录并警示
自己,做事赚钱要踏踏实实,远离投机倒把,希望读者阅读完本文后,可以吸取笔者的教训并学到一些开发
的技巧,Python是真的好玩!!!最后恭喜:

完...


Join in

欢迎大家加入小猪的Python学习交流群一起讨论,可以添加下述的机器人小号 RobotPig,验证信息里包含:
PythonpythonpyPy加群交易屁眼 中的一个关键词即可通过;发送『加群』加入群聊。
或者在公众号『抠腚男孩』中发送加群~

PS:因为今天太多人加群...我的机器人坏掉了,明天再弄或者写个脚本自动拉吧,抱歉~

机器人小号

     


参考文献


推荐阅读更多精彩内容