def download(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return [] # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) samples = utils.SampleZipper() lang = None for pre, h3 in self._find_sample_tags(soup): s = utils.textfile(utils.dos2unix(pre.string.lstrip())) name = h3.string l = self._get_tag_lang(pre) if lang is None: lang = l elif lang != l: log.info( 'skipped due to language: current one is %s, not %s: %s ', lang, l, name) continue samples.add(s, name) return samples.get()
def login_with_github(self, get_credentials, session=None): session = session or requests.Session() url = 'https://yukicoder.me/auth/github' # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() if urllib.parse.urlparse(resp.url).hostname == 'yukicoder.me': log.info('You have already signed in.') return True # redirect to github.com # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form') if not form: log.error('form not found') log.info('Did you logged in?') return False log.debug('form: %s', str(form)) # post username, password = get_credentials() form = utils.FormSender(form, url=resp.url) form.set('login', username) form.set('password', password) resp = form.request(session) resp.raise_for_status() if urllib.parse.urlparse(resp.url).hostname == 'yukicoder.me': log.success('You signed in.') return True else: log.failure('You failed to sign in. Wrong user ID or password.') return False
def login(self, get_credentials, session=None): session = session or requests.Session() url = 'https://practice.contest.atcoder.jp/login' # get log.status('GET: %s', url) resp = session.get(url, allow_redirects=False) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) for msg in msgs: log.status('message: %s', msg) if msgs: return 'login' not in resp.url # post username, password = get_credentials() log.status('POST: %s', url) resp = session.post(url, data={ 'name': username, 'password': password }, allow_redirects=False) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) AtCoderService._report_messages(msgs) return 'login' not in resp.url # AtCoder redirects to the top page if success
def download(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) samples = utils.SampleZipper() for pre in soup.find_all('pre'): log.debug('pre: %s', str(pre)) hn = utils.previous_sibling_tag(pre) log.debug('hN: %s', str(hn)) log.debug(hn) if hn and hn.name in [ 'h2', 'h3' ] and hn.string and 'ample' in hn.string.lower( ): # 'ample' is the suffix of 'sample', 'example' s = utils.textfile(pre.string.lstrip()) name = hn.string samples.add(s, name) return samples.get()
def submit(self, code, language, session=None): assert language in self.get_language_dict(session=session) session = session or requests.Session() url = self.get_url() + '/submit' # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', action=re.compile(r'/submit$')) if not form: log.error('form not found') return None log.debug('form: %s', str(form)) # post form = utils.FormSender(form, url=resp.url) if False: form.set('source', code) else: form.set_file('file', ('source', code)) form.set('lang', language) resp = form.request(session=session) resp.raise_for_status() # result if '/submissions/' in resp.url: log.success('success: result: %s', resp.url) return resp.url else: log.failure('failure') return None
def download(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) samples = utils.SampleZipper() for tag in soup.find_all('div', class_=re.compile( '^(in|out)put$')): # Codeforces writes very nice HTML :) log.debug('tag: %s', str(tag)) assert len(list(tag.children)) title, pre = list(tag.children) assert 'title' in title.attrs['class'] assert pre.name == 'pre' s = '' for it in pre.children: if it.name == 'br': s += '\n' else: s += it.string samples.add(s, title.string) return samples.get()
def login(self, get_credentials, session=None): session = session or requests.Session() url = 'http://codeforces.com/enter' # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() if resp.url != url: # redirected log.info('You have already signed in.') return True # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', id='enterForm') log.debug('form: %s', str(form)) username, password = get_credentials() form = utils.FormSender(form, url=resp.url) form.set('handle', username) form.set('password', password) form.set('remember', 'on') # post resp = form.request(session) resp.raise_for_status() if resp.url != url: # redirected log.success('Welcome, %s.', username) return True else: log.failure('Invalid handle or password.') return False
def get_input_format(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) for h4 in soup.find_all('h4'): if h4.string == '入力': return h4.parent.find('pre').string
def download(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) samples = utils.SampleZipper() for h2 in soup.find_all('h2'): it = self._parse_sample_tag(h2) if it is not None: s, name = it samples.add(s, name) return samples.get()
def download_all(self, session=None): session = session or requests.Session() url = 'http://yukicoder.me/problems/no/{}/testcase.zip'.format(self.problem_no) # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() # parse samples = collections.defaultdict(list) with zipfile.ZipFile(io.BytesIO(resp.content)) as fh: for filename in sorted(fh.namelist()): # "test_in" < "test_out" s = fh.read(filename).decode() name = os.path.basename(filename) if os.path.splitext(name)[1] == '.in': # ".in" extension is confusing name = os.path.splitext(name)[0] print(filename, name) samples[os.path.basename(filename)] += [( s, name )] return sorted(samples.values())
def get_input_format(self, session=None): session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return '' # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) for h3 in soup.find_all('h3'): if h3.string == '入力': s = '' for it in h3.parent.find('pre'): s += it.string or it # AtCoder uses <var>...</var> for math symbols return s
def _get_task_id(self, session=None): if self._task_id is None: session = session or requests.Session() url = self.get_url() # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return {} # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) submit = soup.find('a', href=re.compile(r'^/submit\?task_id=')) if not submit: log.error('link to submit not found') return False m = re.match(r'^/submit\?task_id=([0-9]+)$', submit.attrs['href']) assert m self._task_id = int(m.group(1)) return self._task_id
def get_language_dict(self, session=None): session = session or requests.Session() url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id) # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return {} # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) select = soup.find( 'select', class_='submit-language-selector' ) # NOTE: AtCoder can vary languages depending on tasks, even in one contest. here, ignores this fact. language_dict = {} for option in select.find_all('option'): language_dict[option.attrs['value']] = { 'description': option.string } return language_dict
def submit(self, code, language, session=None): assert language in self.get_language_dict(session=session) session = session or requests.Session() url = 'http://{}.contest.atcoder.jp/submit'.format(self.contest_id) # get log.status('GET: %s', url) resp = session.get(url) log.status(utils.describe_status_code(resp.status_code)) resp.raise_for_status() msgs = AtCoderService._get_messages_from_cookie(resp.cookies) if AtCoderService._report_messages(msgs, unexpected=True): return None # parse soup = bs4.BeautifulSoup(resp.content.decode(resp.encoding), utils.html_parser) form = soup.find('form', action=re.compile(r'^/submit\?task_id=')) if not form: log.error('form not found') return None log.debug('form: %s', str(form)) # post task_id = self._get_task_id(session=session) form = utils.FormSender(form, url=resp.url) form.set('task_id', str(task_id)) form.set('source_code', code) form.set('language_id_{}'.format(task_id), language) resp = form.request(session=session) resp.raise_for_status() # result msgs = AtCoderService._get_messages_from_cookie(resp.cookies) AtCoderService._report_messages(msgs) if '/submissions/me' in resp.url: log.success('success: result: %s', resp.url) return resp.url else: log.failure('failure') return None