基于python的安全知识自动搜题

前言:

        近期学校要求强制去微信公众号小程序进行:安全知识答题,连续5天,每次25题,时间由10分钟逐级递减,感觉题量有点大,而且每天都要答题,所以我就在想有没有什么办法能进行自动答题,同时也可以来锻炼自己的技术,经过不断踩坑失败后,终于成功了。效果如下图所示:

前期思路: 

        1.selenium自动化:首先我想到的就是,能不能分享小程序链接,在网页做,可以用selenium来实现,不过我发现这个小程序链接根本就分享不了,这种方法直接pass。

        2.抓包:可以用一些抓包软件来抓包解析请求分析参数,但是难度肯定极高,而且说不定一堆反爬,鉴于我逆向基础较差这种方法pass

        3.用模拟器模拟手机,然后登陆微信进行操作,最后发现模拟器登陆微信打不开这个做题小程序,不知道是不是反扒措施,非常恼火。

解决办法:

        山穷水尽疑无路,柳暗花明又一村。经过一次次碰壁,我最终选择了一个最笨的办法:

        1.使用投屏软件将手机投屏到电脑屏幕上

        2.使用python的pyautogui库,将电脑截屏,刚好把题目截下来

        3.使用百度api图片文字识别技术,将截屏的问题识别出来

        4.获取题库,采用正则表达式将问题和答案保存进字典里

        5.根据问题和字典获取答案

 解决过程及代码:

1.使用投屏软件将手机投屏到电脑屏幕上

这里我使用的软件是todesk,手机和电脑各下载一个,就可以投屏了

 2.使用python的pyautogui库,将电脑截屏,刚好把题目截下来

其中(x1,y1)是左上角坐标, (x2,y2)是右下角坐标

import pyautogui


# 获取屏幕截图
def save_screen(x1, y1, x2, y2):
    screenshot = pyautogui.screenshot()
    cropped_screenshot = screenshot.crop((x1, y1, x2, y2))
    cropped_screenshot.save('cropped_screenshot.png')
    
    
save_screen(66, 400, 730, 1500)
  3.使用百度api图片文字识别技术,将截屏的问题识别出来 

        这里需要去百度智能云-登录注册账号,创建应用,把下面的api_key和secret_key换成自己的就行了

import base64
import urllib
import requests

API_KEY = "您的API_KEY "
SECRET_KEY = "您的SECRET_KEY "


def get_text(filaPath):
    url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=" + get_access_token()
    image = get_file_content_as_base64(filaPath, True)
    payload = f'image={image}'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    return response.text


def get_file_content_as_base64(path, urlencoded=False):
    """
    获取文件base64编码
    :param path: 文件路径
    :param urlencoded: 是否对结果进行urlencoded
    :return: base64编码信息
    """
    with open(path, "rb") as f:
        content = base64.b64encode(f.read()).decode("utf8")
        if urlencoded:
            content = urllib.parse.quote_plus(content)
    return content


def get_access_token():
    """
    使用 AK,SK 生成鉴权签名(Access Token)
    :return: access_token,或是None(如果错误)
    """
    url = "https://aip.baidubce.com/oauth/2.0/token"
    params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
    return str(requests.post(url, params=params).json().get("access_token"))


