HDU 自动刷题机 Auto AC (轻轻松松进入HDU首页)
前言:
在写这篇文章之前,首先感谢给我思路以及帮助过我的学长们
以下4篇博客都是学长原创,其中有很多有用的,值得学习的东西,希望能够帮到大家!
1、手把手教你用C++ 写ACM自动刷题神器(冲入HDU首页)
2、[C#] 逆袭——自制日刷千题的AC自动机攻克HDU OJ
3、C#利用POST实现杭电oj的AC自动机器人,AC率高达50%~~
4、继续Node爬虫 — 百行代码自制自动AC机器人日解千题攻占HDOJ
当初抱着想试试的想法,用过他们的程序,嗯~ o(* ̄▽ ̄*)o。
1、比如那个用C++写AC机的学长,他的程序是用VS2013编译的,原谅我的C++并不是学的很好,照着他的教程试过好多次也没有运行成功,最终只能以失败告终了!
不过源程序我一直保留着。
2、正在入门C#的我看到这个程序,果断fork,或许会看不懂,不过……总会有用的!喏!这是一个模拟人操作的程序,模拟复制,模拟鼠标点击提交,缺点就是,如果程序是后台运行便会停止~(
╯□╰ )……表示并不是自己想要的那一种……
3、博主还是用C#写的,50%的AC率看起来好”*/¥#“,只是没有开源,貌似自己在YTU OJ上的AC率只有56%。
4、用 node 来模拟用户的这个过程,其实就是一个 模拟登录+模拟提交 的过程,根据经验,模拟提交这个 post 过程肯定会带有 cookie。提交的 code
哪里来呢?直接爬取搜索引擎就好了。整个思路非常清晰:模拟登录(post),从搜索引擎爬取 code(get),模拟提交(post)。那这个是不是看起来很不错呢?对,只是Node普通环境我通过baidu找教程配置好了,然而还是不能运行,估计还缺少一个什么环境吧!只有一百多行代码写出的AC机果然不容小觑,运行不了……【笑哭】【笑哭】【笑哭】
正文
至于网上找的,终究不如自己写的,那么,先上图!
第12名的千千是我哦!
请忽略我的正确率,相比学长做的那些,还是差了很多……不过,先给各位辛苦刷题的ACMer赔个不是,毕竟这是很投机的一种方式,仅供娱乐,还请各位见谅!
下面我们一步一步开始AUTO AC之旅吧!
1、同样使用socket编程模拟HTTP协议GET请求向服务器发送页面请求
string reqInfo = "POST " + (string)othPath + " HTTP/1.1\r\nHost: " + (string)host + ElseInfo + Typee + ConLen + (string)s + "\r\nCookie: " + Cookie + "\r\nConnection:Close\r\n\r\n" + ResCode;
if (SOCKET_ERROR == send(sock, reqInfo.c_str(), reqInfo.size(), 0))
{
cout << "send error! 错误码: " << WSAGetLastError() << endl;
closesocket(sock);
}
我们使用Socket编程通过bind(),connect(),send(),recv()这些函数建立与服务器的连接。 接下来我们想:点击按钮的过程发生了什么,我们使用send()需要将什么信息发送至服务器,这里就要涉及到HTTP协议的GET请求。
2、借助搜索引擎获取csdn博客链接
先上几张图~
看到这些不同的搜索引擎所搜索的结果,你有什么发现么?
没错,注意左下角哦!百度和360的搜索引擎都对链接做了加密处理,对于这样的链接,我们从源代码中是很难提取对应页面的原始地址的!所以最终找到了必应搜索引擎(有道搜索也可以),不过,缺点就是这些对于我们来说不太常用的搜索引擎对我们想要的页面的索引量也不是很多。不过,够用了~
有没有人想问我为什么不用CSDN内置的搜索呢?我只能说,CSDN的搜索引擎还没有我自己写的find函数好用
,有时候站内搜索已有的文章也搜索不到!
void GetCSDNurl(string &allHtml) ///提取网页中的csdn博客网址
{
blogUrl.clear();
smatch mat;
regex pattern("href=\"(http://blog.csdn[^\\s\"]+)\"");
string::const_iterator start = allHtml.begin();
string::const_iterator end = allHtml.end();
while (regex_search(start, end, mat, pattern))
{
string msg(mat[1].first, mat[1].second);
blogUrl.push_back(msg);
start = mat[0].second;
}
}
曾经用PHP做<微信公众平台:imqxms> 的后台的时候用过正则表达式,结果发现C++中也有。所以直接找学长的源码为我所用啦!(说出名称只求你的关注:imqxms)
3、从HTML源代码中提取程序代码
这张图片是网页源代码中的程序代码部分!
明显的特征就是<pre></pre>与我们常用的#include<>
,可以看到,'<'与'>'等一些字符都被改成了其他字符,这或许是网络标记语言中的转义字符吧!
void GetCode(string &allHtml) //提取代码部分
{
CodeHtml = "";
int pos = allHtml.find("#include");
if (pos != string::npos)
{
for (int i = pos; i < (int)allHtml.length(); i++)
{
if ((allHtml[i] == '<'&&allHtml[i + 1] == '/'&&allHtml[i + 2] == 't'&&allHtml[i + 3] == 'e'&&allHtml[i + 4] == 'x'&&allHtml[i + 5] == 't'))return;
else if (allHtml[i] == '<'&&allHtml[i + 1] == '/'&&allHtml[i + 2] == 'p'&&allHtml[i + 3] == 'r'&&allHtml[i + 4] == 'e'&&allHtml[i + 5] == '>')return;
CodeHtml += allHtml[i];
}
}
else
{
cout << "未找到合适的代码!" << endl;
return;
}
}
我们需要的是原来完整的代码,那么,接下来的任务就是将这段程序中所有的HTML转义字符转换成C++或者其他语言中的字符咯!
另外讲一下几个关于网页表单很重要的编码。
一个是url编码,因为如果要传送的数据中包含一些符号,可能会对原本的文本的分隔符产生冲突,比如& / =等一些用于地址的符号,所以需要把这些符号转义
网页中都是利用url编码进行转义的。
然后一个问题就是网页的编码,分gb2312和utf-8两种
gb2312是中文编码,utf-8是一种更普遍的面向更多语言的编码,两种编码在字母的ASCII码上,是一样的
但是在中文汉字上,gb2312是占2个字节,utf-8占3个字节,这也会导致两种编码下的内容url编码之后会不一样
因此我们还需要做一个对不同编码进行转换的函数!
char* U2G(const char* utf8) ///UTF-8 to GB2312
{
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len + 1];
memset(wstr, 0, len + 1);
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len + 1];
memset(str, 0, len + 1);
WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
if (wstr) delete[] wstr;
return str;
} char* G2U(const char* gb2312) ///GB2312 TO UTF-8
{
int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len + 1];
memset(wstr, 0, len + 1);
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len + 1];
memset(str, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
if (wstr) delete[] wstr;
return str;
}
喏,就是这个,百度(Bing)就是好用
string HTMLTOC(string &CodeHtml) ///HTML转义字符转义处理
{
string ans;
for (int i = 0; i < (int)CodeHtml.length(); i++)
{
if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == 'l'&&CodeHtml[i + 2] == 't'&&CodeHtml[i + 3] == ';') ///< <
{
ans += '<';
i += 3;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == 'g'&&CodeHtml[i + 2] == 't'&&CodeHtml[i + 3] == ';') ///> >
{
ans += '>';
i += 3;
}
else if (CodeHtml[i] == '/'&&CodeHtml[i + 1] == 'n') /// /n; \\n
{
ans += "\\n";
i += 1;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == 'a'&&CodeHtml[i + 2] == 'm'&&CodeHtml[i + 3] == 'p'&&CodeHtml[i + 4] == ';') ///& &
{
ans += '&';
i += 4;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == 'q'&&CodeHtml[i + 2] == 'u'&&CodeHtml[i + 3] == 'o'&&CodeHtml[i + 4] == 't'&&CodeHtml[i + 5] == ';') ///" \"
{
ans += '\"';
i += 5;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == 'n'&&CodeHtml[i + 2] == 'b'&&CodeHtml[i + 3] == 's'&&CodeHtml[i + 4] == 'p'&&CodeHtml[i + 5] == ';') /// ' '
{
ans += ' ';
i += 5;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == '#'&&CodeHtml[i + 2] == '4'&&CodeHtml[i + 3] == '3'&&CodeHtml[i + 4] == ';') ///+ +
{
ans += '+';
i += 4;
}
else if (CodeHtml[i] == '&'&&CodeHtml[i + 1] == '#'&&CodeHtml[i + 2] == '3'&&CodeHtml[i + 3] == '9'&&CodeHtml[i + 4] == ';') ///' '\'
{
ans += '\'';
i += 4;
}
else ans += CodeHtml[i];
}
return ans;
}
好诧异为什么有的学长写的代码中没有这一部分,难道说……[撇嘴],,其实,有一个问题,上面的代码实现了字符的转换,可是这种算法和KMP模式匹配哪种更好呢?
我不会告诉你我昨晚C语言结课考试的时候也有这么一道题(把句子中所有的don't 替换成do not),用的也是上面的方法!
---------------------------貌似已经说了,( ╯□╰ )……
4、利用网页中的cookie来模拟在线
因为每一个账号登录之后都会有唯一的一个cookie,那种模拟鼠标点击的程序,实质上是一个浏览器,可是我在控制台下不会做到这些
,所以做出来的AC机只能在你用浏览器打开的情况下,并且你的账号在线的情况下才能运行
string Cookie = "exesubmitlang=2; PHPSESSID=" + PHPSESSID + "; CNZZDATA1254072405=" + CNZZDATA;
string reqInfo = "POST " + (string)othPath + " HTTP/1.1\r\nHost: " + (string)host + ElseInfo + Typee + ConLen + (string)s + "\r\nCookie: " + Cookie + "\r\nConnection:Close\r\n\r\n" + ResCode;
说到Cookice,想要查看你在浏览器中的Cookice信息,以谷歌浏览器为例,鼠标右键>>检查里面有惊喜哦!
用来刷题的是我的小号
5、既然能做到从网页中提取一个程序的源代码,那么,我也可以在HDU OJ的状态栏找到我们提交之后的最终结果咯!
void GetResult(string &allHtml, int Prob) ///解析出state.php中的结果,空间,时间
{
StateAns = "", StateSapce = "", StateTime = "";
char d[200];
_itoa(ProblemID, d, 10);
strcat(d, "</a>");
int pos = allHtml.find((string)d);
int Mpos = pos;
int Tpos;
if (Mpos == string::npos)return;
else
{
Mpos += 17;
while (true)
{
if (allHtml[Mpos] == '<')
{
Tpos = Mpos;
break;
}
StateSapce += allHtml[Mpos];
Mpos++;
}
cout << "空间: " << StateSapce << endl;
}
Tpos += 9;
while (true)
{
if (allHtml[Tpos] == '<')break;
StateTime += allHtml[Tpos];
Tpos++;
}
cout << "耗时: " << StateTime << endl;
if (pos == string::npos)return;
else
{
pos = pos - 52;
int begin;
while (true)
{
if (allHtml[pos] == '>')
{
begin = pos;
break;
}
pos--;
}
for (int i = begin + 1; allHtml[i] != '<'; i++)StateAns += allHtml[i];
}
cout << "结果: " << "---------------::::::" << StateAns << endl;
}
if(StateAns=="Accepted")break;//如果AC,跳出本次循环,也就是执行下一道题目!
6、别忘了在你的循环后面加上Sleep函数哦!
不然那个状态页面整个页面都会是你的提交。
貌似我曾经因为没有Sleep,然后被不认识的人加了好友【撇嘴】,并不知道他是怎么加到我的!然后告诉我看到我在航电上面刷题了,所以问了我几道题
有的人或许会问,HDU上面不是有1000-5674个题目吗?为什么你总共才AC了两千多道题目,对于这个问题,只能怪我算法没有好好优化,或许可以去ACM之家找源码哦!
7、可执行文件在我的GitHub里面,欢迎大家Fork,别刷太快哦!不然会超过我的。。。【祈求】【祈求】【祈求】
至于源码,以后放出吧! 已放出 千千好委屈,但千千不说!
后记
<a href="www.dreamwings.cn">若是凉夜已成梦</a>
期待你的留言与评论哦!
前段时间有人说我的博客不能留言了,不知道是不是真的……o(* ̄▽ ̄*)ブ
HDU 自动刷题机 Auto AC (轻轻松松进入HDU首页)的更多相关文章
- 【BZOJ-4590】自动刷题机 二分 + 判定
4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 156 Solved: 63[Submit][Status ...
- BZOJ4590 自动刷题机
Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写 ...
- BZOJ_4590_[Shoi2015]自动刷题机_二分答案
BZOJ_4590_[Shoi2015]自动刷题机_二分答案 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题 ...
- BZOJ4590 Shoi2015 自动刷题机 【二分】
BZOJ4590 Shoi2015 自动刷题机 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机–一种可以自动AC题目的神秘装置.自动刷题机刷题的方式非常简 ...
- 【BZOJ4590】[Shoi2015]自动刷题机 二分
[BZOJ4590][Shoi2015]自动刷题机 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动刷题机刷题的方式 ...
- COGS2642 / Bzoj4590 [Shoi2015]自动刷题机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 906 Solved: 321 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了 ...
- LibreOJ #2036. 「SHOI2015」自动刷题机
#2036. 「SHOI2015」自动刷题机 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开 ...
- bzoj4590: [Shoi2015]自动刷题机(二分答案)
4590: [Shoi2015]自动刷题机 题目:传送门 题解: 很明显的一道二分题. 对于二分性的判断:如果n越大,那么AC的题就越少,n越小,AC的题就越多,那么最大最小值都满足单调性,直接瞎搞. ...
- luogu P4343 [SHOI2015]自动刷题机 |二分答案
题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开了他的新发明:自动刷题机--一种可以自动 AC 题目的神秘装置. 自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序. ...
随机推荐
- 用get方式提交请求的url带有中文参数
又碰到JSP页面中文乱码问题,经过一次encodeURI处理后仍旧是乱码,后来经过两次encodeURI后正常显示中文 以前也碰到过同样的问题,没深究,这次网上搜集了一些资料,记录下来留做备份 ___ ...
- Java基础之写文件——从多个缓冲区写(GatheringWrite)
控制台程序,使用单个写操作将数据从多个缓冲区按顺序传输到文件,这称为集中写(GatheringWrite)操作.这个功能的优势是能够避免在将信息写入到文件中之前将信息复制到单个缓冲区中.从每个缓冲区写 ...
- C++ set容器简单用法
set是关联容器,类似于集合,里面的元素不会重复,而且呈现为有序性 常用操作: using namespace std; set<int>:s;1.元素插入:s.insert()2.中序遍 ...
- ACM常用算法及练习(2)
ACM常用算法及练习 知识类型 重要度 容易度 应掌握度 典型题 其他 数据结构(5) 链表 ★★☆ ★★★ ★★☆ 栈 stack ★★★ ★★★ ★★★ HLoj120 ...
- [转]Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言
最近开始学Hibernate,看的是李刚的那本<轻量级java ee企业应用实战>.头一个hibernate程序,我原原本本的按照书上例子写下来,同时只是改动了些mysql的连接参数,并且 ...
- poj: 3094
简单题 #include <iostream> #include <stdio.h> #include <string> #include <stack> ...
- extjs4.0下的日期控件的星期显示为y的解决办法
没有修改的时候的问题: 今天第一次写博客,就记录一下以前extjs4.2下运用日期组件的星期显示问题,当时找了n久,可能是extjs4.2才出来没多久,没有多少人发现这个问题或者说很少有人将Extjs ...
- linux第13天 生产者与消费者
pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INIT ...
- PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器
PHP V5.2:开始 2006 年 11 月发布了 PHP V5.2,它包括许多新增功能和错误修正.它废止了 5.1 版并被推荐给所有 PHP V5 用户进行升级.我最喜欢的实验室环境 —— Win ...
- Easyui主从表设计
js代码: // 全局变量 var loading; var grid; var mainGrid; var dlg_Edit; var dlg_Edit_form; var virpath = &q ...