開催中のコンテストなど、ログインが必要なコンテストでも取得するべくセッションを利用するように変更。(参考: GitHub - kyuridenamida/atcoder-tools: Convenient modules & tools for AtCoder users, written in Python 3.5)
import os
from typing import Optional
from http.cookiejar import LWPCookieJar
import pyperclip
import requests
import bs4
CONTEST = 'abc124'
USERNAME = ''
PASSWORD = ''
url_root = 'https://atcoder.jp'
default_cookie_path = os.path.dirname(__file__) + '/session.txt'
def dokuwiki_link(url, title):
return '[[' + url + '|' + title + ']]'
def save_cookie(session: requests.Session, cookie_path: Optional[str] = None):
cookie_path = cookie_path or default_cookie_path
os.makedirs(os.path.dirname(cookie_path), exist_ok=True)
session.cookies.save()
os.chmod(cookie_path, 0o600)
def load_cookie_to(session: requests.Session, cookie_path: Optional[str] = None):
cookie_path = cookie_path or default_cookie_path
session.cookies = LWPCookieJar(cookie_path)
if os.path.exists(cookie_path):
session.cookies.load()
return True
return False
def try_login(session):
login_url = url_root + '/login'
# ユーザー名がログインページに含まれるかで、ログイン状態を判定
# もしユーザー名が一般的で非ログイン時でも当てはまってしまう場合はもう少し工夫が必要
r = session.get(login_url)
if USERNAME in r.text:
# print('Already logged in.')
return True
# csrf_token取得
s = bs4.BeautifulSoup(r.text, 'lxml')
csrf_token = s.find(attrs={'name': 'csrf_token'}).get('value')
post_data = {
"csrf_token": csrf_token,
"username": USERNAME,
"password": PASSWORD,
}
r = session.post(login_url, data=post_data)
if 'tokens mismatch.' in r.text:
print('Login error.')
print(r.text)
return False
save_cookie(session)
return True
def main():
# セッション開始
session = requests.Session()
load_cookie_to(session)
if try_login(session):
pass
else:
return
tasks_url = url_root + f'/contests/{CONTEST}/tasks'
r = session.get(tasks_url)
bs = bs4.BeautifulSoup(r.text, 'lxml')
problem_urls = []
tbl = bs.find('table').find('tbody')
for tr in tbl.find_all('tr'):
problem_url = tr.find('td').find('a').get('href')
problem_urls.append(problem_url)
contest_title = bs.select('#main-div a.contest-title')[0]
dokuwiki_buf = []
dokuwiki_buf.append('======' + contest_title.text + '======\n\n')
dokuwiki_buf.append(dokuwiki_link(url_root + contest_title.get('href'), contest_title.text) + '\n\n')
for problem_url in problem_urls:
problem_url = url_root + problem_url
r = session.get(problem_url)
bs = bs4.BeautifulSoup(r.text, 'lxml')
title = bs.find('title').text
dokuwiki_buf.append('===== ' + title + ' =====\n\n')
dokuwiki_buf.append(dokuwiki_link(problem_url, title) + '\n\n')
dokuwiki_buf.append('==== 問題 ====\n\n\n')
dokuwiki_buf.append('==== 例 ====\n\n\n')
dokuwiki_buf.append('==== 解法 ====\n\n\n')
dokuwiki_buf.append('<sxh python>\n\n\n< /sxh>\n\n\n')
# print(''.join(dokuwiki_buf))
pyperclip.copy(''.join(dokuwiki_buf))
if __name__ == '__main__':
main()
41行目の</sxh>が干渉しちゃうのでスペース入れてるけど、取る。