poj和zoj自动登录,提交并获取评判结果-阿里云开发者社区

开发者社区> 吞吞吐吐的> 正文

poj和zoj自动登录,提交并获取评判结果

简介:
+关注继续查看

杭州电子科技大学的OJ(http://acm.hdu.edu.cn/)(以后简称杭电)很有特色,目前也很火,其中一个关键原因就是它提供了一些新功能,比如diy,webdiy,virtual contest等。这里我们简单讨论一下杭电的webdiy。

      webdiy是什么?是在DIY的基础上增加了从其他OJ选题的功能,那么DIY是什么?就是自己在本地选题,然后组成一场比赛。实现这个功能关键是能在其他OJ上提交,并能获得评判结果,直接往数据库里面写肯定是不可能的,那就只剩下一个方法:网络爬虫,模拟用户提交。

      最近一直在研究python的网络编程模块,用python来实现这个功能还是比较简单的,先看两张demo截图

 

 

左边是poj,右边是zoj,除了给出评判结果外,还有必要的提示信息

 

下面是代码实现:

POJ

复制代码

# -*- coding: utf-8 -*- 

import re
import sys
import logging
from time import sleep
import urllib,urllib2,cookielib
from BeautifulSoup import BeautifulSoup

class POJ:
    URL_HOME = 'http://poj.org/'
    URL_LOGIN = URL_HOME + 'login?'
    URL_SUBMIT = URL_HOME + 'submit?'
    URL_STATUS = URL_HOME + 'status?'
    #结果信息
    INFO =['RunID','User','Problem','Result','Memory','Time','Language','Code Length','Submit Time']
    #语言
    LANGUAGE = {
            'G++':'0',
            'GCC':'1',
            'JAVA':'2',
            'PASCAL':'3',
            'C++':'4',
            'C':'5',
            'FORTRAN':'6',
            }

    def __init__(self, user_id, password):
        self.user_id = user_id
        self.password = password
        cj = cookielib.LWPCookieJar()
        self.opener =urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
        urllib2.install_opener(self.opener)

    def login(self):
        data = dict(
                user_id1 = self.user_id,
                password1 = self.password,
                B1 = 'login',
                url = '.')
        postdata = urllib.urlencode(data)
        try:
            req = urllib2.Request(POJ.URL_LOGIN,postdata)
            res = self.opener.open(POJ.URL_LOGIN,postdata).read()
            if res.find('loginlog')>0: 
                logging.info("login successful!")
                return True
            else:
                logging.error('login failed')
                return False
        except:
            logging.error('login failed')
            return False

    def submit(self,pid,language,src):
        submit_data = dict(
                problem_id = pid,
                language = POJ.LANGUAGE[language.upper()],
                source = src,
                submit = 'Submit',)
        postdata2 = urllib.urlencode(submit_data)
        try:
            req2 = urllib2.Request(POJ.URL_SUBMIT,data = postdata2)
            res = self.opener.open(POJ.URL_SUBMIT,postdata2).read()
            logging.info('submit successful')
            return True
        except:
            logging.error('submit error')
            return False

    def result(self,user_id):
        url = POJ.URL_STATUS + urllib.urlencode({'user_id':user_id})
        page = urllib2.urlopen(url)
        soup = BeautifulSoup(page)
        table = soup.findAll('table',{'class':'a'}) #提取表格
        pattern = re.compile(r'>[-+: \w]*<')  #正则表达式匹配需要的信息
        result = pattern.findall(str(table))
        #正在评判,编译或等待
        wait = ['Running & Judging','Compiling','Waiting']
        for i in range(3):
            if result[32][1:-1]==wait[i] or result[32][1:-1] == '':
                logging.info(result[32])
#                sleep(1)
                return False
        #最终结果在result序列中的位置
        num = [21,24,28,32,35,37,40,43,45]
        for i in range(9):
            print POJ.INFO[i],':',result[num[i]][1:-1]
        return True


if __name__=='__main__':
    #基础logging模块配置
    FORMAT = '----%(message)s----'
    logging.basicConfig(level=logging.INFO,format = FORMAT)
    if len(sys.argv) > 1: #从外部传入参数
        user_id, pwd, pid, lang, src, = sys.argv[1:]
        src = open(src,'r').read()
    else:  #测试
        user_id = 'username'
        pwd = 'password'
        pid = 1000
        lang = 'gcc'
        src = '''
        #include<stdio.h>
        int main()
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d",a+b);
            return 0;
        }
        
'''
    logging.info('connecting to server')
    poj = POJ(user_id,pwd)
    if poj.login():
        logging.info("submiting")
        if poj.submit(pid,lang,src):
            logging.info('getting result')
            status = poj.result(user_id)
            while status!=True:  #直到检测到结果
                status = poj.result(user_id)
复制代码

 

ZOJ

复制代码
# -*- coding: utf-8 -*-
import re
import sys
import logging
from time import sleep
import urllib,urllib2,cookielib
from BeautifulSoup import BeautifulSoup

class ZOJ:
    URL_HOME = 'http://acm.zju.edu.cn/onlinejudge/'
    URL_LOGIN = URL_HOME + 'login.do?'
    URL_SUBMIT = URL_HOME + 'submit.do?'
    URL_STATUS = URL_HOME + 'showRuns.do?contestId=1&'
    
    #结果信息
    INFO =['RunID','Submit Time','Judge Status','Problem ID',
        'Language','Run Time(ms)','Run Memory(KB)','User Name']
    #语言:为了防止出错,gcc定义为C语言,g++定义为c++,zoj没有gcc和g++选项
    LANGUAGE = {
            'C':'1',
            'C++':'2',
            'FPC':'3',
            'JAVA':'4',
            'PYTHON':'5',
            'PERL':'6',
            'SCHEME':'7',
            'PHP':'8',
            'GCC':'1',
            'G++':'2',
            }

    def __init__(self, user_id, password):
        self.user_id = user_id
        self.password = password
        cj = cookielib.LWPCookieJar()
        self.opener =urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
        urllib2.install_opener(self.opener)

    def login(self):
        data = dict(
                handle = self.user_id,
                password = self.password,
                )
        postdata = urllib.urlencode(data)
        try:
            req = urllib2.Request(ZOJ.URL_LOGIN,postdata)
            res = self.opener.open(ZOJ.URL_LOGIN,postdata).read()
            if res.find(self.user_id)>0:
                logging.info("login successful!")
                return True
            else:
                logging.error('login failed')
                return False
        except:
            logging.error('login failed')
            return False

    def submit(self,pid,language,src):
        submit_data = dict(
                problemId = str(int(pid) - 1000),
                languageId = ZOJ.LANGUAGE[language.upper()],
                source = src,)
        postdata2 = urllib.urlencode(submit_data)
        try:
            req2 = urllib2.Request(ZOJ.URL_SUBMIT,data = postdata2)
            res = self.opener.open(ZOJ.URL_SUBMIT,postdata2).read()
            logging.info('submit successful')
            return True
        except:
            logging.error('submit error')
            return False

    def result(self,user_id):
        url = ZOJ.URL_STATUS + urllib.urlencode({'handle':user_id})
        page = urllib2.urlopen(url)
        soup = BeautifulSoup(page)
        table = soup.findAll('table',{'class':'list'})
        table = ''.join(str(table).split())
        pattern = re.compile(r'>[-+:\w]*<')
        result = pattern.findall(str(table))
        wait = ['Running','Compiling','Waiting']
        num = [18,20,23,27,31,34,36,40]
        for i in range(3):
            if result[23][1:-1]==wait[i]:
                logging.info(result[23])
                sleep(1)
                return False
        if result[23][1:-1] == '':
            num = [18,20,24,29,33,36,38,42]
        for i in range(8):
            print ZOJ.INFO[i],':',result[num[i]][1:-1]
        return True


if __name__=='__main__':
    FORMAT = '----%(message)s----'
    logging.basicConfig(level=logging.INFO,format = FORMAT)
    if len(sys.argv) > 1:
        user_id, pwd, pid, lang, src, = sys.argv[1:]
        src = open(src,'r').read()
    else:
        user_id = 'username'
        pwd = 'password'
        pid = 1001
        lang = 'c++'
        src = '''
        #include<stdio.h>
        int main()
        {
            int a,b;
            while(scanf("%d%d",&a,&b)!=EOF)
            printf("%d\\n",a+b);
            return 0;
        }
        
'''
    logging.info('connecting to server')
    zoj = ZOJ(user_id,pwd)
    if zoj.login():
        logging.info('submiting')
        if zoj.submit(pid,lang,src):
            logging.info('getting result')
            status = zoj.result(user_id)
            while status!=True:

                status = zoj.result(user_id) 

复制代码

 

      先简单解释一下代码:程序用urllib模块编码数据,用urllib2模块提交,用cookielib模块保存登录信息,提交成功后用beautifulsoup模块解析网页得到表格,然后用re模块正则表达式匹配最终结果,sys模块用来从外部程序外部传入参数,整个过程用logging日志模块记录事件日志。

      应该说,上面提到的模块都是经常用到的,都是应该熟练掌握的。上面只是一些简单用法,以后好要深入学习。

      再说说程序的用法(以poj为例):将上面的代码保存到"poj.py",然后在终端执行这个命令:”python poj.py username password problem_id language source_code_path“ 。将上面的用户名和密码替换成你自己的用户名和密码,problem_id是你要提交的题号,如1001,语言可以选gcc,g++,java,pascal等,最后是源文件所在的目录,如果源文件在当前目录下,可以省略路径,直接写文件名。

      这个程序仅仅实现了功能,用户可以根据需要自己扩展,让这个程序更易用,更实用,更符合你的要求,比如在程序中集成用户名和密码,自动识别题目号和语言,给poj.py增加执行权限然后把它所在的目录添加到环境变量或者直接把程序放到/usr/local/bin/目录下,这样的话,或许你以后用vim写完代码,然后一个命令“poj.py 1001.c”就自动交过去了,把这个程序集成到vim里面做成一键提交或许更爽!哈哈,这一切不是不可能!

      说来也有趣,poj和zoj很容易就实现了,但是在弄杭电时,却一直没成功,貌似杭电有防止网络爬虫的机制,杭电自己在其他oj上刷题,却不让别人在自己oj上刷。或许是我学艺不精,还要好好研究。网上说需要增加header,也就是模拟浏览器才能登录,但是登录以后提交却一直没提交成功,也不知道为什么,哪位大神知道帮忙解决一下?小弟感激不尽!

      上面只是一个demo,真正用到webdiy里面的话还要进行扩充,比如增加数据库的支持,还要抓取题目和编译错误信息。当提交量大的时候如何进行调度,网络不给力怎么办,出现错误如何处理等,这都是需要考虑的问题。上面的程序只是一个后台程序,如果做一个webdiy的话还要有前台的展示页面和后台的管理页面,正在学习django模块,希望能用这个框架做。


博主ma6174对本博客文章(除转载的)享有版权,未经许可不得用于商业用途。转载请注明出处http://www.cnblogs.com/ma6174/

对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


本文转自ma6174博客园博客,原文链接:http://www.cnblogs.com/ma6174/archive/2012/07/26/2609791.html,如需转载请自行联系原作者标签: pojzoj自动登录自动提交

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
(六)Gateway开发教程之实现统一授权【集成JWT】
本篇文章就是告诉大家如何在SpringCloud项目中使用JWT实现统一授权。Gateway中集成统一认证授权,是微服务网关中必然要集成的功能之一,重要性不言而喻.
4 0
3月已有5起千万级融资,无/低代码开发平台的春天来了
3月已有5起千万级融资,无/低代码开发平台的春天来了 从3年16起融资到半个月5起融资,无/低代码平台真正受追捧
4 0
一日千星的「机器学习系统设计指南」,这个英伟达小姐姐的项目火了
今年 8 月份,毕业于斯坦福、现就职于英伟达人工智能应用团队的一位小姐姐在推特上列出了十大优质的免费机器学习课程资源,并将它们串成了一条高效的学习路线。该课程资源现已获得 8000 多赞。近日,她又为读者带来了新的福利,这次是深度学习系统的设计教程。
3 0
不可见世界的掘金者,如何改变中国机床行业下半生?
天泽智云无忧机床系统聚焦机加工领域,通过结合领域知识与机器学习算法,提供关键组件健康评估、故障预诊与寿命预测等功能,一方面帮助企业实现降本增效,另一方面帮助发掘新的增值点,突破制造附加值较低的瓶颈,服务机床厂商和加工厂向智能化升级,甚至促进他们未来服务模式的转型。机加工是一个非常典型的装备制造产业,把产业上下游企业服务好,其他行业便可以借鉴其有效经验,进而加速整个中国制造业的升级。类似机加工产业的案例说明,中国的丰沛工业数据资源或许可以帮助中国制造业在工业大数据中创知和创值,成为世界可以参考的成功标杆。
4 0
数字化催生新职业数字员工兴起,RPA拉开人机协同时代序幕
数字化催生新职业数字员工兴起,RPA拉开人机协同时代序幕 人机协同时代数字员工大兴,人+RPA加速企业数字化转型
4 0
英特尔AI医疗实战曝光:10倍加速辅助诊断、准确度高达90%
深耕医疗健康领域 20 年,医疗健康数字化、药物治疗精确化一直是英特尔的重要议题。
6 0
(五)Gateway开发教程之为什么选择JWT
微服务中的权限认证,一般是有着几种常用的解决方案,比如JWT(Json web token)、分布式Session、OAuth2 Token等等方案。JWT,简单易集成,而且可以将用户的基本信息加密到token中,此信息在前端也可以去获取到一定的信息。
6 0
(四)Gateway开发教程之自定义网关过滤器
Gateway中一共提供了两种过滤器,一种是GatewayFilter、GlobalFilter; GatewayFilter:Gateway网关过滤器,是针对单个路由的过滤器,又称局部过滤器。GlobalFilter:从名称而言,那就是全局过滤器,
5 0
Dubbo02【搭建provider和consumer】
本文来给大家介绍下基于Spring配置的方式来搭建dubbo中的服务提供端和消费端 provider和consumer的搭建
3 0
(三)Gateway开发教程之配置路由详解(全)
初步的使用了Gateway组件,并且在SpringCloud框架中进行了集成操作,已经算是入门了,接下来就是要全面的了解下Gateway中各项配置了。
4 0
4252
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载