Closed7

AtCoderのSubmissionコードをローカルに保存し、GitHubにプッシュする

AtCoderで提出したACコードを取得し、ローカルに保存する

目的

  • AtCoderで自分が提出したACコードを取得し、GitHubにデプロイする

仕様

  • 提出した問題のうち、最新のACコードを取得する
  • コンテストごとにフォルダを分けて、問題ごとにファイルを作成する

言語

  • Python (3.7.0)

ライブラリ

  • スクレイピング
    • Selenium
  • Git
    • GitPython

API

AtCoder Problems APIを用いたユーザの提出データのjsonの取得

APIのリンク

https://github.com/kenkoooo/AtCoderProblems/blob/master/doc/api.md

コード

import requests
import json

userID = "tishii24"
api_path = "https://kenkoooo.com/atcoder/atcoder-api/results?user="

# APIを用いた提出データの取得
def getSubmissionData(userID):
    api_url = api_path + userID
    response = requests.get(api_url)
    jsonData = response.json()
    return jsonData

submissions = getSubmissionData(userID)

最新のAC提出のデータのみに絞る

コード

# 各問題において最も新しいAC提出のみを取得する
# 各コンテストごとにまとめて返す
def collectNewestAcceptedSubmissions(submissions):
    sortedData = sorted(submissions, key=lambda x: x['id'])  # IDで昇順ソートすると古い順になる
    submits = {} # 各問題ごとに最新の提出に更新する
    for data in sortedData:
        if data["result"] != "AC": # ACだった提出だけ対象
            continue
        submits[data["problem_id"]] = data
    
    result = {} # コンテストごとにまとめる
    for sub in submits.values():
        if not sub["contest_id"] in result:
            result[sub["contest_id"]] = []
        result[sub["contest_id"]].append(sub)
    return result

newestSubmits =  collectNewestAcceptedSubmissions(submissions)

ディレクトリの作成

コード

import os
root = "submissions/"

for contestName in newestSubmits:
    path = root + contestName
    os.makedirs(path, exist_ok=True)

ファイルの作成と書き込み、フォーマット

コード

import chromedriver_binary
from selenium import webdriver
from time import sleep
import subprocess

driver = webdriver.Chrome()

for submissions in newestSubmits.values():
    for sub in submissions:
        # 問題番号の取得
        problem_num = sub["problem_id"][-1]
        
        # 古い問題の場合には数字になっているので、アルファベットに戻す
        if problem_num.isdigit():
            problem_num = chr(int(problem_num)+ord('a')-1)
        
        # 作成するファイルへのパス
        path = root + sub["contest_id"] + "/" + problem_num
        # 拡張子の設定(C++, Pythonのみ)
        if "C++" in sub["language"]:
            path += ".cpp"
        elif "Python" in sub["language"]:
            path += ".py"
        
        # 既に提出コードがある場合は取得せず、次の問題の提出を探す
        if os.path.isfile(path): continue
        
        # 提出ページへアクセス
        sub_url = "https://atcoder.jp/contests/" + sub["contest_id"] + "/submissions/" + str(sub["id"])
        driver.get(sub_url)
        
        # 提出コードの取得
        code = driver.find_element_by_id("submission-code") 
            
        # 書き込み
        with open(path, 'w') as f:
            f.write(code.text)
        
        # C++の場合にはclang-formatを使ってフォーマットする
        if "C++" in sub["language"]:
            subprocess.call(["clang-format", "-i",  "-style=file", path])
            
        # アクセス負荷軽減のために時間をおく(3秒)
        sleep(3)
driver.quit()

.clang-formatの中身

コード

BasedOnStyle:  Google
IndentWidth: 4
ColumnLimit: 0

GitHubにプッシュする

# GitHubにプッシュ
import git
import datetime

dt_now = datetime.datetime.now()
repo_url = "https://github.com/tishii2479/atcoder.git"
repo = git.Repo()
repo.git.add("*")
repo.git.commit("*", message="add submission: " + dt_now.strftime('%Y/%m/%d %H:%M:%S'))
repo.git.push("origin", "main")
このスクラップは2021/04/13にクローズされました
ログインするとコメントできます