Codeforces 開催日時取得プログラムβ
TopcoderのSRM開催日時を取得するプログラムのついでにCodeforcesのほうもテキトーに書いた.こっちのほうはページの仕様が変わりそうだしサーバが不調そうなのでCodeforcesと同じようにベータ扱い.
対象URL:http://www.codeforces.com/contests
使用ライブラリ
HTMLParser(http://htmlparser.sourceforge.net/)
出力(12月25日時点)
>UpcomingContests CodeforcesContest [name=Codeforces Beta Round #48, isPast=false, data=2010年12月29日(水)01時00分, duration=150] >ContestHistory CodeforcesContest [name=Codeforces Beta Round #47, isPast=true, data=2010年12月20日, duration=120] CodeforcesContest [name=Codeforces Beta Round #46 (Div. 2), isPast=true, data=2010年12月17日, duration=120] CodeforcesContest [name=School Personal Contest #3 (Winter Computer School 2010/11), isPast=true, data=2010年12月12日, duration=180] CodeforcesContest [name=Codeforces Beta Round #44 (Div. 2), isPast=true, data=2010年12月07日, duration=120] CodeforcesContest [name=School Personal Contest #2 (Winter Computer School 2010/11), isPast=true, data=2010年12月05日, duration=180] ...
コード
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; import org.htmlparser.Parser; import org.htmlparser.filters.HasAttributeFilter; import org.htmlparser.filters.NodeClassFilter; import org.htmlparser.tags.TableColumn; import org.htmlparser.tags.TableRow; import org.htmlparser.tags.TableTag; import org.htmlparser.util.NodeList; public class Main { public static void main(String[] args) throws Exception { Main main = new Main(); System.out.println(">UpcomingContests"); for(CodeforcesContest contest : main.getUpcomingContests()){ System.out.println(contest); } System.out.println(">ContestHistory"); for(CodeforcesContest contest : main.getContestHistory()){ System.out.println(contest); } } private static final String url = "http://codeforces.com/contests"; private static final SimpleDateFormat parseFormat1; private static final SimpleDateFormat parseFormat2; private static final SimpleDateFormat printFormat1; private static final SimpleDateFormat printFormat2; static { Locale us = Locale.US, jp = Locale.JAPAN; parseFormat1 = new SimpleDateFormat("MM/dd/yyyy hh:mma", us); parseFormat1.setTimeZone(TimeZone.getTimeZone("GMT+03:00")); parseFormat2 = new SimpleDateFormat("MM/dd/yyyy", us); parseFormat2.setTimeZone(TimeZone.getTimeZone("GMT+03:00")); printFormat1 = new SimpleDateFormat("yyyy年MM月dd日(E)HH時mm分", jp); printFormat1.setTimeZone(TimeZone.getTimeZone("GMT+09:00")); printFormat2 = new SimpleDateFormat("yyyy年MM月dd日", jp); printFormat2.setTimeZone(TimeZone.getTimeZone("GMT+09:00")); } public Main() { try { Parser parser = new Parser(url); // NodeList list = parser.parse(new HasAttributeFilter("class", // "contestlist")); NodeList list = parser.parse(new HasAttributeFilter("class", "datatable")); NodeList tables = list.extractAllNodesThatMatch( new NodeClassFilter(TableTag.class), true); TableTag ucTable = (TableTag) tables.elementAt(0); upcomingContests = getContests(ucTable, false); TableTag chTable = (TableTag) tables.elementAt(1); contestHistory = getContests(chTable, true); } catch (Exception e) { // log (network) } } private List<CodeforcesContest> getContests(TableTag table, boolean isPast) { List<CodeforcesContest> contests = new ArrayList<CodeforcesContest>(); for (TableRow row : Arrays.copyOfRange(table.getRows(), 1, table.getRowCount())) { CodeforcesContest contest = new CodeforcesContest(); TableColumn[] cols = row.getColumns(); contest.setName(toName(cols[0])); contest.setDate(toDate(cols[1]), isPast); contest.setDuration(toDurMins(cols[2])); contests.add(contest); } return contests; } private List<CodeforcesContest> upcomingContests; private List<CodeforcesContest> contestHistory; public List<CodeforcesContest> getUpcomingContests() { return upcomingContests; } public List<CodeforcesContest> getContestHistory() { return contestHistory; } private String toName(TableColumn col) { return col.getFirstChild().toPlainTextString().trim(); } private Date toDate(TableColumn col) { String str = col.toPlainTextString().trim(); Date r = null; try { if (str.matches("\\d{2}/\\d{2}/\\d{4}")) { r = parseFormat2.parse(str); } else { r = parseFormat1.parse(str); } } catch (Exception e) { // log } return r; } private int toDurMins(TableColumn col) { String[] strs = col.toPlainTextString().trim().split(":"); return 60 * new Integer(strs[0]) + new Integer(strs[1]); } static public class CodeforcesContest { private String name; private boolean isPast; private Date date; private int duration; // minutes @Override public String toString() { DateFormat format = isPast ? printFormat2 : printFormat1; return "CodeforcesContest [name=" + name + ", isPast=" + isPast + ", date=" + format.format(date) + ", duration=" + duration + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDate() { return date; } public void setDate(Date date, boolean isPast) { this.date = date; this.isPast = isPast; } public boolean isPast() { return isPast; } public int getDuration() { return duration; } public void setDuration(int duration) { this.duration = duration; } } }