def _get_gym_contest_rating(contest_id): star_rating = [DEFAULT_PROBLEM_RATING, 1200, 1600, 2000, 2400, 2800] mapping = Mapping.get_by_id('gym-{}'.format(contest_id)) stars = mapping.value if stars: return star_rating[int(stars)] url = 'https://codeforces.com/gyms' req = SpiderHttp() res = req.get(url=url) soup = BeautifulSoup(res.text, 'lxml') token = soup.find('input', {'name': 'csrf_token'})['value'] res = req.post(url=url, data={ 'csrf_token': token, 'searchByNameOrIdQuery': contest_id, 'searchByProblem': False, }) soup = BeautifulSoup(res.text, 'lxml') stars = len( soup.find('tr', { 'data-contestid': contest_id }).findAll('img')) mapping.modify(value=str(stars)) return star_rating[stars]
class VjudgeSpider(BaseSpider): def __init__(self): self.vjudge_http = SpiderHttp() def get_user_info(self, oj_username, accept_problems): username = oj_username.oj_username password = oj_username.oj_password try: cookie = json.loads(oj_username.oj_cookies) headers = {'Cookie': Cookie.dict_to_str(cookie)} self.vjudge_http.headers.update(headers) assert self.check_login_status() == username except: try: cookie = self._get_cookies(username, password) except: return {'success': False, 'data': []} headers = {'Cookie': Cookie.dict_to_str(cookie)} self.vjudge_http.headers.update(headers) assert self.check_login_status() == username oj_username.modify(oj_cookies=json.dumps(cookie, sort_keys=True)) accept_problem_list = [] success = False start = 0 length = 20 ok = False while not ok: url = "https://vjudge.net/status/data/?&length=20&res=1&start={}&un={}".format( start, username) res = self.vjudge_http.get(url=url).json() if not res['data']: break success = True for submission in res['data']: if submission['statusCanonical'] != 'AC': continue time_stamp = submission['time'] / 1000 accept_time = timestamp_to_str(time_stamp) oj = self._change_oj_name(submission['oj']) problem_id = submission['probNum'] if accept_problems.get('{}-{}'.format( oj, problem_id)) == accept_time: ok = True continue accept_problem_list.append({ 'oj': oj, 'problem_pid': problem_id, 'accept_time': accept_time }) start += length return {'success': success, 'data': accept_problem_list} def check_login_status(self): url = 'https://vjudge.net/user/update' res = self.vjudge_http.get(url=url).json() return res.get('username', None) def _get_cookies(self, username, password): url = 'https://vjudge.net/user/login' data = {'username': username, 'password': password} res = self.vjudge_http.post(url=url, data=data).text if res == 'success': return Cookie.str_to_dict( Cookie.dict_to_str(self.vjudge_http.sess.cookies)) raise Exception(res) def get_problem_info(self, problem_id): pass @staticmethod def _change_oj_name(name): name = name.lower() if name == 'gym': name = 'codeforces' elif name == 'zju': name = 'zoj' elif name == 'pku': name = 'poj' elif name == '计蒜客': name = 'jisuanke' elif name == 'uvalive': name = 'uva' elif name == 'libreoj': name = 'loj' return name
class ZuccSpider(BaseSpider): zucc_http = SpiderHttp() def __init__(self): try: self.check_cookie() except AssertionError: self.get_new_cookie() self.check_cookie() def check_cookie(self): self.zucc_http = SpiderHttp() mapping = Mapping.get_by_id('zucc-cookie') cookie = json.loads(mapping.value) for k, v in cookie.items(): self.zucc_http.sess.cookies.set(k, v) self.zucc_http.sess.cookies.set("lang", "cn") assert self.check_login_status() == ZUCC_ID def get_new_cookie(self): self.zucc_http = SpiderHttp() self.login(ZUCC_ID, ZUCC_PASSWORD) assert self.check_login_status() == ZUCC_ID cookie = {} for i in self.zucc_http.sess.cookies: cookie[i.name] = i.value Mapping.get_by_id('zucc-cookie').modify( value=json.dumps(cookie, sort_keys=True)) def get_user_info(self, oj_username, accept_problems): username = oj_username.oj_username if not self._judge_user(username): return {'success': False, 'data': []} accept_problem_list = [] url = 'http://acm.zucc.edu.cn/status.php?user_id={}'.format(username) ok = False while not ok: res = self.zucc_http.get(url=url) soup = BeautifulSoup(res.text, 'lxml') trs = soup.find('tbody').find_all('tr') next = -1 if not trs: break for tr in trs: tds = tr.find_all('td') next = int(tds[0].text) status = tds[3].find_all('a')[0]['class'] if 'label-success' not in status: continue problem_id = tds[2].text accept_time = tds[8].text accept_time = re.findall( r'\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}', accept_time)[0] if accept_problems.get('zucc-' + problem_id) == accept_time: ok = True continue accept_problem_list.append({ 'oj': 'zucc', 'problem_pid': problem_id, 'accept_time': accept_time }) new_url = 'http://acm.zucc.edu.cn/status.php?user_id={}&top={}'.format( username, next - 1) if new_url == url: break url = new_url return {'success': True, 'data': accept_problem_list} def get_problem_info(self, problem_id): url = 'http://acm.zucc.edu.cn/problem.php?id={}'.format(problem_id) res = self.zucc_http.get(url=url) try: total = int( re.search(r'Submit: </span>(\d+)( )*<span', res.text).group(1)) accept = int( re.search(r'Solved: </span>(\d+)( )*<br>', res.text).group(1)) rating = DEFAULT_PROBLEM_RATING except: rating = DEFAULT_PROBLEM_RATING return {'rating': rating} def _judge_user(self, username): url = 'http://acm.zucc.edu.cn/userinfo.php?user={}'.format(username) res = self.zucc_http.get(url=url) return not re.findall(r"No such User!", res.text) def check_login_status(self): url = 'http://acm.zucc.edu.cn/template/bs3/profile.php' res = self.zucc_http.get(url=url) try: return re.search( r'document\.getElementById\("profile"\)\.innerHTML="(.*)";', res.text).group(1) except: return None def _get_csrf_value(self): url = 'http://acm.zucc.edu.cn/csrf.php' res = self.zucc_http.get(url=url) return re.search(r'value="(.*?)"', res.text).group(1) def login(self, username, password): url = 'http://acm.zucc.edu.cn/login.php' data = { 'user_id': username, 'password': password, 'csrf': self._get_csrf_value() } res = self.zucc_http.post(url=url, data=data)