IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 使用Python导出hustoj题目提交代码结果(用于收集留言的题目) -> 正文阅读

[Python知识库]使用Python导出hustoj题目提交代码结果(用于收集留言的题目)

1. 前情提要

2022年9月10日,为IMAU七十周年校庆,我计算机院了举办“校庆杯”大学生程序设计大赛。其中有一道题J题,使用了SPJ,用来收集所有参赛者的祝福。

1576: 祈愿imau

时间限制:1s 内存限制:128MB Special Judge

题目描述

嗨 亲爱的农大IT人,相信点开这道题的时候,比赛已经接近尾声。
我想告诉你的是,这道题是一道特殊判断题(Special Judge),也就是说,这道题的答案不唯一,是否判题通过取决于一个智能程序,而不是单纯的文本比对。
用任意编程语言的输出方法,输出你们队伍对农大的祝福,并留下你的队名,提交即可AC。并且,我们会在比赛结束后将你们的祝福收集,作为本次比赛的额外收获。
同时也祝你们中秋快乐!——出题组

输入格式

输出格式

你对农大的祝福

由于队伍比较多,从管理后台一条一条复制粘贴显然是不合适的,所以接下来记录一下我导出的过程。

2. SSH 登录判题服务器

学校OJ采用的是 开源项目 hustoj(https://github.com/zhblue/hustoj),并在内网部署,其提交的代码以文本形式存在数据库中。

2.1 登录ssh

打开cmd,输入ssh远程连接指令。
(这里的user为判题用户,如果有root账户的密码也可以用root)

ssh user@172.xx.xx.xx

如果是第一次登录,会给出提示:

The authenticity of host ‘172.20.25.11 (172.20.25.11)’ can’t be established.
ECDSA key fingerprint is SHA256:xNk0TUMV41iUcslAClIk1AqddxIQHFfWOrjiakPbIWw.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

这里我们输入 yes 即可。

再次连接,提示输入密码,验证后成功进入服务器。

2.2 查看判题数据库配置

hustoj有一键安装脚本,所有的流程都是全自动执行的,所以我们事先不知道数据库相关配置,这时候就需要查看配置文件。根据hustoj官方文档,我们得知,其配置信息都存放在 /home/judge/etc/judge.conf 中。

但是直接提取会显示权限不足,遂换用root用户

我们使用 su 提权

su

输入root密码后,当前账户变成了root,这时我们再访问

vi /home/judge/etc/judge.conf

然后就会看到配置,其中含mysql的账户和密码。

OJ_HOST_NAME=127.0.0.1
OJ_USER_NAME=debian-sys
OJ_PASSWORD=**********
OJ_DB_NAME=jol
OJ_PORT_NUMBER=3306

我们再来查看一下该账户是否支持远程访问。

在ssh上:

mysql -uroot

然后输入SQL查询语句

select user, host from mysql.user;

查询结果:

+------------------+-----------+
| user             | host      |
+------------------+-----------+
| debian-sys       | %         |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

可以看到,debian-sys账户的host为 %,说明支持远程访问,我们接下来就可以脱离SSH进行操作了。如果这里不是 %,可以去百度一下mysql账户如何开启远程访问。

3. 写SQL

3.1 使用 Navicat 连接数据库

我们使用上述配置,用 Navicat连接,查看表结构。
在这里插入图片描述

3.2 查看模型

可知,我们需要的数据集中在 solutionsource_code 表中。

逆向模型后:
在这里插入图片描述
已知题目IDproblem_id = 1576,通过题的 result = 4

3.3 写出SQL

select user_id, nick, source, result, `language`
from solution
left join source_code
on solution.solution_id = source_code.solution_id
where problem_id = 1576 and result = 4;

这样,我们就拿到了所有源代码及提交记录信息。

3.4 用Python实现

import os
import time
import pymysql
from tqdm import tqdm
import sys

database = {
    "host": "172.xx.xx.xxx",
    "username": "debian-sys",
    "password": "******",
    "database": "jol"
}

conn = pymysql.connect(
    host=database["host"],
    port=3306,
    user=database["username"],
    password=database["password"],
    database=database["database"],
    charset='utf8'
)

# 获取游标对象
cursor = conn.cursor()

# 查询 SQL 语句
# sql = "select solution_id,source from source_code where solution_id in (select solution_id from solution where problem_id = 1576) limit 10"


sql = "select user_id, nick, source, result, `language` from solution left join source_code on solution.solution_id = source_code.solution_id where problem_id = 1576 and result = 4";

cursor.execute(sql)
data = cursor.fetchall()

4. 源码处理

我们拿到了源码,但只是源码,我们还需要在本地编译运行后拿取stdout输出的内容。

我们可以针对不同语言,编写对应的编译运行代码,然后通过 重定向 >xxx.txt的方式,将结果保存在文本文件中。

# 6 = python
# 0 = c
# 1 = c++
# 3 = java
lang_dict = {
    "0": ".c",
    "1": ".cpp",
    "3": ".java",
    "6": ".py"
}
complier_dict = {
    "0": [
        "g++ -o Main {filename}",
        "Main <nullptr.txt > {filename}.txt"
    ],
    "1": [
        "g++ -o Main {filename}",
        "Main <nullptr.txt > {filename}.txt"
    ],
    "3": [
        "copy {filename} Main.java",
        "javac Main.java",
        "java Main <nullptr.txt > {filename}.txt"
    ],
    "6": [
        "python {filename} <nullptr.txt > {filename}.txt"
    ]
}

你可能会问为什么有一个 <nullptr.txt ,是因为有的队伍写了input.hasNext()等类似语句,使得初次导出时卡在那里了,所以索性直接把输入流也重定向了。
运行时需要在脚本同目录下建一个 nullptr.txt,内容为空。

循环执行指令,生成.txt文件

for item in tqdm(data):
    file_path = f"{item[0]}{lang_dict[str(item[4])]}"
    
    with open(file_path,"w") as f:
        f.write(item[2])

    for i in complier_dict[str(item[4])]:
        cmd= str(i).replace("{filename}", file_path)
        os.system(cmd)
        time.sleep(1)

完整代码:


import os
import subprocess
import time

import pymysql
from tqdm import tqdm
import sys

database = {
    "host": "172.xx.xx.xx",
    "username": "debian-sys",
    "password": "*******",
    "database": "jol"
}

conn = pymysql.connect(
    host=database["host"],
    port=3306,
    user=database["username"],
    password=database["password"],
    database=database["database"],
    charset='utf8'
)
# 获取游标对象
cursor = conn.cursor()

# 查询 SQL 语句
# sql = "select solution_id,source from source_code where solution_id in (select solution_id from solution where problem_id = 1576) limit 10"


sql = "select user_id, nick, source, result, `language` from solution left join source_code on solution.solution_id = source_code.solution_id where problem_id = 1576 and result = 4";

cursor.execute(sql)
data = cursor.fetchall()
# 6 = python
# 0 = c
# 1 = c++
# 3 = java
lang_dict = {
    "0": ".c",
    "1": ".cpp",
    "3": ".java",
    "6": ".py"
}
complier_dict = {
    "0": [
        "g++ -o Main {filename}",
        "Main <nullptr.txt > {filename}.txt"
    ],
    "1": [
        "g++ -o Main {filename}",
        "Main <nullptr.txt > {filename}.txt"
    ],
    "3": [
        "copy {filename} Main.java",
        "javac Main.java",
        "java Main <nullptr.txt > {filename}.txt"
    ],
    "6": [
        "python {filename} <nullptr.txt > {filename}.txt"
    ]
}

res_list = []
for item in tqdm(data):
    file_path = f"{item[0]}{lang_dict[str(item[4])]}"
    # print(file_path)
    # print(item)
    with open(file_path,"w") as f:
        f.write(item[2])

    for i in complier_dict[str(item[4])]:
        cmd= str(i).replace("{filename}", file_path)
        print(cmd)
        os.system(cmd)
        time.sleep(1)
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:10:11  更:2022-09-13 11:14:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 10:19:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码