实现HDU基础爬虫提交和查询结果
This commit is contained in:
parent
2631577541
commit
0fc7aa51d4
|
@ -97,11 +97,29 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Jsoup-->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.13.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--单元测试-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -149,9 +149,6 @@ public class JudgeController {
|
|||
|
||||
@PostMapping(value = "/remote-judge")
|
||||
public CommonResult remoteJudge(@RequestBody ToJudge toJudge) {
|
||||
/**
|
||||
* TODO 在此调用远程判题
|
||||
*/
|
||||
// 发送消息
|
||||
try {
|
||||
String[] source = toJudge.getRemoteJudge().split("-");
|
||||
|
|
|
@ -16,6 +16,8 @@ import top.hcode.hoj.remoteJudge.task.RemoteJudgeStrategy;
|
|||
import top.hcode.hoj.util.Constants;
|
||||
import top.hcode.hoj.util.RedisUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RemoteJudgeResultReceiver implements MessageListener {
|
||||
|
@ -39,8 +41,12 @@ public class RemoteJudgeResultReceiver implements MessageListener {
|
|||
return;
|
||||
}
|
||||
|
||||
String result = remoteJudgeStrategy.result(submitId);
|
||||
// TODO 获取对应的result ID,修改到数据库
|
||||
// TODO 获取对应的result,修改到数据库
|
||||
try {
|
||||
Map<String, Object> result = remoteJudgeStrategy.result(submitId);
|
||||
} catch (Exception e) {
|
||||
log.error("获取结果出错------------>{}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,10 +42,15 @@ public class RemoteJudgeSubmitReceiver implements MessageListener {
|
|||
log.error("暂不支持该{}题库---------------->请求失败", remoteJudge);
|
||||
return;
|
||||
}
|
||||
Long submitId = remoteJudgeStrategy.submit(pid, language, userCode);
|
||||
// TODO 提交失败 修改状态 STATUS_NOT_SUBMITTED
|
||||
Long submitId = -1L;
|
||||
try {
|
||||
submitId = remoteJudgeStrategy.submit(pid, language, userCode);
|
||||
} catch (Exception e) {
|
||||
log.error("网络错误,提交失败");
|
||||
}
|
||||
// TODO 提交失败 前端手动按按钮再次提交 修改状态 STATUS_NOT_SUBMITTED
|
||||
if (submitId < 0) {
|
||||
log.error("提交失败---------------->获取不到提交ID");
|
||||
log.error("网络错误---------------->获取不到提交ID");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -1,53 +1,147 @@
|
|||
package top.hcode.hoj.remoteJudge.task.Impl;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import jdk.nashorn.internal.runtime.regexp.RegExp;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Connection;
|
||||
import org.jsoup.helper.Validate;
|
||||
import top.hcode.hoj.remoteJudge.task.RemoteJudgeStrategy;
|
||||
import top.hcode.hoj.util.Constants;
|
||||
import top.hcode.hoj.util.JsoupUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
public class HduJudge implements RemoteJudgeStrategy {
|
||||
public static final String host = "acm.hdu.edu.cn";
|
||||
public static final String host = "http://acm.hdu.edu.cn";
|
||||
public static final String loginUrl = "/userloginex.php?action=login";
|
||||
public static final String submitUrl = "/submit.php?action=submit";
|
||||
public static final String statusUrl = "/status.php?user=%s&pid=%d";
|
||||
public static final String queryUrl = "/status.php?first=%d";
|
||||
public static final String errorUrl = "/viewerror.php?rid=%d";
|
||||
|
||||
/**
|
||||
* TODO 提交题目
|
||||
*
|
||||
* @param problemId 提交的题目id
|
||||
* @param language
|
||||
* @param userCode 用户代码
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Long submit(Long problemId, String language, String userCode) {
|
||||
public Long submit(Long problemId, String language, String userCode) throws Exception {
|
||||
if (problemId == null || userCode == null) {
|
||||
return -1L;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String result(Long submitId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getLoginCookie() {
|
||||
try {
|
||||
Connection connection = JsoupUtils.getConnectionFromUrl(host + loginUrl, null, null);
|
||||
Connection.Response response = JsoupUtils.postResponse(connection, MapUtil
|
||||
.builder(new HashMap<String, String>())
|
||||
.put("username", "12")
|
||||
.put("userpass", "").map());
|
||||
return response.cookies();
|
||||
} catch (IOException e) {
|
||||
log.error("网络错误");
|
||||
Map<String, String> loginCookie = getLoginCookie();
|
||||
Connection connection = JsoupUtils.getConnectionFromUrl(host + submitUrl, null, loginCookie);
|
||||
Connection.Response response = JsoupUtils.postResponse(connection, MapUtil
|
||||
.builder(new HashMap<String, String>())
|
||||
.put("check", "0")
|
||||
.put("language", getLanguage(language))
|
||||
.put("problemid", String.valueOf(problemId))
|
||||
.put("usercode", userCode)
|
||||
.map());
|
||||
System.out.println("提交代码的状态码:-------" + response.statusCode());
|
||||
if (response.statusCode() != 200) {
|
||||
log.error("提交题目失败");
|
||||
return -1L;
|
||||
}
|
||||
return null;
|
||||
// 获取提交的题目id
|
||||
Long maxRunId = getMaxRunId(connection, "2018030402055", problemId);
|
||||
System.out.println(maxRunId);
|
||||
return maxRunId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> result(Long submitId) throws Exception {
|
||||
String url = host + String.format(queryUrl, submitId);
|
||||
System.out.println(url);
|
||||
Connection connection = JsoupUtils.getConnectionFromUrl(url, null, null);
|
||||
Connection.Response response = JsoupUtils.getResponse(connection, null);
|
||||
// 1提交时间 2结果 3执行时间 4执行空间 5代码长度
|
||||
// 一般情况下 代码长度和提交时间不需要,想要也行,自行添加
|
||||
Pattern pattern = Pattern.compile(">" + submitId + "</td><td>([\\s\\S]*?)</td><td>([\\s\\S]*?)</td><td>[\\s\\S]*?</td><td>(\\d*?)MS</td><td>(\\d*?)K</td><td>(\\d*?)B</td>");
|
||||
Matcher matcher = pattern.matcher(response.body());
|
||||
// System.out.println(response.body());
|
||||
// 找到时
|
||||
Validate.isTrue(matcher.find());
|
||||
String rawStatus = matcher.group(2).replaceAll("<[\\s\\S]*?>", "").trim();
|
||||
System.out.println(rawStatus);
|
||||
Constants.Judge statusType = statusTypeMap.get(rawStatus);
|
||||
// 返回的结果map
|
||||
Map<String, Object> result = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("status", statusType).build();
|
||||
// 获取其他信息
|
||||
String executionTime = matcher.group(3);
|
||||
result.put("executionTime", executionTime);
|
||||
String executionMemory = matcher.group(4);
|
||||
result.put("executionMemory", executionMemory);
|
||||
// 如果CE了,则还需要获得错误信息
|
||||
if (statusType == Constants.Judge.STATUS_COMPILE_ERROR) {
|
||||
connection.url(host + String.format(errorUrl, submitId));
|
||||
response = JsoupUtils.getResponse(connection, null);
|
||||
String compilationErrorInfo = ReUtil.get("(<pre>[\\s\\S]*?</pre>)", response.body(), 1);
|
||||
result.put("compilationErrorInfo", compilationErrorInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getLoginCookie() throws Exception {
|
||||
Connection connection = JsoupUtils.getConnectionFromUrl(host + loginUrl, null, null);
|
||||
Connection.Response response = JsoupUtils.postResponse(connection, MapUtil
|
||||
.builder(new HashMap<String, String>())
|
||||
// TODO 添加账号密码 暂时写死测试,后续将在队列中获取空闲账号
|
||||
.put("username", "11")
|
||||
.put("userpass", "11").map());
|
||||
return response.cookies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage(String language) {
|
||||
switch (language) {
|
||||
case "G++":
|
||||
return "0";
|
||||
case "GCC":
|
||||
return "1";
|
||||
case "C++":
|
||||
return "2";
|
||||
case "C":
|
||||
return "3";
|
||||
case "Pascal":
|
||||
return "4";
|
||||
case "Java":
|
||||
return "5";
|
||||
case "C#":
|
||||
return "6";
|
||||
default:
|
||||
// TODO 抛出没有这个语言的异常
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getMaxRunId(Connection connection, String userName, Long problemId) throws Exception {
|
||||
String url = String.format(statusUrl, userName, problemId);
|
||||
connection.url(host + url);
|
||||
Connection.Response response = JsoupUtils.getResponse(connection, null);
|
||||
Matcher matcher = Pattern.compile("<td height=22px>(\\d+)").matcher(response.body());
|
||||
return matcher.find() ? Long.parseLong(matcher.group(1)) : -1L;
|
||||
}
|
||||
|
||||
|
||||
// TODO 添加结果对应的状态
|
||||
private static final Map<String, Constants.Judge> statusTypeMap = new HashMap<String, Constants.Judge>() {
|
||||
{
|
||||
put("Submitted", Constants.Judge.STATUS_SUBMITTING);
|
||||
put("Accepted", Constants.Judge.STATUS_ACCEPTED);
|
||||
put("Wrong Answer", Constants.Judge.STATUS_WRONG_ANSWER);
|
||||
put("Compilation Error", Constants.Judge.STATUS_COMPILE_ERROR);
|
||||
put("Time Limit Exceeded", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package top.hcode.hoj.remoteJudge.task;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
|
@ -14,14 +15,16 @@ public interface RemoteJudgeStrategy {
|
|||
* @param userCode 用户代码
|
||||
* @return 返回对应题库的提交Id
|
||||
*/
|
||||
Long submit(Long problemId, String language, String userCode);
|
||||
Long submit(Long problemId, String language, String userCode) throws Exception;
|
||||
|
||||
/**
|
||||
* @param submitId 题库的提交ID
|
||||
* @return 返回结果
|
||||
*/
|
||||
String result(Long submitId);
|
||||
Map<String, Object> result(Long submitId) throws Exception;
|
||||
|
||||
Map<String, String> getLoginCookie();
|
||||
Map<String, String> getLoginCookie() throws Exception;
|
||||
|
||||
String getLanguage(String language);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@ public class JsoupUtils {
|
|||
Connection connection = Jsoup.connect(url);
|
||||
// 设置用户代理
|
||||
connection.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36");
|
||||
// 设置超时时间5秒
|
||||
connection.timeout(5000);
|
||||
// 设置超时时间10秒
|
||||
connection.timeout(10000);
|
||||
// 设置cookie,保存信息
|
||||
connection.cookies(cookies);
|
||||
if (cookies != null)
|
||||
connection.cookies(cookies);
|
||||
// 设置请求头
|
||||
if (headers != null) {
|
||||
connection.headers(headers);
|
||||
|
@ -35,21 +36,14 @@ public class JsoupUtils {
|
|||
}
|
||||
|
||||
public static Connection.Response postResponse(Connection connection, Map<String, String> postData) throws IOException {
|
||||
//添加参数
|
||||
if (postData != null) {
|
||||
for (Map.Entry<String, String> entry : postData.entrySet()) {
|
||||
connection.data(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
connection.data(postData);
|
||||
return connection.method(Connection.Method.POST).execute();
|
||||
}
|
||||
|
||||
public static Connection.Response getResponse(Connection connection, Map<String, String> postData) throws IOException {
|
||||
public static Connection.Response getResponse(Connection connection, Map<String, String> getData) throws IOException {
|
||||
//添加参数
|
||||
if (postData != null) {
|
||||
for (Map.Entry<String, String> entry : postData.entrySet()) {
|
||||
connection.data(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (getData != null) {
|
||||
connection.data(getData);
|
||||
}
|
||||
return connection.method(Connection.Method.GET).execute();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package top.hcode.hoj;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import top.hcode.hoj.remoteJudge.task.Impl.HduJudge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
@SpringBootTest
|
||||
public class JudgeServerApplicationTests {
|
||||
@Test
|
||||
void test1() {
|
||||
HduJudge hduJudge = new HduJudge();
|
||||
String code = "#include<iostream>\n" +
|
||||
"using namespace std;\n" +
|
||||
"\n" +
|
||||
"int main()\n" +
|
||||
"{\n" +
|
||||
"\tint t;\n" +
|
||||
"\tcin >> t;\n" +
|
||||
"\twhile (t--) {\n" +
|
||||
"\t\tint a, b;\n" +
|
||||
"\t\tcin >> a >> b;\n" +
|
||||
"\t\tcout << a + b;\n" +
|
||||
"\t\tif (t == 0){\n" +
|
||||
"\t\t\tcout << endl;\n" +
|
||||
"\t\t} else {\n" +
|
||||
"\t\t\tcout << endl;\n" +
|
||||
"\t\t}\n" +
|
||||
"\t}\n" +
|
||||
"\treturn 1;\n" +
|
||||
"}";
|
||||
try {
|
||||
Long submit = hduJudge.submit(1090L, "G++", code);
|
||||
System.out.println(submit);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package top.hcode.hoj.remoteJudge.task.Impl;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class HduJudgeTest {
|
||||
|
||||
@Test
|
||||
void getLoginCookie() {
|
||||
HduJudge hduJudge = new HduJudge();
|
||||
|
||||
try {
|
||||
Map<String, Object> submit = hduJudge.result(35329033L);
|
||||
System.out.println(submit);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue