需求:给你一个学生名单(Excel表格),统计在一个比赛(开放)中,名单上所有学生的AC情况,要求语言是java
名单上有三列:学号,姓名,分组 最后统计的时候我在新表格中加了三列:OJ昵称,AC数量,非JAVA语言AC的数量
其实这个任务一开始对我来说真有点困难,主要是用Python操作Excel,这个我之前没接触过,而且和网页爬虫结合在一起,即把爬虫爬下来的数据整理后写入新的Excel表格,我感觉,整个过程最头疼最重要的应该是数据结构的组织了,幸好Python内置的数据结构(列表,字典等)用起来都很灵活,我把整个过程分成了四个部分完成,注释里写得很详细啦~ 用了两天多的时间(并不是一直在弄,我还要上课,写作业.....)最后再说一下时间问题,,,实际上昨晚我就写出来了,但是运行起来好慢,,,等了几秒,光标都不闪了,我以为程序死循环了QAQ,找了好久也没发现问题,事实是它真的很慢,今天我特意等了几十秒,终于等出了结果,可能是ACM中毒比较深吧2333
(我又修改了一些地方)
#!/usr/bin/env python
#-*-coding:utf-8-*-
import sys, os
import xlrd, xlwt
import urllib, urllib2, cookielib
from bs4 import BeautifulSoup as BS
#1.登录OJ,主要用到的模块:urllib, urllib2, cookielib
home = 'http://acm.sdut.edu.cn/onlinejudge2/index.php/Home'
login = 'http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Login/login'
cookie_support = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
opener = urllib2.build_opener(cookie_support)
urllib2.install_opener(opener)
temp = urllib2.urlopen(home)
username = raw_input('请输入用户名:\n')
password = raw_input('请输入密码:\n')
value = {'user_name': username, 'password': password}
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0'}
post = urllib.urlencode(value)
response = urllib2.urlopen(urllib2.Request(login, post, headers))
soup = BS(response.read())
if soup.find(text = 'Logout') != None:
print '登录成功!'
else:
print '登录失败,请重新登录!'
sys.exit(0) #退出程序
#2.获取学生名单的数据,主要用到的模块:xlrd
workbook = xlrd.open_workbook(os.getcwd() + '/Lists_15_Software.xlsx') #获得文件路径,打开Excel表格
sheet1 = workbook.sheet_by_name('Sheet1')
data = []
for row in range(1, sheet1.nrows):
info = []
info.append(int(sheet1.cell(row, 0).value))#学号
info.append(sheet1.cell(row, 2).value) #分组
info.append('无提交') #OJ昵称,默认为无提交
info.append(0) #AC,默认为0
info.append(0) #非JAVA提交,默认为0
data.append(((sheet1.cell(row, 1).value, info)))
data = dict(data) #得到以学生名字为键的字典
#3.解析排名榜,主要用到的模块:BeautifulSoup
cid = raw_input('请输入比赛的id:\n')
url = 'http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestranklist/cid/' + cid
soup = BS(urllib2.urlopen(url).read())
def Java(href): #统计每个学生JAVA语言AC的数量
t = set()
while True:
sub = BS(urllib2.urlopen(href).read())
for tr in sub.find_all('tr'):
td = tr.find_all('td')
try:
if td[3].text == 'Accepted' and td[6].text == 'java':
t.add(td[2].text)
except:
pass
try:
href = 'http://acm.sdut.edu.cn' + sub.find(class_ = 'next')['href']
except:
return len(t)
for tr in soup.find_all('tr'):
td = tr.find_all('td')
if td:
nickname = td[1].text
href = td[2].a.get('href')
ac = int(td[2].text)
try:
if nickname[-3].isdigit():
name = nickname[-2:]
else:
name = nickname[-3:]
data[name][2] = nickname
data[name][3] = ac
data[name][4] = ac - Java('http://acm.sdut.edu.cn' + href)
except:
pass
temp = []
for key in data:
temp = data[key]
temp.append(key) #把字典中的键(名字)也加入值(列表)中
data = list(data.values()) #舍弃键,只取包含所有数据的值(列表)
def my_cmp(a, b): #sort的cmp函数
if a[1] > b[1]:
return 1
if a[1] < b[1] or a[3] > b[3]:
return -1
if a[3] < b[3]:
return 1
return 0
data.sort(cmp = my_cmp) #排序,分组正序,AC逆序
#4.写入文件,主要用到的模块:xlwt
workbook = xlwt.Workbook(encoding = 'utf-8') #创建表格
sheet1 = workbook.add_sheet('Sheet1')
sheet1.col(0).width = 3500 #设置单元格宽度
sheet1.col(3).width = 4500
style = xlwt.easyxf('alignment: horz center, vert center') #设置样式,居中
row0 = [u'学号', u'姓名', u'分组', u'OJ昵称', u'AC', u'非JAVA提交']#表格第一行
for i in range(6):
sheet1.write(0, i, row0[i], style)
i = 1
for value in data: #将数据写入表格
sheet1.write(i, 0, value[0], style)
sheet1.write(i, 1, value[5], style)
sheet1.write(i, 2, value[1], style)
sheet1.write(i, 3, value[2], style)
sheet1.write(i, 4, value[3], style)
sheet1.write(i, 5, value[4], style)
i += 1 #行数加一
workbook.save('data.xls') #保存表格
一个测试的结果(cid-2038):