get_text("images/2.png")
4.获取题库,采用正则表达式将问题和答案保存进字典里 

         这是一份题库,里面涵盖了绝大部分原题,不会写代码的把文字复制进文档,按ctrl+f搜索题也可以查到题和答案。

        也可以将下列文字保存进txt文件,然后使用正则表达式进行解析,由于题库格式问题我踩了不少坑,我列举一下我踩过的坑:

        我开始发现的规律是每道题都以 题号(数字)+开头 ,以  ()。结尾,所以我开始写的正则表达式就是        res = re.findall('\d{1,3}、(.*?)()。', text, re.S)        但是很快我就发现,匹配的少了几十道题,误差较大,在我仔细核对后发现:

        第一个坑:

        问题:有些题不以()。为结尾,这就导致很多题没匹配上

        解决方法:在我的一番观察后发现,虽然很多题空不在最后,但是每到题结束后肯定有选项吧,第一个选项就是选项A,改进后的代码: res = re.findall('\d{1,3}、(.*?)A', text, re.S) 确实多匹配到很多数据,但是还是有遗漏。

        第二个坑:

        问题:有些题不以 题号(数字)+开头,比如有的是题号(数字)+或者题号(数字)+空格

        解决方法res = re.findall('\d{1,3}[、\s \\.](.*?)A', text, re.S),这样不论是以 点 顿号 还是空格开头,都能匹配上了。

        第三个坑:

        问题:有些题的选项部分甚至没有ABCD,只有简单的换行,而且题目还有几十个,看到这我一下子就懵了,没办法题库质量太差了。

        解决方法res = re.findall('\d{1,3}[、\s \\.](.*?)答案', text, re.S),这样即使有的题没有abcd选项,至少有“参考答案”这几个字是全的(有的参考两个字都没有,所以我匹配的是答案)这样一下就能直接匹配一整道题,答案的匹配就容易很多了answer= re.findall('答案.*?(\w{1,7}\s', text, re.S)因为答案有单选和多选,而且有的多选很恶心中间放空格。

        第三个坑:

        问题:有些问题没有题号,导致无法匹配

        解决方法:这下真的没办法了,还好不是很多,只能一个一个去加了,如果大家有什么好办法欢迎来评论区讨论。

 5.根据问题和字典获取答案

        这里我将识别文本重新拼接了一下,可以直接返回第count张图片的问题

def get_question(count):
    url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=" + get_access_token()
    image = get_file_content_as_base64(f"images/{count}.png", True)
    payload = f'image={image}'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    data = json.loads(response.text)
    words_result = data['words_result']
    question = ''
    flag = False
    for result in words_result:
        words = result['words']
        if '【判断】' in words or '【多选】' in words or '【单选】' in words:
            flag = True
        if flag:
            question += words
        if '()' in words:
            flag = False
    print('问题:', question)
    return question

结果如下: 

主函数如下:

1.首先加载保存好的字典

2.为了能够持续识别,采用while True循环

3.屏幕区域截图

4.通过截图获取问题

5.为了防止截图识别到的文字和题库有细微差别,这里我选取了识别到的问题中两个关键词,判断题库里的问题是否同时包含这俩关键词,如果同时包含,说明大概率就是这道题,输出问题以及结果就行。

优化思路:可以选用机器学习里的知识,求 截图问题的文本 所有题库里的问题 做相关性分析,进行排序找到相似度最高的,输出答案。

def main():
    # 加载题库
    dan_xuan = load_answer('构建题库/单选.json')
    duo_xuan = load_answer('构建题库/多选.json')
    pan_duan = load_answer('构建题库/判断.json')
    x1, y1, x2, y2 = 66, 400, 730, 1500
    count = 0
    while True:
        s = input('是否继续?')
        count += 1
        save_screen(x1, y1, x2, y2, count)
        q = get_question(count)
        s1 = q[8:11]
        ss = q[-8:-4]
        print('关键词: ', s1, ss)
        print()
        if '【单选】' in q:
            for k, v in dan_xuan.items():
                if ss in k and s1 in k:
                    print('搜索结果:'+k, '答案:'+v)
        if '【多选】' in q:
            for k, v in duo_xuan.items():
                if ss in k and s1 in k:
                    print('搜索结果:' + k, '答案:' + v)
        if '【判断】' in q:
            for k, v in pan_duan.items():
                if ss in k and s1 in k:
                    print('搜索结果:'+k, '答案:'+v)
        print('\n\n\n')

全部代码:

import base64
import json
import urllib
import pyautogui
import requests

API_KEY = "您的API_KEY "
SECRET_KEY = "您的SECRET_KEY "


