概要
わたしは AtCoder の過去問をテキトーに解くだけでやっているうち、どの問題をどれだけ解いたのかわからなくなってしまいました。なので、スクレイピングで過去の ABC の解答状況を表示させるコードを書いてみました。
公式 API があればいちばんよいのでしょうが、どうもないようなので、Ruby を使ってスクレイピングしています。問題があればコメント欄で御指摘願います。
結果
ABC245
B - Mex (Elixir (1.10.2))
D - Polynomial division (Elixir (1.10.2))
C - Choose Elements (Elixir (1.10.2))
A - Good morning (Elixir (1.10.2))
D - Polynomial division (Ruby (2.7.1))
C - Choose Elements (Ruby (2.7.1))
B - Mex (Ruby (2.7.1))
A - Good morning (Ruby (2.7.1))
ABC244
D - Swap Hats (Elixir (1.10.2))
C - Yamanote Line Game (Elixir (1.10.2))
B - Go Straight and Turn Right (Elixir (1.10.2))
A - Last Letter (Elixir (1.10.2))
D - Swap Hats (Ruby (2.7.1))
C - Yamanote Line Game (Ruby (2.7.1))
B - Go Straight and Turn Right (Ruby (2.7.1))
A - Last Letter (Ruby (2.7.1))
......
ABC213
D - Takahashi Tour (Ruby (2.7.1))
B - Booby Prize (Ruby (2.7.1))
C - Reorder Cards (Ruby (2.7.1))
A - Bitwise Exclusive Or (Ruby (2.7.1))
ABC212
D - Querying Multiset (Ruby (2.7.1))
C - Min Difference (Ruby (2.7.1))
B - Weak Password (Ruby (2.7.1))
A - Alloy (Ruby (2.7.1))
ABC211
ABC210
ABC209
ABC208
......
こんな感じになります。ABC211 以前は解いていないのかな、って感じになっています。なお、表示されるのは「AC」を取ったものだけです。
前提
gem "mechanize" をインストールして下さい。ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux] で確認しましたが、サポートされているバージョンなら別に問題なく実行できると思います。
コード
自分の「ユーザ名」と「パスワード」を.value =
のあとに埋めて下さい。また、コンテストはここでは ABC245 以前に対応しているので、定数LatestABCContest
を適宜変更して下さい。
atcoder_check.rb
require "mechanize"
LatestABCContest = ARGV.shift&.to_i || 245
agent = Mechanize.new
#login
url = "https://atcoder.jp/login?continue=https%3A%2F%2Fatcoder.jp%2F"
page = agent.get(url)
login_form = page.forms[1]
login_form.field_with(name: 'username').value = '自分のユーザ名'
login_form.field_with(name: 'password').value = 'パスワード'
page = agent.submit(login_form)
#ページ取得
define_method(:get_page) do |problem_number|
num = "%03d" % problem_number
puts "ABC" + num
url = "https://atcoder.jp/contests/abc#{num}/submissions/me"
page = agent.get(url)
sleep(1)
result = page.css("table tbody tr").map {|node|
tds = node.css("td")
if tds.empty?
nil
else
problem = tds&.at(1)&.text
language = tds&.at(3)&.text
c_result = tds&.at(6)&.text
if c_result == "AC"
" " + problem.ljust(40) + "(#{language})"
else
nil
end
end
}.compact.uniq
puts result
end
LatestABCContest.downto(1) { |num| get_page(num) }
見ればわかると思いますが、表示させたいコンテストを変えるには最後の1行をいじればよいです。