经过Wireshark抓包,我发现要抓取BNU上提交过的代码,访问http://www.bnuoj.com/bnuoj/get_source.php?runid=%d&randomid=0.19548853184096515这个链接,其中runid=%d,%d填代码执行的id号。那个randomid不知道是干嘛的。。
然后这个页面就会返回包含代码信息的html页面。
如图:
用python urllib2模块中的opener,打开就能够得到这个页面的html源文件。
url="http://www.bnuoj.com/bnuoj/get_source.php?runid=%d&randomid=0.19548853184096515" % int(runid) res=opener.open(url)
当然,在抓取源文件时,需要事先登录拿到cookie。
cj=cookielib.CookieJar() opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) opener.addheaders=defaultHeaders while True: username=raw_input(u'Please input your username:') password=getpass.getpass('Please input your password:') logindata={'username' : username, 'password' : password, 'cksave' : '365'} data=urllib.urlencode(logindata) tmp=opener.open(loginURL,data) if tmp.read() == 'Yes': print u'Login successed!' break else: print u'Login failed!'
拿到html代码,格式比较正规。可以从页面中提取到很多有用的信息。比如,用户名,代码语言,etc。
如:
<div style='clear:both;margin:auto;font-weight:bold;text-align:center'>Result: Accepted Memory Used: 1396 KB Time Used: 4 ms </div> <div style='clear:both;margin:auto;font-weight:bold;text-align:center'>Language: GNU C++ User Name: sssogs Problem ID: 1082 <div> <div style="clear:both;margin:auto;text-align:center">Share Code? <input name="tisshare" type="radio" style="width:16px" value="1" checked="checked" />Yes <input name="tisshare" value="0" type="radio" style="width:16px" />No</div><div style='clear:both;margin:auto;color:blue;font-weight:bold;text-align:center' id='sharenote'><b>This code is shared.</b></div> <div style='clear:both;text-align:left'><pre id='source_code' class='cpp'>#include <iostream> using namespace std; int main() { cout<<13<<endl; return 0; }</pre></div>
看上去,有点乱,这时就用强大的正则表达式来处理一下。
现在,我把源代码都提取到了s中。
先除去所有的html标签。
s=re.sub('<.+>','',s)
把html的符号属性,转化成一般的。如,空格, ,等等。
最后因为保存在s中的换行符是''\r\n"的,所以需要把它转化为"\n",这样在文本中的代码才能正常地显示。
s=re.sub('\r\n','\n',s)
保存文件信息
fa=open('BNUOJ_%s.%s'%(info['Problem ID'],extLang[info['Language']]),"w") print 'BNUOJ_%s.%s'%(info['Problem ID'],extLang[info['Language']]) fa.write('/**\n * Result : %s\n' % info['Result']) fa.write(' * Language : %s\n' % info['Language']) fa.write(' * Author Name : %s\n' % info['User Name']) fa.write(' * Problem ID : %s\n' % info['Problem ID']) fa.write(' * Time Used : %s\n' % info['Time Used']) fa.write(' * Memory Used : %s\n' % info['Memory Used']) fa.write(' */\n') fa.write(s) fa.close()
效果图:
附上全部代码:
import re import httplib import httplib import urllib2 import urllib import cookielib import getpass loginURL = 'http://www.bnuoj.com/bnuoj/login.php' submitURL = 'http://www.bnuoj.com/bnuoj/action.php' defaultHeaders=[('User-agent','Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)')] extLang={'GNU C++':'cpp', 'Visual C++':'cpp', 'Visual C':'c', 'GNU C':'c', 'Oracle Java':'java', 'C#':'cs' } info={} def SourceProcess(s,uid,res='Accepted'): t1=re.search('Permission denined',s) if t1 != None: return 0 t1=re.search('(Time Used:\s)(\w+\s?\w+)',s) info['Time Used']=t1.group(2) t1=re.search('(Memory Used:\s)(\w+\s?\w+)',s) info['Memory Used']=t1.group(2) t1=re.search('(Language:\s)([\w+]+\s?[#\w+]+)',s) info['Language']=t1.group(2) t1=re.search('(User Name:\s)([\w+]+\s?[\w+]+)',s) info['User Name']=t1.group(2) if info['User Name'] != uid: return 0 t1=re.search('(Problem ID:\s)([\w+]+\s?[\w+]+)',s) info['Problem ID']=t1.group(2) t1=re.search('(Result:\s)([\w+]+\s?[\w+]+)',s) info['Result']=t1.group(2) if info['Result'] != res: return 0 s=re.sub('<.+>','',s) s=re.sub('( )+','!',s) s=re.sub('(<)','<',s) s=re.sub('(>)','>',s) s=re.sub('(&)','&',s) s=re.sub('(")','"',s) s=re.sub('^[ \t\n]*\n','',s) s=re.sub('\r\n','\n',s) fa=open('BNUOJ_%s.%s'%(info['Problem ID'],extLang[info['Language']]),"w") print 'BNUOJ_%s.%s'%(info['Problem ID'],extLang[info['Language']]) fa.write('/**\n * Result : %s\n' % info['Result']) fa.write(' * Language : %s\n' % info['Language']) fa.write(' * Author Name : %s\n' % info['User Name']) fa.write(' * Problem ID : %s\n' % info['Problem ID']) fa.write(' * Time Used : %s\n' % info['Time Used']) fa.write(' * Memory Used : %s\n' % info['Memory Used']) fa.write(' */\n') fa.write(s) fa.close() return 1 def main(): cj=cookielib.CookieJar() opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) opener.addheaders=defaultHeaders while True: username=raw_input(u'Please input your username:') password=getpass.getpass('Please input your password:') logindata={'username' : username, 'password' : password, 'cksave' : '365'} data=urllib.urlencode(logindata) tmp=opener.open(loginURL,data) if tmp.read() == 'Yes': print u'Login successed!' break else: print u'Login failed!' runid=202669 cnt=0; while True: url="http://www.bnuoj.com/bnuoj/get_source.php?runid=%d&randomid=0.19548853184096515" % int(runid) res=opener.open(url) if SourceProcess(res.read(),username,'Accepted')==1: cnt+=1 print cnt runid=runid-1 print runid main()