1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| import re import sys from functools import lru_cache
import requests
url = 'https://leetcode-cn.com/graphql'
@lru_cache def loadPage(page): query = "{\n localRankingV2(page:" + str( page) + ") {\nmyRank {\nattendedContestCount\ncurrentRatingRanking\ndataRegion\nisDeleted\n" \ "user {\nrealName\nuserAvatar\nuserSlug\n__typename\n}\n__typename\n}\npage\ntotalUsers\nuserPerPage\n" \ "rankingNodes {\nattendedContestCount\ncurrentRatingRanking\ndataRegion\nisDeleted\n" \ "user {\nrealName\nuserAvatar\nuserSlug\n__typename\n}\n__typename\n}\n__typename\n }\n}\n" retry = 0 while retry < 3: resp = requests.post(url=url, json={'query': query}) if resp.status_code == 200: nodes = resp.json()['data']['localRankingV2']['rankingNodes'] return [(int(nd['currentRatingRanking']), nd['user']['userSlug']) for nd in nodes] else: retry += 1 return None
@lru_cache def getUserRank(uid): operationName = "userContest" query = "query userContest($userSlug: String!){\n userContestRanking(userSlug: $userSlug){" \ "\ncurrentRatingRanking\nratingHistory\n}\n}\n " variables = {'userSlug': uid} retry = 0 while retry < 3: resp = requests.post(url=url, json={ 'operationName': operationName, 'query': query, 'variables': variables }) if resp.status_code == 200: ranking = resp.json()['data']['userContestRanking'] score = None if ranking and 'ratingHistory' in ranking: s = ranking['ratingHistory'] mth = re.search(r'(\d+(?:\.\d+)?)(?:, null)*]$', s) if mth: score = mth.group(1) return (ranking['currentRatingRanking'], float(score)) if score else (None, None) else: retry += 1 return None, None
def get1600Count() -> int: l, r = 1, 3000 while l < r: mid = (l + r + 1) // 2 page = loadPage(mid) print(f'第 {mid} 页:', page) if not page: return 0 score = None for _, uid in page: if not uid: continue score = getUserRank(uid)[1] if score is not None: break if score < 1600: r = mid - 1 else: l = mid page = [uid for _, uid in loadPage(l) if uid] print('校准中...') l, r = 0, len(page) - 1 while l < r: mid = (l + r + 1) // 2 ranking, score = getUserRank(page[mid]) if score < 1600: r = mid - 1 else: l = mid
return getUserRank(page[l])[0]
@lru_cache def getUser(rank, alter): while rank: if rank <= 0: raise Exception('无效的排名') p = (rank - 1) // 25 + 1 off = (rank - 1) % 25 page = loadPage(p) if page[off][1]: ranking, score = getUserRank(page[off][1]) return score, page[off][1] else: rank += alter return '--', '--'
total = get1600Count() if not total: print('网络故障') sys.exit() print(f'1600 分以上共计 {total} 人')
guardian = int(total * 0.05) knight = int(total * 0.25) g_first, g_last = getUser(1, 1), getUser(guardian, -1) print(f'Guardian(top 5%): 共 {guardian} 名,守门员 {g_last[0]} 分(uid: {g_last[1]}),最高 {g_first[0]} 分(uid: {g_first[1]})') k_first, k_last = getUser(guardian + 1, 1), getUser(knight, -1) print(f'Knight(top 25%): 共 {knight} 名,守门员 {k_last[0]} 分(uid: {k_last[1]}),最高 {k_first[0]} 分(uid: {k_first[1]})')
|