def get_file_content_as_base64(path, urlencoded=False):
    with open(path, "rb") as f:
        content = base64.b64encode(f.read()).decode("utf8")
        if urlencoded:
            content = urllib.parse.quote_plus(content)
    return content


def get_access_token():
    url = "https://aip.baidubce.com/oauth/2.0/token"
    params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
    return str(requests.post(url, params=params).json().get("access_token"))


# 获取屏幕截图
def save_screen(x1, y1, x2, y2, i):
    screenshot = pyautogui.screenshot()
    cropped_screenshot = screenshot.crop((x1, y1, x2, y2))
    cropped_screenshot.save(f'images/{i}.png')


#加载json文件读取为字典
def load_answer(fileName):
    with open(fileName, 'r') as file:
        data_dict = json.load(file)
    return data_dict


#获取第i张图片的 问题 的文本
def get_question(count):
    url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate?access_token=" + get_access_token()
    image = get_file_content_as_base64(f"images/{count}.png", True)
    payload = f'image={image}'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    data = json.loads(response.text)
    words_result = data['words_result']
    question = ''
    flag = False
    for result in words_result:
        words = result['words']
        if '【判断】' in words or '【多选】' in words or '【单选】' in words:
            flag = True
        if flag:
            question += words
        if '()' in words:
            flag = False
    print('问题:', question)
    return question


def main():
    # 加载题库
    dan_xuan = load_answer('构建题库/单选.json')
    duo_xuan = load_answer('构建题库/多选.json')
    pan_duan = load_answer('构建题库/判断.json')
    x1, y1, x2, y2 = 66, 400, 730, 1500
    count = 0
    while True:
        s = input('是否继续?')
        count += 1
        save_screen(x1, y1, x2, y2, count)
        q = get_question(count)
        s1 = q[8:11]
        ss = q[-8:-4]
        print('关键词: ', s1, ss)
        print()
        if '【单选】' in q:
            for k, v in dan_xuan.items():
                if ss in k and s1 in k:
                    print('搜索结果:'+k, '答案:'+v)
        if '【多选】' in q:
            for k, v in duo_xuan.items():
                if ss in k and s1 in k:
                    print('搜索结果:' + k, '答案:' + v)
        if '【判断】' in q:
            for k, v in pan_duan.items():
                if ss in k and s1 in k:
                    print('搜索结果:'+k, '答案:'+v)
        print('\n\n\n')


if __name__ == '__main__':
    main()

小猿搜题Python自动比赛的代码通常涉及网络爬虫、自动化测试和竞赛规则的理解。这类代码的主要目的是模拟用户在小猿搜题平台上做题的过程,通过分析题目、输入答案并提交以获取评分。以下是一个简单的概述: 1. **环境设置**:首先需要安装Python的requests库用于发送HTTP请求,BeautifulSoup或lxml库用于解析HTML页面。 ```python import requests from bs4 import BeautifulSoup ``` 2. **登录和模拟操作**:编写函数来模拟登录,然后根据题目列表的URL获取题目详情,解题并填写答案。 ```python def login(username, password): # 发送登录请求... def get_problem(problem_id): # 发送请求获取问题详情,解析HTML... ``` 3. **答题处理**:解析题目信息,如题型、选项等,并编写解题逻辑。 ```python def solve_question(question): # 根据题型解析并给出答案... return answer ``` 4. **提交答案**:将解答的答案提交到比赛系统。 ```python def submit_answer(answer, problem_id): # 发送提交答案的请求... ``` 5. **循环和控制流程**:通常会设置一个循环,对每个问题进行上述操作,直到所有题目完成或达到特定的比赛限制。 ```python for i in range(total_problems): answer = solve_question(get_problem(i)) submit_answer(answer, i) ``` 请注意,实际的代码可能因平台的反爬虫策略而有所不同,而且公开分享这类代码可能会违反平台规定。因此,在进行此类活动时一定要遵守相关规定,并尊重其他用户的权益。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值