Add files via upload

master
JesterHey 2 years ago committed by GitHub
parent 949a1525d8
commit df335fc678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
注意WARNING
答案信息由生成式预训练模型生成并不一定100%准确,甚至可能存在错误,仅作为代码参考!
并且只适用于实训编程作业。matplotlib等绘图相关作业请参见网站https://github.com/JesterHey/img_file/blob/main/educoder.md

@ -23,12 +23,8 @@ def is_exist(name:str) -> bool:
# 如果文件存在则下载到本地并命名为shixun_id_answer # 如果文件存在则下载到本地并命名为shixun_id_answer
def download(name): def download(name):
# 先检查本地文件是否存在,如果存在,则不下载 # 将云端文件下载到本地并命名为shixun_id.json
if os.path.exists(name): bucket.get_object_to_file(name, name)
return
else:
# 将云端文件下载到本地并命名为shixun_id_answer.json
bucket.get_object_to_file(name, name)
# 上传函数,用于获得答案后上传到云端,此步骤在获得答案后调用 # 上传函数,用于获得答案后上传到云端,此步骤在获得答案后调用
# (to do)如果用户将答案认证为正确则将本地json中的verified参数改为True后再上传并覆盖云端文件 # (to do)如果用户将答案认证为正确则将本地json中的verified参数改为True后再上传并覆盖云端文件
def upload(name): def upload(name):
@ -48,9 +44,7 @@ def delete(name):
if is_exist(name): if is_exist(name):
bucket.delete_object(name) bucket.delete_object(name)
if __name__ == '__main__': if __name__ == '__main__':
print('测试用')
# 测试用 # 测试用
# print(is_exist('18503.json')) # print(is_exist('18503.json'))
#download('18503.json') #download('18503.json')
# delete('18503.json')

@ -9,32 +9,32 @@ import os
import json import json
import asyncio import asyncio
from cloud import download,delete from cloud import download,delete
import base64
download('apis.json')
#读取当前目录下的json文件 #读取当前目录下的json文件
#获得指定目录下的所有json文件的文件名 #获得指定目录下的所有数字开头的json文件的文件名
def get_json(file): def get_json(file:str) -> list:
return [i for i in os.listdir(file) if i.endswith('.json')] '''
#将file指定为当前目录 file:指定目录
file = os.getcwd() '''
return [i for i in os.listdir(file) if i.endswith('.json') and i[0].isdigit()]
#获得json文件名因为程序逻辑是每次只有一个json文件所以直接取第一个 #获得json文件名因为程序逻辑是每次只有一个json文件所以直接取第一个
''' '''
后续准备与云服务器连接先判断当前json是否已在云服务器上如果在则直接调用 与云服务器连接先判断当前json是否已在云服务器上如果在则直接调用
节省调用API的时间和资费否则调用API获得答案并将答案存入云服务器 节省调用API的时间和资费否则调用API获得答案并将答案存入云服务器
12.4晚更新 12.4晚更新
阿里云服务器申请成功 阿里云服务器申请成功
''' '''
json_name = get_json(file)[0] # 以下封装成函数
#读取json文件并转换为字典 #读取json文件并转换为字典
with open(json_name,'r',encoding='utf-8') as f: def load_json_data(json_name:str) -> dict:
data = json.load(f) with open(json_name,'r',encoding='utf-8') as f: # json_name为无答案的json文件名
with open('apis.json','r',encoding='utf-8') as f: data = json.load(f)
apis = json.load(f) return data
#获得api_key def load_api_key() -> str:
api_key = apis['openaiapi'] with open('apis.json','r',encoding='utf-8') as f: # apis.json为存储api_key的json文件名
#删除本地的apis.json文件 return json.load(f)['openaiapi']
os.remove('apis.json')
#遍历字典,获得每一关的参数,构造请求,获得答案 #遍历字典,获得每一关的参数,构造请求,获得答案
''' '''
用于构造请求的参数describe,require,code 用于构造请求的参数describe,require,code
@ -52,17 +52,23 @@ promot = '现在我想让你扮演一个Python程序员来解一个问题
# 初始化异步客户端 # 初始化异步客户端
client = AsyncOpenAI( client = AsyncOpenAI(
api_key=api_key, api_key=load_api_key(),
base_url='https://api.op-enai.com/v1' base_url='https://api.op-enai.com/v1'
) )
def get_answer_from_api(jsonfile:dict,client:AsyncOpenAI,promot:str) -> dict: def get_answer_from_api(jsonfile:dict,client:AsyncOpenAI,promot:str) -> dict:
'''
jsonfile:本地json文件
client:异步客户端
promot:问题模板
'''
data = jsonfile data = jsonfile
client = client client = client
promot = promot promot = promot
# 异步函数来获取答案 # 异步函数来获取答案
async def get_answer(key,value): async def get_answer(key,value) -> str:
cid = key 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}' question = f'问题描述:{des}\n任务需求:{req}\n根据上面的需求,你需要补充并完善代码:\n{code}'
try: try:
response = await client.chat.completions.create( 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])) answers = sorted(answers,key=lambda x:int(x.split('/')[0]))
# 在data的每个value中新增一个键值对键为answer值为答案并作为返回值返回 # 在data的每个value中新增一个键值对键为answer值为答案并作为返回值返回
for i in range(len(answers)): 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 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)) return asyncio.run(main(data=data))
if __name__ == '__main__': 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) print(new_data)
#重写本地json文件 #重写本地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) json.dump(new_data,f,ensure_ascii=False,indent=4)

