卡尔马克思杯练习赛满分脚本
原理
每次点击下一题,会发送如https://kamabeisai.8531.cn/api/questions/14065655622981?result=D
的请求,其中14065655622981
为题目id,result=D
为用户选择的选项,同时返回带有is_right
字段的响应,值为1则表示题用户作答正确,若为0则作答错误。同时响应中附带包含正确答案的result
,即我们可以通过每次提交的响应来获得该题的正确答案。
由于模拟练习答题次数不设限制,我们可以通过多次作答来获取大量题目id和对应的正确答案,再通过拦截每次点击下一题发送的请求,将它替换为我们收集的包含id与正确答案的请求链接即可实现满分答题。
具体代码
获取正确答案部分
import sys
from mitmproxy import http
import re
import json
import os
from mitmproxy.tools.main import mitmdump
# 用于匹配请求的正则表达式,问题ID和答案部分为可变部分
TARGET_PATTERN = re.compile(r"https://kamabeisai\.8531\.cn/api/questions/\d+\?result=[A-Za-z]+")
# 文件名,用于保存符合条件的请求链接
ANSWER_FILE = "answer.txt"
# 加载已有的链接以避免重复
if os.path.exists(ANSWER_FILE):
with open(ANSWER_FILE, "r") as f:
existing_links = set(f.read().splitlines())
else:
existing_links = set()
def response(flow: http.HTTPFlow) -> None:
# 判断请求链接是否符合目标格式
if TARGET_PATTERN.match(flow.request.url):
# 尝试解析响应的 JSON 数据
try:
data = flow.response.json()
# 检查"is_right"字段的值
if "data" in data and "question" in data["data"]:
question = data["data"]["question"]
if "is_right" in question:
with open(ANSWER_FILE, "a") as f:
if question["is_right"] == 1:
# 如果is_right为1,直接保存请求链接(确保不重复)
if flow.request.url not in existing_links:
f.write(flow.request.url + "\n")
existing_links.add(flow.request.url)
elif question["is_right"] == 0 and "result" in question:
# 如果is_right为0,将响应中的result替换请求链接中的result
parsed_url = re.match(r"(https://kamabeisai\.8531\.cn/api/questions/\d+\?result=)([A-Za-z]+)", flow.request.url)
if parsed_url:
new_url = parsed_url.group(1) + question["result"]
if new_url not in existing_links:
f.write(new_url + "\n")
existing_links.add(new_url)
except ValueError:
# 如果响应不是JSON格式,则跳过
pass
addons = [
response
]
if __name__ == "__main__":
sys.argv.append('-s')
sys.argv.append(__file__)
mitmdump()
获取到的正确答案请求链接将被保存至脚本目录下的answer.txt
文件中。
替换部分
import sys
import random
from mitmproxy import http
import re
import os
from mitmproxy.tools.main import mitmdump
# 用于匹配请求的正则表达式,问题ID和答案部分为可变部分
TARGET_PATTERN = re.compile(r"https://kamabeisai\.8531\.cn/api/questions/\d+\?result=[A-Za-z]+")
# 文件名,用于保存符合条件的请求链接
ANSWER_FILE = "answer.txt"
# 加载已有的链接用于随机选择且避免重复
if os.path.exists(ANSWER_FILE):
with open(ANSWER_FILE, "r") as f:
available_links = list(f.read().splitlines())
else:
available_links = []
USED_LINKS = set()
def request(flow: http.HTTPFlow) -> None:
# 判断请求链接是否符合目标格式
if TARGET_PATTERN.match(flow.request.url) and available_links:
# 随机选择一个未使用的链接替换请求链接
unused_links = list(set(available_links) - USED_LINKS)
if unused_links:
selected_link = random.choice(unused_links)
flow.request.url = selected_link
USED_LINKS.add(selected_link)
addons = [
request
]
if __name__ == "__main__":
sys.argv.append('-s')
sys.argv.append(__file__)
mitmdump()
该脚本将随机但不重复地从answer.txt
提取请求链接并进行替换。
免责声明
1. 使用责任:
本爬虫脚本仅供学习和研究使用。使用者需对其在使用本脚本过程中产生的一切行为及后果负责。本脚本的使用不得用于非法目的,包括但不限于未经授权的网络抓取、数据盗取或对目标网站的恶意攻击。
2. 合法性声明:
使用本爬虫脚本时,用户应确保遵守相关法律法规,包括但不限于《中华人民共和国网络安全法》、《著作权法》等法律。同时,用户应遵守目标网站的《服务条款》、《隐私政策》以及Robots.txt等规定。未经授权抓取或获取目标网站的数据可能会侵犯他人的知识产权、隐私权及其他合法权益,用户应承担因此引发的法律责任。
3. 不得滥用:
本脚本仅限于合法、合规的使用场景。请勿使用本脚本对目标网站进行恶意爬取,如过度抓取、分布式攻击、频繁请求等,以免造成对目标网站的负面影响。建议用户合理控制抓取频率,避免对网站正常服务造成干扰。
4. 网站所有权:
本脚本所抓取的任何数据都属于目标网站及其数据提供方的财产,使用者应尊重他人知识产权。任何未经授权转载或滥用这些数据的行为,使用者需要为其可能产生的后果承担全部责任。
5. 脚本修改与发布:
本脚本可以根据个人需求进行修改,但不得以任何形式进行非法传播或用于恶意用途。若您将本脚本发布给他人或分享,请务必附上免责声明,并提醒其他使用者遵守上述条款。
6. 不承担责任:
本脚本的作者和开发者不对因使用该脚本造成的任何直接或间接损失、损害、数据丢失、服务中断或任何其他法律责任负责。使用本脚本即表示您同意自行承担所有风险。
7. 禁止商业化使用:
本脚本的使用不应涉及任何未经授权的商业化行为。未经许可,不得将本脚本用于商业目的或以任何方式为他人谋取经济利益。
请仔细阅读以上免责声明并确保您在使用本爬虫脚本时遵守相关法律和规定。如有疑问,请咨询专业法律人士。