Fetch the repository succeeded.
from string import Template
import requests
import urllib3
urllib3.disable_warnings()
class Ranking:
def __init__(self, region='CN', retry=3):
self.retry = retry
self.region = region
if region == 'CN':
self.url = 'https://leetcode.cn/graphql'
self.page_query = Template(
"{\n localRankingV2(page:$page) {\nmyRank {\nattendedContestCount\n"
"currentRatingRanking\ndataRegion\nisDeleted\nuser {\nrealName\n"
"userAvatar\nuserSlug\n__typename\n}\n__typename\n}\npage\ntotalUsers\n"
"userPerPage\nrankingNodes {\nattendedContestCount\ncurrentRatingRanking\n"
"dataRegion\nisDeleted\nuser {\nrealName\nuserAvatar\nuserSlug\n__typename\n}\n__"
"typename\n}\n__typename\n }\n}\n"
)
else:
self.url = 'https://leetcode.com/graphql'
self.page_query = Template(
"{\nglobalRanking(page:$page){\ntotalUsers\nuserPerPage\nmyRank{\nranking\n"
"currentGlobalRanking\ncurrentRating\ndataRegion\nuser{\nnameColor\nactiveBadge{\n"
"displayName\nicon\n__typename\n}\n__typename\n}\n__typename\n}\nrankingNodes{\n"
"ranking\ncurrentRating\ncurrentGlobalRanking\ndataRegion\nuser{\nusername\nnameColor\n"
"activeBadge{\ndisplayName\nicon\n__typename\n}\nprofile{\nuserAvatar\ncountryCode\n"
"countryName\nrealName\n__typename\n}\n__typename\n}\n__typename\n}\n__typename\n}\n}\n"
)
def load_page(self, page):
query = self.page_query.substitute(page=page)
for _ in range(self.retry):
resp = requests.post(url=self.url, json={'query': query}, verify=False)
if resp.status_code != 200:
continue
nodes = resp.json()['data'][
'localRankingV2' if self.region == 'CN' else 'globalRanking'
]['rankingNodes']
if self.region == 'CN':
return [
(int(v['currentRatingRanking']), v['user']['userSlug'])
for v in nodes
]
else:
return [
(int(v['currentGlobalRanking']), v['user']['username'])
for v in nodes
]
return []
def _user_ranking(self, region, uid):
if region == 'CN':
key = 'userSlug'
url = 'https://leetcode.cn/graphql/noj-go/'
query = (
"\nquery userContestRankingInfo($userSlug:String!){\nuserContestRanking"
"(userSlug:$userSlug){\nattendedContestsCount\nrating\nglobalRanking\nlocalRanking\n"
"globalTotalParticipants\nlocalTotalParticipants\ntopPercentage\n}\n"
"userContestRankingHistory(userSlug:$userSlug){\nattended\ntotalProblems\n"
"trendingDirection\nfinishTimeInSeconds\nrating\nscore\nranking\ncontest{\n"
"title\ntitleCn\nstartTime\n}\n}\n}\n"
)
else:
key = 'username'
url = 'https://leetcode.com/graphql'
query = (
"\nquery userContestRankingInfo($username:String!){\nuserContestRanking"
"(username:$username){\nattendedContestsCount\nrating\nglobalRanking\n"
"totalParticipants\ntopPercentage\nbadge{\nname\n}\n}\nuserContestRankingHistory"
"(username:$username){\nattended\ntrendDirection\nproblemsSolved\n"
"totalProblems\nfinishTimeInSeconds\nrating\nranking\ncontest{\n"
"title\nstartTime\n}\n}\n}\n "
)
variables = {key: uid}
for _ in range(self.retry):
resp = requests.post(
url=url, json={'query': query, 'variables': variables}, verify=False
)
if resp.status_code != 200:
continue
res = resp.json()
if 'errors' in res:
break
ranking = res['data']['userContestRanking']
if ranking and 'rating' in ranking:
score = float(ranking['rating'])
if 'localRanking' in ranking:
return int(ranking['localRanking']), score
if 'globalRanking' in ranking:
return int(ranking['globalRanking']), score
return None, None
def get_user_ranking(self, uid):
for region in ['CN', 'US']:
# 美国站会有国服用户,这里最多需要查询两次
ranking, score = self._user_ranking(region, uid)
if score is not None:
return ranking, score
return None
def get_1600_count(self):
left, right = 1, 4000
while left < right:
mid = (left + right + 1) >> 1
page = self.load_page(mid)
print(f'第 {mid} 页:', page)
if not page:
return 0
ranking, score = self.get_user_ranking(page[0][1])
if score >= 1600:
left = mid
else:
right = mid - 1
page = [uid for _, uid in self.load_page(left) if uid]
print('校准中...')
left, right = 0, len(page) - 1
while left < right:
mid = (left + right + 1) >> 1
ranking, score = self.get_user_ranking(page[mid])
if score >= 1600:
left = mid
else:
right = mid - 1
return self.get_user_ranking(page[left])[0]
def get_user(self, rank):
p = (rank - 1) // 25 + 1
offset = (rank - 1) % 25
page = self.load_page(p)
_, score = self.get_user_ranking(page[offset][1])
return score, page[offset][1]
def fetch_ranking_data(self):
total = self.get_1600_count()
if not total:
return
print(f'[{self.region}] 1600 分以上共计 {total} 人')
guardian = int(total * 0.05)
knight = int(total * 0.25)
g_first, g_last = self.get_user(1), self.get_user(guardian)
print(
f'Guardian(top 5%): 共 {guardian} 名,守门员 {g_last[0]} 分(uid: {g_last[1]}),最高 {g_first[0]} 分(uid: {g_first[1]})'
)
k_first, k_last = self.get_user(guardian + 1), self.get_user(knight)
print(
f'Knight(top 25%): 共 {knight} 名,守门员 {k_last[0]} 分(uid: {k_last[1]}),最高 {k_first[0]} 分(uid: {k_first[1]})'
)
# 国服竞赛排名
lk = Ranking(region='CN')
lk.fetch_ranking_data()
print('\n------------------------------\n')
# 全球竞赛排名
gk = Ranking(region='US')
gk.fetch_ranking_data()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。