@ -23,6 +23,8 @@ from lxml import etree
import time import time
import requests import requests
from cloud import is_exist,download from cloud import is_exist,download
global retry
retry = 0
#配置参数 #配置参数
opt = Options() opt = Options()
opt.add_experimental_option('detach', True) 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'): if os.path.exists(f'{shixun_id}.json'):
print('下载完成') print('下载完成')
safari.quit() safari.quit()
exit() return
break break
except Exception as e: except Exception as e:
print(e) print(e)
@ -105,15 +107,18 @@ def get_parameters(url:str,user_name:str,password:str):
print('云端文件不存在,正在爬取') print('云端文件不存在,正在爬取')
#获取关卡数 #获取关卡数
#点击展开关卡页面 #点击展开关卡页面
time.sleep(3)
safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[1]/a[1]').click() safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[1]/a[1]').click()
time.sleep(2)
#关卡数量由 class = "flex-container challenge-title space-between" 的元素数量决定 #关卡数量由 class = "flex-container challenge-title space-between" 的元素数量决定
time.sleep(3)
htmltxt = safari.page_source htmltxt = safari.page_source
html = etree.HTML(htmltxt) html = etree.HTML(htmltxt)
task_num = html.xpath('count(//*[@class="flex-container challenge-title space-between"])') task_num = html.xpath('count(//*[@class="flex-container challenge-title space-between"])')
task_num = int(task_num) task_num = int(task_num)
#关闭关卡页面 print(f'关卡数量为{task_num}')
safari.find_element(By.XPATH,'//*[@id="task-left-panel"]/div[3]/div[1]').click() #回到第一关
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 i=1
try: try:
while i <= task_num: 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中?前面的,最后一个/后面的那部分参数构造请求同时似乎还需要用到cookieUser-Agent和Referer参数这些统一用selenium在登陆后获取并组装成headers
#获取cookieUser-Agent和Referer
cur_url=Referer = safari.current_url cur_url=Referer = safari.current_url
identity = cur_url.split('/')[-1].split('?')[0] identity = cur_url.split('/')[-1].split('?')[0]
id_url = f'https://data.educoder.net/api/tasks/{identity}.json?' 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: except BaseException:
print('获取课程id失败') print('获取课程id失败')
#获取任务描述(如果存在的话) #获取任务描述(如果存在的话)
time.sleep(3)
page_source = safari.page_source page_source = safari.page_source
describe = obj1.findall(page_source) describe = obj1.findall(page_source)
#获取编程要求(如果存在的话) #获取编程要求(如果存在的话)
require = obj2.findall(page_source) require = obj2.findall(page_source)
#获取编辑器中的代码,由于代码都是class = "view-line"的div,先找到所有class = "view-line"的div获取其中的所有文本再把不同行的代码用\n连接起来 #获取编辑器中的代码,采用requests抓取https://data.educoder.net/api/tasks/{identity}/rep_content.json中的content中的content
code = safari.find_elements(By.CLASS_NAME,'view-line') # 然后然后这个content是一个base64编码的字符串需要解码
code = '\n'.join([i.text for i in code]).lstrip('\n') code = requests.get(f'https://data.educoder.net/api/tasks/{identity}/rep_content.json',headers=headers).json()['content']['content']
#把参数存入字典再转换为json格式 #把参数存入字典再转换为json格式
task = { task = {
'describe':describe[0] if len(describe) != 0 else '', '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 total[challenge_id] = task
#去往下一关 #去往下一关
i += 1 safari.implicitly_wait(10)
except BaseException: if i == 1:
print(f'{challenge_id}参数获取参数失败') i += 1
#判断爬取到的代码是否存在空值,如果存在空值,则重新爬取 safari.find_element(By.XPATH,f'//*[@id="task-right-panel"]/div[4]/div/div[2]/a').click()
for value in total.values(): elif i<task_num:
if value['code'] == '': i += 1
print('检测到代码参数为空值,重新爬取') safari.find_element(By.XPATH,f'//*[@id="task-right-panel"]/div[4]/div/div[2]/a[2]').click()
safari.close()
# 再次执行本程序
if 'Windows' in platf:
os.system('python get_params.py')
else: else:
os.system('python3 get_params.py') i += 1
except Exception as e:
print(e)
print(f'{i}关参数获取参数失败')
#判断爬取到的代码是否存在空值或者键的数量是否与关卡数量相等,如果不相等,则说明爬取失败,需要重新爬取
# if len(total) != task_num:
# print('参数爬取失败,正在重新爬取')
# get_parameters(url,user_name,password)
# else:
# for i,j in total.items():
# if j['code'] == '':
# print('参数爬取失败,正在重新爬取')
# get_parameters(url,user_name,password)
#把参数写入本地json文件中文件名字与shixun_name相同键为course_id值为一个列表列表中每个元素为一个字典字典中包含每一关的参数 #把参数写入本地json文件中文件名字与shixun_name相同键为course_id值为一个列表列表中每个元素为一个字典字典中包含每一关的参数
with open(f'{shixun_id}.json','w',encoding='utf-8') as f: with open(f'{shixun_id}.json','w',encoding='utf-8') as f:
json.dump(total,f,ensure_ascii=False,indent=4) json.dump(total,f,ensure_ascii=False,indent=4)
@ -189,9 +200,9 @@ def get_parameters(url:str,user_name:str,password:str):
safari.quit() safari.quit()
else: else:
print('这不是一个实训作业') print('这不是一个实训作业')
exit() return
if __name__ == '__main__': if __name__ == '__main__':
url = 'https://www.educoder.net/tasks/27V4D95N/1191515/vmxpzae734bj?coursesId=27V4D95N' url = 'https://www.educoder.net/tasks/27V4D95N/1191512/lfi2gqtnueb8?coursesId=27V4D95N'
user_name = 'hnu202311020126' user_name = 'hnu202311020126'
password = 'hzy123456' password = 'hzy123456'
get_parameters(url,user_name,password) get_parameters(url,user_name,password)

@ -5,6 +5,7 @@ import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel
from PyQt5.QtCore import Qt,QTimer from PyQt5.QtCore import Qt,QTimer
from PyQt5.QtGui import QPixmap, QPainter from PyQt5.QtGui import QPixmap, QPainter
from PyQt5.QtWidgets import QCheckBox
import platform import platform
from solve_path import b2_path, b2txt_path from solve_path import b2_path, b2txt_path
import json import json
@ -23,15 +24,20 @@ class MyApp(QWidget):
# 创建一个垂直布局 # 创建一个垂直布局
mainLayout = QVBoxLayout() mainLayout = QVBoxLayout()
self.showPasswordCheckbox = QCheckBox("显示密码", self)
self.showPasswordCheckbox.stateChanged.connect(self.togglePasswordVisibility)
# 创建三个文本框并设置占位符 # 创建三个文本框并设置占位符
self.nameEdit = QLineEdit() self.nameEdit = QLineEdit()
self.pwdEdit = QLineEdit() self.pwdEdit = QLineEdit()
self.urlEdit = QLineEdit() self.urlEdit = QLineEdit()
self.pwdEdit.setEchoMode(QLineEdit.Password)
# 创建一个按钮并连接信号 # 创建一个按钮并连接信号
btn = QPushButton('提交') btn = QPushButton('提交')
btn.clicked.connect(self.onSubmit) btn.clicked.connect(self.onSubmit)
mainLayout.addWidget(self.showPasswordCheckbox, 0, Qt.AlignCenter)
# 创建一个用于显示错误信息的标签 # 创建一个用于显示错误信息的标签
self.errorLabel = QLabel('', self) self.errorLabel = QLabel('', self)
self.errorLabel.hide() # 初始时隐藏该标签 self.errorLabel.hide() # 初始时隐藏该标签
@ -63,6 +69,12 @@ class MyApp(QWidget):
# 应用样式 # 应用样式
self.applyStyles() self.applyStyles()
def togglePasswordVisibility(self):
if self.showPasswordCheckbox.isChecked():
self.pwdEdit.setEchoMode(QLineEdit.Normal)
else:
self.pwdEdit.setEchoMode(QLineEdit.Password)
def paintEvent(self, event): def paintEvent(self, event):
painter = QPainter(self) painter = QPainter(self)
painter.drawPixmap(self.rect(), self.background) painter.drawPixmap(self.rect(), self.background)

@ -1,69 +1,83 @@
# ''' '''
# 主程序:整合各个模块 主程序整合各个模块
# 1、ui文件调用相应ui模块 1ui文件调用相应ui模块
# 2、get_params.py获取参数 2get_params.py获取参数
# 3、get_answer.py获取答案 3get_answer.py获取答案
# 4、cloud.py将json文件存入云端 4cloud.py将json文件存入云端
# ''' '''
# # 生成图形化界面,引导用户登陆并输入实训网址 # 生成图形化界面,引导用户登陆并输入实训网址
# # 调用get_params.py获取参数这一步同时隐含了云端获取答案的过程 # 调用get_params.py获取参数这一步同时隐含了云端获取答案的过程
# # 如果云端答案不存在则调用get_answer.py获取答案并展示给用户 # 如果云端答案不存在则调用get_answer.py获取答案并展示给用户
# # 用户verif选项确认后调用cloud.py将json文件存入云端 # 用户verif选项确认后调用cloud.py将json文件存入云端
# 导入所需模块
from cloud import upload,download,is_exist
print('处理api相关中...')
download('apis.json')
print('处理完成!')
from get_params import get_parameters
from get_answer import get_answer_from_api,promot,client,get_json,load_api_key,load_json_data
from login_ui import show_login,show_image,MyApp
from trans_to_txt import transToTxt,readJson
import json
import os
from printtxt import print_txt,get_all_txt_file
global finished
finished = False
# 调用login_ui获得用户输入的用户名、密码和实训网址
show_image()
show_login()
# # 导入所需模块 # 检查userinfo.json文件是否存在存在则程序继续
assert os.path.exists('userinfo.json'), 'userinfo.json文件不存在,请检查'
# from get_params import get_parameters # 先读取userinfo.json文件获得用户名、密码和实训网址
# from get_answer import get_answer_from_api,promot,client with open('userinfo.json', 'r') as f:
# from login_ui import show_login,show_image,MyApp userinfo = json.load(f)
# from trans_to_txt import transToTxt,readJson user_name = userinfo['name']
password = userinfo['pwd']
url = userinfo['url']
# import json # 调用get_params.py获得参数完成后本地应该有一个json文件里面有参数
# import os get_parameters(url,user_name,password)
print('到这一步,参数获取完成!')
# 获得刚才get_params.py生成的json文件名
j_name = readJson()[0]
# 判断j_name文件中是否有answer
with open(j_name,'r',encoding='utf-8') as f:
json_data = json.load(f)
# # 调用login_ui获得用户输入的用户名、密码和实训网址 def is_exist_answer(data:dict) -> bool:
# show_image() for i,j in data.items():
# show_login() 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文件是否存在存在则程序继续 # 上面的判断执行完后本地的json文件中已经有answer了下面实现信息展示
# assert os.path.exists('userinfo.json'), 'userinfo.json文件不存在,请检查' # 先删除本地api.json文件
os.remove('apis.json')
# # 先读取userinfo.json文件获得用户名、密码和实训网址 # 使用readJson函数读取当前目录下的所有json文件
# with open('userinfo.json', 'r') as f: JSS = readJson()
# userinfo = json.load(f) # 构建txt文件
# user_name = userinfo['name'] transToTxt(JSS)
# password = userinfo['pwd'] # 展示txt文件
# url = userinfo['url'] # print('哈哈终于要写完了')
print_txt(get_all_txt_file(os.getcwd()))
# # 调用get_params.py获得参数完成后本地应该有一个json文件里面有参数 # #打印完删除本地txt和json文件
# get_parameters(url,user_name,password) for i in JSS:
os.remove(i)
# # 获得本地所有数字开头的json文件名 # 删除本地所有数字开头的txt文件
# j_name = readJson()[0] for i in os.listdir():
# # 判断j_name文件中是否有answer if i.split('.')[0].isdigit() and i.endswith('.txt'):
# with open(j_name,'r',encoding='utf-8') as f: os.remove(i)
# json_data = json.load(f) # 判断云端是否存在答案json如果不存在则上传
if not is_exist(j_name):
# def is_exist_answer(data:dict) -> bool: upload(j_name)
# 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
#询问用户是否认证答案正确(下午新开一个模块实现)

@ -89,12 +89,13 @@ def print_txt(json_path: list): # 传入json文件路径
def get_all_txt_file(path): def get_all_txt_file(path):
file_list = [] file_list = ['0Atip.txt']
for root, dirs, files in os.walk(path): for root, dirs, files in os.walk(path):
for file in files: for file in files:
if file.endswith('.txt') and file[0].isdigit(): if file.endswith('.txt') and file[0].isdigit():
file_list.append(os.path.join(root, file)) file_list.append(os.path.join(root, file))
file_list.sort(key=lambda x:x.split('.')[0])
return file_list return file_list
if __name__ == '__main__':
print_txt(get_all_txt_file(os.getcwd())) print_txt(get_all_txt_file(os.getcwd()))

@ -0,0 +1 @@
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "someElementID")))

@ -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。暂时就想到那么多哈哈。
Loading…
Cancel
Save