предисловие
Вот в чем дело: прошел месяц с тех пор, как Nuggets запустили лотерею с регистрацией, и прошел 31 день с тех пор, как они настояли на том, чтобы зарегистрироваться.
Как показано на рисунке, количество сэкономленных бриллиантов составляет 23834. (PS: Часть бриллиантов была потрачена на тестирование и дешевые руки, так что должно быть около 30 000 бриллиантов.)
Итак, 23834 бриллианта, 200 бриллиантов потребляются в каждом розыгрыше, сколько всего требуется розыгрышей?
Ответ прост, результат округления в меньшую сторону:119Второсортный. Если вы каждый раз нажимаете и ждете на странице, это взад и вперед действительно ручная работа.
PS: На самом деле ответ на этот расчет не готов, окончательный ответ скажу позже.153Второсортный.
В соответствии с принципом ничего не делать, если вы можете написать код, полностью использовать преимущества программистов и написать сценарий, который заменит мою лотерею.
анализ проблемы
Одним словом: способ реализации лотереи Nuggets — это front-end анимация + back-end реализация интерфейса. Таким образом, настоящее действие лотереи заключается в вызове интерфейса, а интерфейс отображает логику результата.
Нечего сказать, какой интерфейс вызывается, когда Google Chrome открывает инструменты разработчика, чтобы увидеть лотерею. эмм....
Как показано на рисунке, интерфейс, вызываемый при входе в системуhttps://api.juejin.cn/growth_api/v1/lottery/draw
Код
Приведенный выше анализ лотереи требует только вызова интерфейса лотереи, после чего круговая лотерея может быть проведена напрямую. Запустите как открытую копию режима разработки и вставьте session_id из файла cookie. Вставьте в скрипт, чтобы разыграть лотерею.
import requests
from requests import cookies
class Juejin(object):
# 掘金抽奖 URL
lottery_url = "https://api.juejin.cn/growth_api/v1/lottery/draw"
def __init__(self, driver_cookies=None, cookie_obj=None):
self.session = requests.session()
if driver_cookies:
for cookie in driver_cookies:
cookie_obj = requests.cookies.create_cookie(
domain=cookie.get("domain"),
name=cookie.get("name"),
value=cookie.get("value")
)
self.session.cookies.set_cookie(cookie_obj)
elif cookie_obj:
self.session.cookies.set_cookie(cookie_obj)
else:
raise Exception("Cookie is Blank")
def request(self, *args, **kwargs):
response = self.session.request(*args, **kwargs)
if response.status_code != 200:
raise Exception("Request error")
return response.json()
def draw_lottery(self):
return self.request("post", self.lottery_url)
def lottery():
# session id 自行设置
session_id = ""
cookie = requests.cookies.create_cookie(
domain=".juejin.cn",
name="sessionid",
value=session_id
)
juejin = Juejin(cookie_obj=cookie)
gift = {}
num = 1
while True:
result = juejin.draw_lottery()
if result.get("err_no") == 0:
lottery_name = result.get("data", {}).get("lottery_name")
if gift.get(lottery_name):
gift[lottery_name] += 1
else:
gift[lottery_name] = 1
print(f"第{num}次-抽奖结果为:{lottery_name}")
num += 1
else:
print(result.get("err_msg"))
break
print(f"总抽奖次数为:{num-1}")
print("最终抽奖结果为:")
for k, v in gift.items():
print(f"礼物:{k} ---- 个数:{v}")
Отображение результатов работы программы (здесь протестированы результаты десяти розыгрышей лотереи):
第1次-抽奖结果为:66矿石
第2次-抽奖结果为:66矿石
第3次-抽奖结果为:Bug
第4次-抽奖结果为:66矿石
第5次-抽奖结果为:66矿石
第6次-抽奖结果为:Bug
第7次-抽奖结果为:66矿石
第8次-抽奖结果为:66矿石
第9次-抽奖结果为:Bug
第10次-抽奖结果为:66矿石
总抽奖次数为:{10}
礼物:66矿石 ---- 个数:7
礼物:Bug ---- 个数:3
Витрина результатов лотереи
Всего бриллиантов: 23834 Количество розыгрышей: 153 раза
Подарок-66 Руда: 106 Подарок-жук: 47
Подытожим: вероятность вытянуть 66 руд 69,28%, а вероятность вытянуть жука 30,72%.
Лотерейная вероятность тестирования 10 раз в основном согласуется с лотерейной вероятностью тестирования 153 раза.
划重点:此次试验证明掘金抽到 T恤、抱枕、Switch 的概率基本等于零,各位小伙伴不要心存幻想了。
Думать и подводить итоги
- Как использовать программу для реализации алгоритма лотереи, похожей на Наггетс?
Метод реализации очень прост, чтобы контролировать результат лотереи, настраивая интервал. Ниже приведена простая демонстрация кода:
import random
# 66矿石与Bug的比重为 7:3 [0-700)的随机数为66矿石,[700-1000)为Bug
def draw():
temp = random.randint(0, 1000)
if temp < 700:
return "66矿石"
else:
return "Bug"
- Предполагая, что у меня 23834 бриллианта, каково максимальное количество розыгрышей?
# 初始化钻石数
num = 23834
# 66钻石获取概率
rate = 0.7
# 抽奖次数
count = 0
while num >= 200:
t, r = divmod(num,200)
count += t
num = (66 * t + r) * rate
print(count)
# 153.0
JS-версия
Друзья в области комментариев надеются получить версию JS и специально обновить интерфейсные скрипты.
Следующий код можно запустить в консоли браузера (проверено только в хроме).
Примечание. Для запуска скопируйте и вставьте прямо в консоль. Раз операцию нельзя остановить, это очень полезно. . .
stime = Date.parse(new Date());
result = {}
count = 0
flag = true
while (flag) {
obj = await fetch('https://api.juejin.cn/growth_api/v1/lottery/draw', {
method: 'POST',
credentials: "include",
headers: {
'Content-type': 'application/json; charset=UTF-8'
}
})
.then(res => {
obj = res.json()
return obj
})
if (obj.err_no === 0) {
if (obj.data.lottery_name in result) {
result[obj.data.lottery_name] += 1
} else {
result[obj.data.lottery_name] = 1
}
count ++
} else {
flag = false
}
}
etime = Date.parse(new Date())
console.log("抽奖次数为:" + count)
console.log("抽奖花费时间为:", (etime - stime)/1000 + " 秒" )
console.log("抽奖奖品明细")
Object.keys(result).forEach(key => console.log("奖品:" + key + "--数量:" + result[key] ))
// 抽奖次数为:3
// 抽奖花费时间为: 1 秒
// 抽奖奖品明细
// 奖品:66矿石--数量:2