From df335fc6788734e77152af67071d6547a2be4da4 Mon Sep 17 00:00:00 2001 From: JesterHey <144512889+JesterHey@users.noreply.github.com> Date: Fri, 8 Dec 2023 17:43:42 +0800 Subject: [PATCH] Add files via upload --- 0Atip.txt | 3 + cloud.py | 14 +- get_answer.py | 52 ++++--- get_params.py | 67 +++++---- login_ui.py | 12 ++ main.py | 142 ++++++++++-------- printtxt.py | 7 +- tempCodeRunnerFile.py | 1 + ...嗨,无任何不良引导和倾向).md | 1 + 9 files changed, 171 insertions(+), 128 deletions(-) create mode 100644 0Atip.txt create mode 100644 tempCodeRunnerFile.py create mode 100644 吐槽一下(纯属口嗨,无任何不良引导和倾向).md diff --git a/0Atip.txt b/0Atip.txt new file mode 100644 index 0000000..0b16184 --- /dev/null +++ b/0Atip.txt @@ -0,0 +1,3 @@ +注意!WARNING +答案信息由生成式预训练模型生成,并不一定100%准确,甚至可能存在错误,仅作为代码参考! +并且只适用于实训编程作业。matplotlib等绘图相关作业请参见网站https://github.com/JesterHey/img_file/blob/main/educoder.md \ No newline at end of file diff --git a/cloud.py b/cloud.py index b9097bf..fa73e68 100644 --- a/cloud.py +++ b/cloud.py @@ -23,12 +23,8 @@ def is_exist(name:str) -> bool: # 如果文件存在,则下载到本地并命名为shixun_id_answer def download(name): - # 先检查本地文件是否存在,如果存在,则不下载 - if os.path.exists(name): - return - else: - # 将云端文件下载到本地并命名为shixun_id_answer.json - bucket.get_object_to_file(name, name) + # 将云端文件下载到本地并命名为shixun_id.json + bucket.get_object_to_file(name, name) # 上传函数,用于获得答案后上传到云端,此步骤在获得答案后调用 # (to do)如果用户将答案认证为正确,则将本地json中的verified参数改为True后再上传并覆盖云端文件 def upload(name): @@ -48,9 +44,7 @@ def delete(name): if is_exist(name): bucket.delete_object(name) if __name__ == '__main__': + print('测试用') # 测试用 # print(is_exist('18503.json')) - #download('18503.json') - # delete('18503.json') - - + #download('18503.json') \ No newline at end of file diff --git a/get_answer.py b/get_answer.py index 18dba81..886756a 100644 --- a/get_answer.py +++ b/get_answer.py @@ -9,32 +9,32 @@ import os import json import asyncio from cloud import download,delete - -download('apis.json') +import base64 #读取当前目录下的json文件 -#获得指定目录下的所有json文件的文件名 -def get_json(file): - return [i for i in os.listdir(file) if i.endswith('.json')] -#将file指定为当前目录 -file = os.getcwd() +#获得指定目录下的所有数字开头的json文件的文件名 +def get_json(file:str) -> list: + ''' + file:指定目录 + ''' + return [i for i in os.listdir(file) if i.endswith('.json') and i[0].isdigit()] #获得json文件名,因为程序逻辑是每次只有一个json文件,所以直接取第一个 ''' -后续准备与云服务器连接,先判断当前json是否已在云服务器上,如果在,则直接调用, +与云服务器连接,先判断当前json是否已在云服务器上,如果在,则直接调用, 节省调用API的时间和资费,否则,调用API,获得答案,并将答案存入云服务器 12.4晚更新: 阿里云服务器申请成功! ''' -json_name = get_json(file)[0] +# 以下封装成函数 #读取json文件并转换为字典 -with open(json_name,'r',encoding='utf-8') as f: - data = json.load(f) -with open('apis.json','r',encoding='utf-8') as f: - apis = json.load(f) -#获得api_key -api_key = apis['openaiapi'] -#删除本地的apis.json文件 -os.remove('apis.json') +def load_json_data(json_name:str) -> dict: + with open(json_name,'r',encoding='utf-8') as f: # json_name为无答案的json文件名 + data = json.load(f) + return data +def load_api_key() -> str: + with open('apis.json','r',encoding='utf-8') as f: # apis.json为存储api_key的json文件名 + return json.load(f)['openaiapi'] + #遍历字典,获得每一关的参数,构造请求,获得答案 ''' 用于构造请求的参数:describe,require,code @@ -52,17 +52,23 @@ promot = '现在,我想让你扮演一个Python程序员来解一个问题, # 初始化异步客户端 client = AsyncOpenAI( - api_key=api_key, + api_key=load_api_key(), base_url='https://api.op-enai.com/v1' ) def get_answer_from_api(jsonfile:dict,client:AsyncOpenAI,promot:str) -> dict: + ''' + jsonfile:本地json文件 + client:异步客户端 + promot:问题模板 + ''' data = jsonfile client = client promot = promot # 异步函数来获取答案 - async def get_answer(key,value): + async def get_answer(key,value) -> str: cid = key - des, req, code = value['describe'], value['require'], value['code'] + # code 是base64编码的字符串,需要解码 + des, req, code = value['describe'], value['require'], base64.b64decode(value['code']).decode('utf-8') question = f'问题描述:{des}\n任务需求:{req}\n根据上面的需求,你需要补充并完善代码:\n{code}' try: response = await client.chat.completions.create( @@ -85,7 +91,7 @@ def get_answer_from_api(jsonfile:dict,client:AsyncOpenAI,promot:str) -> dict: answers = sorted(answers,key=lambda x:int(x.split('/')[0])) # 在data的每个value中新增一个键值对,键为answer,值为答案,并作为返回值返回 for i in range(len(answers)): - ansewer_data[list(ansewer_data.keys())[i]]['answer'].split('/')[-1] = answers[i] + ansewer_data[list(ansewer_data.keys())[i]]['answer'] = answers[i].split('/')[-1] return ansewer_data @@ -93,9 +99,9 @@ def get_answer_from_api(jsonfile:dict,client:AsyncOpenAI,promot:str) -> dict: # 运行主函数 return asyncio.run(main(data=data)) if __name__ == '__main__': - new_data = get_answer_from_api(jsonfile=data,client=client,promot=promot) + new_data = get_answer_from_api(jsonfile=load_json_data(get_json(os.getcwd())[0]),client=client,promot=promot) print(new_data) #重写本地json文件 - with open(json_name,'w',encoding='utf-8') as f: + with open(get_json(os.getcwd())[0],'w',encoding='utf-8') as f: json.dump(new_data,f,ensure_ascii=False,indent=4) diff --git a/get_params.py b/get_params.py index e6d57c7..1a0d104 100644 --- a/get_params.py +++ b/get_params.py @@ -23,6 +23,8 @@ from lxml import etree import time import requests from cloud import is_exist,download +global retry +retry = 0 #配置参数 opt = Options() opt.add_experimental_option('detach', True) @@ -95,7 +97,7 @@ def get_parameters(url:str,user_name:str,password:str): if os.path.exists(f'{shixun_id}.json'): print('下载完成') safari.quit() - exit() + return break except Exception as e: print(e) @@ -105,15 +107,18 @@ def get_parameters(url:str,user_name:str,password:str): print('云端文件不存在,正在爬取') #获取关卡数 #点击展开关卡页面 + time.sleep(3) safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[1]/a[1]').click() - time.sleep(2) #关卡数量由 class = "flex-container challenge-title space-between" 的元素数量决定 + time.sleep(3) htmltxt = safari.page_source html = etree.HTML(htmltxt) task_num = html.xpath('count(//*[@class="flex-container challenge-title space-between"])') task_num = int(task_num) - #关闭关卡页面 - safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[3]/div[1]').click() + print(f'关卡数量为{task_num}') + #回到第一关 + time.sleep(3) + safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[3]/div[3]/div/div/div/div/div[1]/div[1]/a').click() #对于每一关,获取参数 #每一关的参数由以下元素组成: ''' @@ -127,13 +132,6 @@ def get_parameters(url:str,user_name:str,password:str): i=1 try: while i <= task_num: - safari.implicitly_wait(10) - safari.find_element(By.XPATH, '//*[@id="task-left-panel"]/div[1]/a[1]').click() - safari.implicitly_wait(10) - safari.find_element(By.XPATH,f'/html/body/div[1]/div/div/div/div[2]/section[1]/div[3]/div[3]/div/div/div/div/div[{i}]/div[1]/a').click() - time.sleep(3) - #获取课程id -> 根据url中?前面的,最后一个/后面的那部分参数构造请求,同时,似乎还需要用到cookie,User-Agent和Referer参数,这些统一用selenium在登陆后获取并组装成headers - #获取cookie,User-Agent和Referer cur_url=Referer = safari.current_url identity = cur_url.split('/')[-1].split('?')[0] id_url = f'https://data.educoder.net/api/tasks/{identity}.json?' @@ -150,13 +148,14 @@ def get_parameters(url:str,user_name:str,password:str): except BaseException: print('获取课程id失败') #获取任务描述(如果存在的话) + time.sleep(3) page_source = safari.page_source describe = obj1.findall(page_source) #获取编程要求(如果存在的话) require = obj2.findall(page_source) - #获取编辑器中的代码,由于代码都是class = "view-line"的div,先找到所有class = "view-line"的div,获取其中的所有文本,再把不同行的代码用\n连接起来 - code = safari.find_elements(By.CLASS_NAME,'view-line') - code = '\n'.join([i.text for i in code]).lstrip('\n') + #获取编辑器中的代码,采用requests抓取https://data.educoder.net/api/tasks/{identity}/rep_content.json中的content中的content + # 然后然后,这个content是一个base64编码的字符串,需要解码 + code = requests.get(f'https://data.educoder.net/api/tasks/{identity}/rep_content.json',headers=headers).json()['content']['content'] #把参数存入字典,再转换为json格式 task = { 'describe':describe[0] if len(describe) != 0 else '', @@ -168,19 +167,31 @@ def get_parameters(url:str,user_name:str,password:str): #把每一关的参数存入总的字典中 total[challenge_id] = task #去往下一关 - i += 1 - except BaseException: - print(f'{challenge_id}参数获取参数失败') - #判断爬取到的代码是否存在空值,如果存在空值,则重新爬取 - for value in total.values(): - if value['code'] == '': - print('检测到代码参数为空值,重新爬取') - safari.close() - # 再次执行本程序 - if 'Windows' in platf: - os.system('python get_params.py') + safari.implicitly_wait(10) + if i == 1: + i += 1 + safari.find_element(By.XPATH,f'//*[@id="task-right-panel"]/div[4]/div/div[2]/a').click() + elif i bool: + for i,j in data.items(): + if 'answer' in j.keys(): + return True + return False +print('到这一步,判断是否存在答案') +if is_exist_answer(json_data): + pass +else: + print('到这一步,调用api获取答案') + new_data = get_answer_from_api(jsonfile=json_data,client=client,promot=promot) + # 重写本地json文件 + with open(j_name,'w',encoding='utf-8') as f: + json.dump(new_data,f,ensure_ascii=False,indent=4) -# # 检查userinfo.json文件是否存在,存在,则程序继续 -# assert os.path.exists('userinfo.json'), 'userinfo.json文件不存在,请检查' - -# # 先读取userinfo.json文件,获得用户名、密码和实训网址 -# with open('userinfo.json', 'r') as f: -# userinfo = json.load(f) -# user_name = userinfo['name'] -# password = userinfo['pwd'] -# url = userinfo['url'] - -# # 调用get_params.py获得参数,完成后本地应该有一个json文件,里面有参数 -# get_parameters(url,user_name,password) - -# # 获得本地所有数字开头的json文件名 -# j_name = readJson()[0] -# # 判断j_name文件中是否有answer -# with open(j_name,'r',encoding='utf-8') as f: -# json_data = json.load(f) - -# def is_exist_answer(data:dict) -> bool: -# for i,j in data.items(): -# if 'answer' in j.keys(): -# return True -# return False - -# if is_exist_answer(json_data): -# pass -# else: -# # 调用API获取答案 -# new_data = get_answer_from_api(jsonfile=json_data,client=client,promot=promot) -# # 重写本地json文件 -# with open(j_name,'w',encoding='utf-8') as f: -# json.dump(new_data,f,ensure_ascii=False,indent=4) - -# # 上面的判断执行完后,本地的json文件中已经有answer了,下面实现信息展示 -# # 使用readJson函数读取当前目录下的所有json文件 -# JSONS = readJson() -# # 构建txt文件 -# # transToTxt(JSONS) -# # 展示txt文件 -print('哈哈终于要写完了') -import haha -#询问用户是否认证答案正确(下午新开一个模块实现) \ No newline at end of file +# 上面的判断执行完后,本地的json文件中已经有answer了,下面实现信息展示 +# 先删除本地api.json文件 +os.remove('apis.json') +# 使用readJson函数读取当前目录下的所有json文件 +JSS = readJson() +# 构建txt文件 +transToTxt(JSS) +# 展示txt文件 +# print('哈哈终于要写完了') +print_txt(get_all_txt_file(os.getcwd())) +# #打印完,删除本地txt和json文件 +for i in JSS: + os.remove(i) +# 删除本地所有数字开头的txt文件 +for i in os.listdir(): + if i.split('.')[0].isdigit() and i.endswith('.txt'): + os.remove(i) +# 判断云端是否存在答案json,如果不存在,则上传 +if not is_exist(j_name): + upload(j_name) \ No newline at end of file diff --git a/printtxt.py b/printtxt.py index 0670f7c..c6ba078 100644 --- a/printtxt.py +++ b/printtxt.py @@ -89,12 +89,13 @@ def print_txt(json_path: list): # 传入json文件路径 def get_all_txt_file(path): - file_list = [] + file_list = ['0Atip.txt'] for root, dirs, files in os.walk(path): for file in files: if file.endswith('.txt') and file[0].isdigit(): file_list.append(os.path.join(root, file)) + file_list.sort(key=lambda x:x.split('.')[0]) return file_list - -print_txt(get_all_txt_file(os.getcwd())) +if __name__ == '__main__': + print_txt(get_all_txt_file(os.getcwd())) \ No newline at end of file diff --git a/tempCodeRunnerFile.py b/tempCodeRunnerFile.py new file mode 100644 index 0000000..32752dc --- /dev/null +++ b/tempCodeRunnerFile.py @@ -0,0 +1 @@ +WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "someElementID"))) \ No newline at end of file diff --git a/吐槽一下(纯属口嗨,无任何不良引导和倾向).md b/吐槽一下(纯属口嗨,无任何不良引导和倾向).md new file mode 100644 index 0000000..075e38b --- /dev/null +++ b/吐槽一下(纯属口嗨,无任何不良引导和倾向).md @@ -0,0 +1 @@ +# 我真甜蜜地服了互联网上一群傻逼到处TMD跟喷史一样到处拉史一样的垃圾信息,就TM配置个代理一帮牛马讲得TMD的天花乱坠,什么TM云函数,Cloudfare代理,Njanx反向代理真NMSL的一群人。好不容易TND有几个人直接给TM代理地址又不说明要加/v1,官方文档也TM是一堆SB写的吗,API用法更新了就TM给几个示例代码是怕GitHub存储费用太高吗?社区和和论坛也是一帮勾石东西,TM跟东晋士大夫一样搁哪清谈半天NM一个给代码示例的人都没有,屈指可数的几个代码又是API1.2版本之前的,用不了一点捏。我TM找整整2天就差冲OpenAI官网的时候无意间看到CSDN上的[这篇帖子](https://blog.csdn.net/qq_36265860/article/details/130111351)。WC,什么叫清晰,什么叫对比,什么叫做程序员的自我修养,TM我那么简单的一个问题就只有这个老哥给出解答。我NM,真的,当时真的想嫁给这个哥了。我宣布CSDN就是世界第一技术论坛,那些说看CSDN是屎里淘食的人下赛季池史。以后多看书,再上网查这种技术问题我也是SB。暂时就想到那么多,哈哈。