|
4 | 4 | import warnings |
5 | 5 | from http.cookiejar import LWPCookieJar |
6 | 6 | from typing import List, Optional, Tuple, Union |
| 7 | +from urllib3.util.retry import Retry |
7 | 8 |
|
8 | 9 | import requests |
9 | 10 | from bs4 import BeautifulSoup |
@@ -66,7 +67,12 @@ def default_credential_supplier() -> Tuple[str, str]: |
66 | 67 | class AtCoderClient(metaclass=Singleton): |
67 | 68 |
|
68 | 69 | def __init__(self): |
69 | | - self._session = requests.Session() |
| 70 | + session = requests.Session() |
| 71 | + retries = Retry(total=3, |
| 72 | + backoff_factor=0.5, |
| 73 | + status_forcelist=[status for status in range(400, 600)]) |
| 74 | + session.mount("https://", requests.adapters.HTTPAdapter(max_retries=retries)) |
| 75 | + self._session = session |
70 | 76 |
|
71 | 77 | def check_logging_in(self): |
72 | 78 | private_url = "https://atcoder.jp/home" |
@@ -110,10 +116,11 @@ def login(self, |
110 | 116 | save_cookie(self._session) |
111 | 117 |
|
112 | 118 | def download_problem_list(self, contest: Contest) -> List[Problem]: |
113 | | - resp = self._request(contest.get_problem_list_url()) |
114 | | - soup = BeautifulSoup(resp.text, "html.parser") |
115 | | - if resp.status_code == 404: |
| 119 | + try: |
| 120 | + resp = self._request(contest.get_problem_list_url()) |
| 121 | + except requests.exceptions.RetryError: |
116 | 122 | raise PageNotFoundError |
| 123 | + soup = BeautifulSoup(resp.text, "html.parser") |
117 | 124 | res = [] |
118 | 125 | for tag in soup.find('table').select('tr')[1::]: |
119 | 126 | tag = tag.find("a") |
|
0 commit comments