├── .gitignore
├── DriverNavigator.py
├── PageHandler
├── CompanyProblemPageHandler.py
├── Helper.py
├── LoginPageHandler.py
├── MainTableHandler.py
├── ProblemPageHandler.py
├── StudyPlanPageHandler.py
└── __init__.py
├── README.md
├── driver
└── chromedriver.exe
├── main.py
├── requirements.txt
└── urls
├── companyUrls.txt
├── problemUrls.txt
└── problemsetUrls.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | LeetcodeScrapper/*
2 | __pycache__/
3 | PageHandler/__pycache__/
4 | *.pyc
5 | Leetcode Scrapper Output/*
--------------------------------------------------------------------------------
/DriverNavigator.py:
--------------------------------------------------------------------------------
1 |
2 | import time
3 | from selenium.webdriver.common.by import By
4 | import random
5 | import os
6 | from PageHandler.Helper import PATH_MANAGER, NoCredentialsError
7 | from difflib import SequenceMatcher
8 |
9 |
10 | class DriverNavigator():
11 | def __init__(self, driver, stack, require_login) -> None:
12 | self.require_login = require_login
13 | self.driver = driver
14 | self.url_handlers = {}
15 | self.stack = stack
16 | self.fail_url = []
17 | self.login_url = "https://leetcode.com/accounts/login/"
18 |
19 | def add_url_handlers(self, url, handler):
20 | self.url_handlers[url] = handler
21 |
22 | def process_page(self):
23 | url = self.driver.current_url
24 | for i in self.url_handlers:
25 | if i in url:
26 | handler = self.url_handlers[i]
27 | try:
28 | handler.process_page()
29 | self.handle_success(handler, url)
30 | return
31 | except NoCredentialsError:
32 | url = self.stack.pop()
33 | print(url + " require login but no credetials passed")
34 | return
35 | except Exception as e:
36 | print(url, e)
37 | self.handle_fail(url)
38 | return
39 | print("invalid url")
40 | self.stack.pop()
41 |
42 |
43 | def handle_success(self, handler, url):
44 | if(is_same_link(url1=url, url2=self.stack[-1])):
45 | self.stack.pop()
46 | handler.log_data()
47 |
48 | def handle_fail(self, url):
49 | self.fail_url.append(url)
50 | if(is_same_link(url1=url, url2=self.stack[-1])):
51 | self.stack.pop()
52 |
53 | def need_to_relogin(self):
54 | is_logged_out = self.driver.find_elements(By.ID, "navbar_sign_in_button")
55 | login_url_is_not_queued = self.login_url not in self.driver.current_url
56 | is_need_to_authenticate = self.require_login
57 | return is_logged_out and login_url_is_not_queued and is_need_to_authenticate
58 |
59 |
60 | def run(self):
61 | while len(self.stack) > 0:
62 | print("Queue: " + str(len(self.stack)))
63 | self.driver.get(self.stack[-1])
64 | if (self.need_to_relogin()):
65 | self.stack.append(self.login_url)
66 | continue
67 | time.sleep(random.randint(1,5))
68 | self.process_page()
69 | self.log_failed_urls()
70 |
71 | def log_failed_urls(self):
72 | if(len(self.fail_url) ==0):
73 | return
74 | with open(os.path.join(PATH_MANAGER.target_path, 'fail_urls.txt'), 'w') as f:
75 | for line in self.fail_url:
76 | f.write(f"{line}\n")
77 |
78 |
79 | def is_same_link(url1, url2):
80 | return SequenceMatcher(None, url1, url2).ratio() > 0.9
81 |
--------------------------------------------------------------------------------
/PageHandler/CompanyProblemPageHandler.py:
--------------------------------------------------------------------------------
1 |
2 | from selenium.webdriver.common.by import By
3 | from selenium.webdriver.support.wait import WebDriverWait
4 | import time
5 | from urllib.parse import urlparse
6 | from PageHandler.Helper import log_data
7 |
8 |
9 | class CompanyProblemPageHandler():
10 | def __init__(self, driver) -> None:
11 | self.driver = driver
12 | self.problem_lists = []
13 | self.data = {}
14 |
15 | def clear_data(self):
16 | self.problem_lists = []
17 | self.data = {}
18 |
19 | def log_data(self):
20 | url_data = urlparse(self.driver.current_url)
21 | folder_name = url_data.path.split("/")[1]
22 | file_name = url_data.path.split("/")[2]
23 | self.data["companyName"] = file_name.split()
24 | log_data(self.data, folder_name=folder_name, file_name= file_name)
25 |
26 | def process_page(self):
27 | self.clear_data()
28 | WebDriverWait(self.driver, timeout=100).until(lambda d: d.find_element(By.ID,"react-select-2--value-item"))
29 | options_id = ['0', '1', '2', '3']
30 | for option_id in options_id:
31 | option_element_name = "react-select-2--option-" + option_id
32 | self.click_drop_down()
33 | time.sleep(1)
34 | if(self.is_option_exist(option_element_name)):
35 | self.driver.find_element(By.ID, option_element_name).click()
36 | time.sleep(1)
37 | data = self.get_table_data(duration=self.get_duration())
38 | self.problem_lists.append(data)
39 | breakpoint()
40 | self.data["data"] = self.problem_lists
41 |
42 | def click_drop_down(self):
43 | time_drop_down = self.driver.find_element(By.ID, "react-select-2--value-item")
44 | time_drop_down.click()
45 | time.sleep(0.5)
46 | return time_drop_down.text
47 |
48 | def get_duration(self):
49 | return self.driver.find_element(By.ID, "react-select-2--value-item").text
50 |
51 | def is_option_exist(self, element_id):
52 | if len(self.driver.find_elements(By.ID, element_id)) == 0:
53 | self.click_drop_down()
54 | return False
55 | return True
56 |
57 | def get_table_data(self, duration):
58 | script = '''
59 | const rows = document.getElementsByClassName('reactable-data')[0].children;
60 | const problems = [];
61 | for (const row of rows) {
62 | const problem = {}
63 | const cols = row.children;
64 | const tags = Array.from(cols[3].querySelectorAll('a')).map(t => t.innerText.trim()).join(', ');
65 | const frequency = parseFloat(row.getElementsByClassName('progress-bar')[0].style.width);
66 | const link = cols[2].querySelector('a').href;
67 | problem["problemId"] = cols[1].innerText.trim()
68 | problem["problemName"] = cols[2].innerText.trim()
69 | problem["acceptance"] = cols[3].innerText.trim()
70 | problem["difficulty"] = cols[4].innerText.trim()
71 | problem["frequency"] = frequency
72 | problem["url"] = link
73 | problems.push(problem)
74 | }
75 | return problems
76 | '''
77 | companyProblemsData = self.driver.execute_script(script)
78 | data ={"duration": duration, "problemData":companyProblemsData }
79 | return data
--------------------------------------------------------------------------------
/PageHandler/Helper.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | class PathManager():
6 | def __init__(self) -> None:
7 | self.path = os.getcwd()
8 | self.target_path = self.create_parent_folder()
9 |
10 | def create_parent_folder(self):
11 | folder_name = "Leetcode Scrapper Output"
12 | target_path = os.path.join(os.curdir , folder_name)
13 | try:
14 | os.mkdir(target_path)
15 | except FileExistsError:
16 | pass
17 | return target_path
18 |
19 | def get_path(self):
20 | return self.target_path
21 |
22 | def create_folder(self, name):
23 | end_path = os.path.join(self.target_path, name)
24 | try:
25 | os.mkdir(end_path)
26 | except FileExistsError as e:
27 | pass
28 | return end_path
29 |
30 | def create_status_log(self):
31 | pass
32 |
33 | PATH_MANAGER = PathManager()
34 |
35 | def log_data(data, folder_name, file_name):
36 | file_name += ".json"
37 | folder = PATH_MANAGER.create_folder(folder_name)
38 | with open(os.path.join(folder,file_name), "w") as f:
39 | json.dump(data, f)
40 |
41 |
42 | class NoCredentialsError(Exception):
43 | def __init__(self, url):
44 | self.message = f"The page {url} require login but login credentials not passed"
45 | super().__init__(self.message)
46 |
47 |
--------------------------------------------------------------------------------
/PageHandler/LoginPageHandler.py:
--------------------------------------------------------------------------------
1 |
2 | from selenium.webdriver.common.by import By
3 | from selenium.webdriver.support.wait import WebDriverWait
4 | import time
5 | from PageHandler.Helper import NoCredentialsError
6 | from selenium.common.exceptions import NoSuchElementException
7 |
8 | class LoginPageHandler():
9 | def __init__(self, driver , username, password) -> None:
10 | self.driver = driver
11 | self.username = username
12 | self.password = password
13 |
14 | def log_data(self):
15 | pass
16 |
17 | def is_capcha_required(self):
18 | iframes = self.driver.find_elements(By.CSS_SELECTOR,"iframe")
19 | if len(iframes) ==4:
20 | print("Captcha required, press any key after solving captcha")
21 | self.driver.maximize_window()
22 | input()
23 | self.try_click_login_btn()
24 |
25 |
26 | def check_page(self):
27 | WebDriverWait(self.driver, timeout=100).until(lambda d: d.find_element(By.ID,"id_login"))
28 |
29 | def try_click_login_btn(self):
30 | try:
31 | self.driver.find_element(By.CLASS_NAME, "btn-content__2V4r").click()
32 | except NoSuchElementException:
33 | pass
34 |
35 | def process_page(self):
36 | self.check_page()
37 | if self.username == "" or self.username == None:
38 | raise NoCredentialsError(self.driver.current_url)
39 | time.sleep(1)
40 | self.driver.find_element(by = By.ID, value = "id_login").send_keys(self.username)
41 | self.driver.find_element(by = By.ID, value = "id_password").send_keys(self.password)
42 | self.try_click_login_btn()
43 | time.sleep(3)
44 | self.is_capcha_required()
45 |
46 |
--------------------------------------------------------------------------------
/PageHandler/MainTableHandler.py:
--------------------------------------------------------------------------------
1 | from selenium.webdriver.common.by import By
2 | from selenium.webdriver.support.wait import WebDriverWait
3 | import time
4 | from PageHandler.Helper import log_data
5 | from urllib.parse import urlparse
6 | import re
7 |
8 | class MainTableHandler():
9 | def __init__(self, driver) -> None:
10 | self.driver = driver
11 | self.data = {}
12 |
13 | def check_page(self):
14 | WebDriverWait(self.driver, timeout=100).until(lambda d: d.find_element(By.CSS_SELECTOR,"div[role='rowgroup']"))
15 |
16 | def log_data(self):
17 | url_data = urlparse(self.driver.current_url)
18 | file_name = url_data.query
19 | file_name = re.sub(r'[^\w]', ' ', file_name)
20 | self.data["page"] = file_name.split(" ")[-1]
21 | folder_name = url_data.path.split("/")[1]
22 | log_data(self.data, folder_name=folder_name, file_name=file_name)
23 |
24 | def process_page(self):
25 | self.check_page()
26 | time.sleep(1)
27 | table = self.driver.find_elements(by = By.CSS_SELECTOR, value = "div[role='rowgroup']")[0]
28 | rows = table.find_elements(by = By.CSS_SELECTOR, value = "div[role='row']")
29 | complete_data = []
30 | for i in rows:
31 | row_data = self.get_row_data(i)
32 | complete_data.append(row_data)
33 | self.data["tableData"] = complete_data
34 |
35 | def get_current_page(self):
36 | return self.driver.current_url.split("=")[-1]
37 |
38 | def get_row_data(self, row):
39 | cells = row.find_elements(by = By.CSS_SELECTOR, value = "div[role='cell']")
40 | is_premium = (cells[0].find_elements(by = By.CLASS_NAME, value = "text-brand-orange") or None) != None
41 | problem_name = cells[1].text
42 | have_solution = len(cells[2].find_elements(by = By.TAG_NAME, value = "svg")) != 0
43 | solution_is_premium = len(cells[2].find_elements(by = By.CLASS_NAME, value = "text-purple")) != 0
44 | acceptence = cells[3].text
45 | difficulty = cells[4].text
46 | frequency = None
47 | if (cells[-1].find_elements(by = By.CLASS_NAME, value = "bg-brand-orange") or None != None):
48 | frequency = str(cells[-1].find_element(by = By.CLASS_NAME, value = "bg-brand-orange").get_attribute('style')).split(": ")[-1].replace(";", "")
49 | url = cells[1].find_element(by = By.TAG_NAME, value = "a").get_attribute('href')
50 | row_data = {
51 | "isPremium": is_premium,
52 | "problemName": problem_name,
53 | "haveSolution": have_solution,
54 | "isVideoSolution":solution_is_premium,
55 | "acceptance":acceptence,
56 | "difficulty": difficulty,
57 | "frequency":frequency,
58 | "url":url
59 | }
60 | return row_data
61 |
62 |
--------------------------------------------------------------------------------
/PageHandler/ProblemPageHandler.py:
--------------------------------------------------------------------------------
1 | from selenium.webdriver.common.by import By
2 | from selenium.webdriver.support.wait import WebDriverWait
3 | import time
4 | from PageHandler.Helper import log_data, NoCredentialsError
5 | from urllib.parse import urlparse
6 | from selenium.common.exceptions import NoSuchElementException
7 |
8 | class ProblemPageHandler():
9 | def __init__(self, driver) -> None:
10 | self.driver = driver
11 | self.data = {"tags":[], "problem": ""}
12 |
13 | def remove_on_focus_listener(self):
14 | script = '''
15 | Object.defineProperty(window.document,'hidden',{get:function(){return false;},configurable:true});
16 | Object.defineProperty(window.document,'visibilityState',{get:function(){return 'visible';},configurable:true});
17 | window.document.dispatchEvent(new Event('visibilitychange'));
18 | '''
19 | self.driver.execute_script(script)
20 |
21 | def get_problem_innerHTML(self):
22 | return self.driver.find_element(By.CLASS_NAME, "_1l1MA").get_attribute('innerHTML')
23 |
24 | def check_page(self):
25 | try:
26 | WebDriverWait(self.driver, timeout=10).until(lambda d: d.find_element(By.ID,"qd-content"))
27 | except Exception as e:
28 | if self.switch_to_new_version() == False:
29 | raise e
30 |
31 | def get_similar_questions(self):
32 | try:
33 | similar_question_tab = self.driver.find_elements(By.CLASS_NAME, "translate-y-0")[0]
34 | questions = similar_question_tab.find_elements(By.CLASS_NAME, "w-full")
35 | data = []
36 | for question in questions:
37 | question_name = question.find_elements(By.TAG_NAME, "a")[0].text
38 | difficulty = question.find_elements(By.CLASS_NAME, "text-xs")[0].text
39 | question_data = {"questionName": question_name, "difficulty": difficulty}
40 | data.append(question_data)
41 | return data
42 | except Exception as e:
43 | return []
44 |
45 | def open_all_lower_tab(self):
46 | tabs = self.driver.find_elements(By.CLASS_NAME, "py-3")
47 | for tab in tabs:
48 | pointers = tab.find_elements(By.CLASS_NAME, "cursor-pointer")
49 | if len(pointers) != 0:
50 | pointers[0].click()
51 | time.sleep(1.5)
52 |
53 |
54 | def get_related_topics(self):
55 | try:
56 | related_topic_tab = self.driver.find_elements(By.CLASS_NAME, "translate-y-0")[1]
57 | data = []
58 | tags = related_topic_tab.find_elements(By.TAG_NAME, "a")
59 | for tag in tags:
60 | data.append(tag.text)
61 | return data
62 | except Exception as e:
63 | return []
64 |
65 |
66 | def require_subscription(self):
67 | return len(self.driver.find_elements(By.CLASS_NAME, "text-2xl")) > 0
68 |
69 | def switch_to_new_version(self):
70 | new_btn = self.driver.find_elements(By.CLASS_NAME, "css-ly0btt-NewDiv")
71 | if len(new_btn) >0:
72 | new_btn[0].click()
73 | return True
74 | return False
75 |
76 |
77 | def get_companies_tags(self):
78 | try:
79 | row = self.driver.find_elements(By.CLASS_NAME, "flex-wrap")[0]
80 | row.find_elements(By.CLASS_NAME, "transition-colors")[-1].click()
81 | # time.sleep(1)
82 | WebDriverWait(self.driver, timeout=15).until(lambda d: d.find_element(By.CSS_SELECTOR,"div[role='dialog']"))
83 | dialog = self.driver.find_element(By.CSS_SELECTOR,"div[role='dialog']")
84 | tag_data = self.get_tag_data(dialog=dialog)
85 | return tag_data
86 | except Exception as e:
87 | self.data["isError"] = True
88 | print(self.driver.current_url)
89 | return []
90 |
91 |
92 | def process_page(self):
93 | self.data = {"tags":[], "problem": ""}
94 | self.check_page()
95 | # self.remove_on_focus_listener()
96 | time.sleep(2)
97 | if self.require_subscription():
98 | raise NoCredentialsError(self.driver.current_url)
99 | # self.open_all_lower_tab()
100 | self.data["relatedTopics"] = []
101 | self.data["similarQuestions"] = []
102 | self.data["problem"] = self.get_problem_innerHTML()
103 | self.data["tags"] = self.get_companies_tags()
104 | self.data["editorial"] = self. get_editorial()
105 |
106 | def get_editorial(self):
107 | try:
108 | self.driver.get(self.driver.current_url + "editorial")
109 | time.sleep(2)
110 | return self.driver.find_element(By.CLASS_NAME, "break-words").get_attribute('innerHTML')
111 | except:
112 | return ""
113 |
114 |
115 | def get_tag_data(self, dialog):
116 | buttons = dialog.find_element(By.CLASS_NAME, "space-x-9").find_elements(By.CLASS_NAME, "cursor-pointer")
117 | tag_data = []
118 | for button in buttons:
119 | button.click()
120 | time.sleep(2)
121 | duration = button.text
122 | companies = []
123 | datas = dialog.find_elements(By.CLASS_NAME, "mt-3")
124 | for data in datas:
125 | text = data.text
126 | companies.append([duration, text])
127 | tag_data.append({"duration": duration, "companies": companies})
128 | return tag_data
129 |
130 | def log_data(self):
131 | url_data = urlparse(self.driver.current_url)
132 | folder_name = url_data.path.split("/")[1]
133 | file_name = url_data.path.split("/")[2]
134 | self.data["problemName"] = file_name
135 | log_data(self.data, folder_name=folder_name, file_name=file_name)
136 |
--------------------------------------------------------------------------------
/PageHandler/StudyPlanPageHandler.py:
--------------------------------------------------------------------------------
1 |
2 | from selenium.webdriver.common.by import By
3 | from selenium.webdriver.support.wait import WebDriverWait
4 | import time
5 | from PageHandler.Helper import NoCredentialsError
6 | from urllib.parse import urlparse
7 | from PageHandler.Helper import log_data
8 | from selenium.common.exceptions import NoSuchElementException
9 |
10 |
11 | class StudyPlanPageHandler():
12 | def __init__(self, driver) -> None:
13 | self.driver = driver
14 | self.data = {}
15 |
16 |
17 | def log_data(self):
18 | url_data = urlparse(self.driver.current_url)
19 | folder_name = url_data.path.split("/")[1]
20 | file_name = url_data.path.split("/")[2]
21 | self.data["studyPlan"] = file_name
22 | log_data(self.data, folder_name=folder_name, file_name=file_name)
23 |
24 | def process_page(self):
25 | self.check_page()
26 | self.data = self.get_study_plan_data()
27 |
28 | def check_page(self):
29 | WebDriverWait(self.driver, timeout=100).until(lambda d: d.find_element(By.CLASS_NAME,"css-yw0m6t"))
30 |
31 | def get_study_plan_data(self):
32 | sections = self.driver.find_elements(By.CLASS_NAME, "css-yw0m6t")
33 | data = {}
34 | for i in sections:
35 | title = i.find_element(By.CLASS_NAME, "text-lc-text-primary").text
36 | problems = i.find_elements(By.CLASS_NAME, "truncate")
37 | problem_data = []
38 | for problem in problems:
39 | problem_data.append(problem.text)
40 | data[title] = problem_data
41 | return data
42 |
43 |
44 |
--------------------------------------------------------------------------------
/PageHandler/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Edwardsoen/LeetcodeScrapper/39b40dd4ac2030b7a818559d9940c7a5206dce3b/PageHandler/__init__.py
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Leetcode Scrapper
2 | LeetCode Scraper is a Selenium based Python script that scrapes information from Leetcode.com and stores the data in JSON format.
3 |
4 |
5 |
6 |
7 |
8 | > Note: if you just want to see company wise problems check out the subtree here , it is scraped in Febuary 2023. Alternatively you can checkout Leetcode Premium Unlocker browser extension, which will automatically inject premium data when you open the website.
9 |
10 | Dependencies
11 |
12 | ```
13 | selenium==4.8.0
14 | ```
15 |
16 |
17 |
18 | Currently Supported pages
19 | https://leetcode.com/problemset/*
20 | https://leetcode.com/problem-list/*
21 | https://leetcode.com/company/
22 |
23 |
24 | Usage
25 |
26 |
27 | clone repo + install dependencies
28 |
29 | ```
30 | git clone https://github.com/Edwardsoen/LeetcodeScrapper.git
31 | cd LeetcodeScrapper
32 | pip install -r requirements.txt
33 | ```
34 |
35 | download chromedriver here and paste it to system path
36 |
37 |
38 | if you want to scrape single page, simply run
39 | ```
40 | Python3 main.py {url}
41 | ```
42 | but in most cases you probably want to scrape multiple pages, in which case you need to store the urls into seperate txt file (or you can use pre-scrapped urls here) and pass it like this
43 | ```
44 | Python3 main.py {urlsfile.txt}
45 | ```
46 | if you need to scrape premium data you can pass username and password like so
47 | ```
48 | Python3 main.py -u {username} -p {password} {urls}
49 | ```
50 |
51 |
52 | Sample output
53 |
54 | Company Problem page
55 |
56 | ```
57 |
58 | {
59 | "data": [
60 | {
61 | "duration": "All time",
62 | "problemData": [
63 | {
64 | "acceptance": "73.6%",
65 | "difficulty": "Medium",
66 | "frequency": 0,
67 | "problemId": "2020",
68 | "problemName": "Number of Accounts That Did Not Stream",
69 | "url": "https://leetcode.com/problems/number-of-accounts-that-did-not-stream"
70 | }
71 | ]
72 | },
73 | {
74 | "duration": "All time",
75 | "problemData": [
76 | {
77 | "acceptance": "52.0%",
78 | "difficulty": "Medium",
79 | "frequency": 0,
80 | "problemId": "1990",
81 | "problemName": "Count the Number of Experiments",
82 | "url": "https://leetcode.com/problems/count-the-number-of-experiments"
83 | }
84 | ]
85 | },
86 | {
87 | "duration": "All time",
88 | "problemData": [
89 | {
90 | "acceptance": "72.7%",
91 | "difficulty": "Medium",
92 | "frequency": 0,
93 | "problemId": "1951",
94 | "problemName": "All the Pairs With the Maximum Number of Common Followers",
95 | "url": "https://leetcode.com/problems/all-the-pairs-with-the-maximum-number-of-common-followers"
96 | }
97 | ]
98 | }
99 | ],
100 | "companyName": [
101 | "instagram"
102 | ]
103 | }
104 |
105 | ```
106 |
107 |
108 | Front page
109 |
110 | ```
111 | {
112 | "tableData": [
113 | {
114 | "isPremium": false,
115 | "problemName": "2551. Put Marbles in Bags",
116 | "haveSolution": false,
117 | "isVideoSolution": false,
118 | "acceptance": "51.5%",
119 | "difficulty": "Hard",
120 | "frequency": "10.7001%",
121 | "url": "https://leetcode.com/problems/put-marbles-in-bags/"
122 | },
123 | {
124 | "isPremium": false,
125 | "problemName": "2552. Count Increasing Quadruplets",
126 | "haveSolution": false,
127 | "isVideoSolution": false,
128 | "acceptance": "31.5%",
129 | "difficulty": "Hard",
130 | "frequency": "7.09464%",
131 | "url": "https://leetcode.com/problems/count-increasing-quadruplets/"
132 | },
133 | {
134 | "isPremium": false,
135 | "problemName": "2553. Separate the Digits in an Array",
136 | "haveSolution": false,
137 | "isVideoSolution": false,
138 | "acceptance": "78.1%",
139 | "difficulty": "Easy",
140 | "frequency": "0%",
141 | "url": "https://leetcode.com/problems/separate-the-digits-in-an-array/"
142 | },
143 | {
144 | "isPremium": false,
145 | "problemName": "2554. Maximum Number of Integers to Choose From a Range I",
146 | "haveSolution": false,
147 | "isVideoSolution": false,
148 | "acceptance": "50.3%",
149 | "difficulty": "Medium",
150 | "frequency": "0%",
151 | "url": "https://leetcode.com/problems/maximum-number-of-integers-to-choose-from-a-range-i/"
152 | },
153 | {
154 | "isPremium": false,
155 | "problemName": "2555. Maximize Win From Two Segments",
156 | "haveSolution": false,
157 | "isVideoSolution": false,
158 | "acceptance": "22.8%",
159 | "difficulty": "Medium",
160 | "frequency": "0.166546%",
161 | "url": "https://leetcode.com/problems/maximize-win-from-two-segments/"
162 | },
163 | {
164 | "isPremium": false,
165 | "problemName": "2556. Disconnect Path in a Binary Matrix by at Most One Flip",
166 | "haveSolution": false,
167 | "isVideoSolution": false,
168 | "acceptance": "21.5%",
169 | "difficulty": "Medium",
170 | "frequency": "0%",
171 | "url": "https://leetcode.com/problems/disconnect-path-in-a-binary-matrix-by-at-most-one-flip/"
172 | },
173 | {
174 | "isPremium": false,
175 | "problemName": "2557. Maximum Number of Integers to Choose From a Range II",
176 | "haveSolution": false,
177 | "isVideoSolution": false,
178 | "acceptance": "49.4%",
179 | "difficulty": "Medium",
180 | "frequency": "0%",
181 | "url": "https://leetcode.com/problems/maximum-number-of-integers-to-choose-from-a-range-ii/"
182 | },
183 | {
184 | "isPremium": false,
185 | "problemName": "2558. Take Gifts From the Richest Pile",
186 | "haveSolution": false,
187 | "isVideoSolution": false,
188 | "acceptance": "63.6%",
189 | "difficulty": "Easy",
190 | "frequency": "0%",
191 | "url": "https://leetcode.com/problems/take-gifts-from-the-richest-pile/"
192 | },
193 | {
194 | "isPremium": false,
195 | "problemName": "2559. Count Vowel Strings in Ranges",
196 | "haveSolution": false,
197 | "isVideoSolution": false,
198 | "acceptance": "47.9%",
199 | "difficulty": "Medium",
200 | "frequency": "0%",
201 | "url": "https://leetcode.com/problems/count-vowel-strings-in-ranges/"
202 | },
203 | {
204 | "isPremium": false,
205 | "problemName": "2560. House Robber IV",
206 | "haveSolution": false,
207 | "isVideoSolution": false,
208 | "acceptance": "27.1%",
209 | "difficulty": "Medium",
210 | "frequency": "0%",
211 | "url": "https://leetcode.com/problems/house-robber-iv/"
212 | },
213 | {
214 | "isPremium": false,
215 | "problemName": "2561. Rearranging Fruits",
216 | "haveSolution": false,
217 | "isVideoSolution": false,
218 | "acceptance": "25.6%",
219 | "difficulty": "Hard",
220 | "frequency": "0%",
221 | "url": "https://leetcode.com/problems/rearranging-fruits/"
222 | }
223 | ],
224 | "page": "52"
225 | }
226 |
227 | ```
228 |
229 |
230 | Problem page
231 |
232 | ```
233 | {
234 | "tags": [
235 | {
236 | "duration": "1 year - 2 years",
237 | "companies": [
238 | [
239 | "1 year - 2 years",
240 | "Amazon"
241 | ]
242 | ]
243 | }
244 | ],
245 | "problem": "
You are given a 0-indexed integer array nums
and a positive integer k
.
\n\nWe call an index i
k-big if the following conditions are satisfied:
\n\n\n\t- There exist at least
k
different indices idx1
such that idx1 < i
and nums[idx1] < nums[i]
. \n\t- There exist at least
k
different indices idx2
such that idx2 > i
and nums[idx2] < nums[i]
. \n
\n\nReturn the number of k-big indices.
\n\n
\nExample 1:
\n\nInput: nums = [2,3,6,5,2,3], k = 2\nOutput: 2\nExplanation: There are only two 2-big indices in nums:\n- i = 2 --> There are two valid idx1: 0 and 1. There are three valid idx2: 2, 3, and 4.\n- i = 3 --> There are two valid idx1: 0 and 1. There are two valid idx2: 3 and 4.\n
\n\nExample 2:
\n\nInput: nums = [1,1,1], k = 3\nOutput: 0\nExplanation: There are no 3-big indices in nums.\n
\n\n
\nConstraints:
\n\n\n\t1 <= nums.length <= 105
\n\t1 <= nums[i], k <= nums.length
\n
\n",
246 | "relatedTopics": [
247 | "Array",
248 | "Binary Search",
249 | "Divide and Conquer",
250 | "Binary Indexed Tree",
251 | "Segment Tree",
252 | "Merge Sort",
253 | "Ordered Set"
254 | ],
255 | "similarQuestions": [
256 | {
257 | "questionName": "Count of Smaller Numbers After Self",
258 | "difficulty": "Hard"
259 | },
260 | {
261 | "questionName": "Find All Good Indices",
262 | "difficulty": "Medium"
263 | }
264 | ],
265 | "problemName": "count-the-number-of-k-big-indices"
266 | }
267 | ```
268 |
269 | Contributions
270 | If you have premium account and want to 'donate' data, feel free to open merge request (remember to force add the output folder, it is git-ignored by default).
271 |
272 |
273 |
--------------------------------------------------------------------------------
/driver/chromedriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Edwardsoen/LeetcodeScrapper/39b40dd4ac2030b7a818559d9940c7a5206dce3b/driver/chromedriver.exe
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | from DriverNavigator import DriverNavigator
3 | from selenium import webdriver
4 | from PageHandler.CompanyProblemPageHandler import CompanyProblemPageHandler
5 | from PageHandler.MainTableHandler import MainTableHandler
6 | from PageHandler.LoginPageHandler import LoginPageHandler
7 | from PageHandler.ProblemPageHandler import ProblemPageHandler
8 | from PageHandler.StudyPlanPageHandler import StudyPlanPageHandler
9 | import sys
10 | from selenium.webdriver.chrome.options import Options
11 | from urllib.parse import urlparse
12 |
13 | def read_from_file(path, target_stack):
14 | with open(path, "r") as f:
15 | for i in f.readlines():
16 | target_stack.append(i)
17 |
18 | def get_driver():
19 | user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/60.0.3112.50 Safari/537.36"
20 | options = Options()
21 | options.add_argument(f'user-agent={user_agent}')
22 | # options.headless = True
23 | driver = webdriver.Chrome(options= options)
24 | return driver
25 |
26 | def run_scrapper(stack, username = "" , password = "", require_login = False):
27 | driver = get_driver()
28 | navigator = DriverNavigator(driver=driver, stack = stack, require_login = require_login)
29 | navigator.add_url_handlers("https://leetcode.com/problemset/all/", MainTableHandler(driver))
30 | navigator.add_url_handlers("https://leetcode.com/problem-list/", MainTableHandler(driver))
31 | navigator.add_url_handlers("https://leetcode.com/company/", CompanyProblemPageHandler(driver))
32 | navigator.add_url_handlers("https://leetcode.com/accounts/login/", LoginPageHandler(driver, username , password))
33 | navigator.add_url_handlers("https://leetcode.com/subscribe/", LoginPageHandler(driver, username , password))
34 | navigator.add_url_handlers("https://leetcode.com/problems/",ProblemPageHandler(driver))
35 | navigator.add_url_handlers("https://leetcode.com/studyplan/",StudyPlanPageHandler(driver))
36 | input()
37 | navigator.run()
38 |
39 | if __name__ == "__main__":
40 | stack = []
41 | parser = argparse.ArgumentParser()
42 | parser.add_argument("-u", "--username")
43 | parser.add_argument("-p", "--password")
44 | parser.add_argument("run", nargs= '*')
45 | args = parser.parse_args()
46 |
47 | if args.username == None and args.password != None or args.username != None and args.password == None :
48 | print('Username or password missing')
49 | sys.exit()
50 |
51 | for i in args.run:
52 | if ".txt" in i:
53 | read_from_file(i, stack)
54 | else:
55 | stack.append(i)
56 |
57 | credential_is_passed = (args.username != None)
58 | print("Running Scrapper")
59 | run_scrapper(stack= stack, username=args.username, password= args.password, require_login = credential_is_passed)
60 |
61 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | selenium==4.8.0
2 |
--------------------------------------------------------------------------------
/urls/companyUrls.txt:
--------------------------------------------------------------------------------
1 | https://leetcode.com/company/amazon
2 | https://leetcode.com/company/google
3 | https://leetcode.com/company/microsoft
4 | https://leetcode.com/company/facebook
5 | https://leetcode.com/company/apple
6 | https://leetcode.com/company/bloomberg
7 | https://leetcode.com/company/adobe
8 | https://leetcode.com/company/uber
9 | https://leetcode.com/company/oracle
10 | https://leetcode.com/company/goldman-sachs
11 | https://leetcode.com/company/tiktok
12 | https://leetcode.com/company/bytedance
13 | https://leetcode.com/company/yahoo
14 | https://leetcode.com/company/linkedin
15 | https://leetcode.com/company/salesforce
16 | https://leetcode.com/company/snapchat
17 | https://leetcode.com/company/walmart-labs
18 | https://leetcode.com/company/vmware
19 | https://leetcode.com/company/ebay
20 | https://leetcode.com/company/twitter
21 | https://leetcode.com/company/expedia
22 | https://leetcode.com/company/paypal
23 | https://leetcode.com/company/cisco
24 | https://leetcode.com/company/doordash
25 | https://leetcode.com/company/yandex
26 | https://leetcode.com/company/intuit
27 | https://leetcode.com/company/jpmorgan
28 | https://leetcode.com/company/qualtrics
29 | https://leetcode.com/company/samsung
30 | https://leetcode.com/company/nvidia
31 | https://leetcode.com/company/visa
32 | https://leetcode.com/company/airbnb
33 | https://leetcode.com/company/infosys
34 | https://leetcode.com/company/citadel
35 | https://leetcode.com/company/flipkart
36 | https://leetcode.com/company/de-shaw
37 | https://leetcode.com/company/tcs
38 | https://leetcode.com/company/morgan-stanley
39 | https://leetcode.com/company/tesla
40 | https://leetcode.com/company/servicenow
41 | https://leetcode.com/company/zillow
42 | https://leetcode.com/company/square
43 | https://leetcode.com/company/wix
44 | https://leetcode.com/company/ibm
45 | https://leetcode.com/company/wayfair
46 | https://leetcode.com/company/intel
47 | https://leetcode.com/company/nutanix
48 | https://leetcode.com/company/qualcomm
49 | https://leetcode.com/company/splunk
50 | https://leetcode.com/company/atlassian
51 | https://leetcode.com/company/spotify
52 | https://leetcode.com/company/indeed
53 | https://leetcode.com/company/pinterest
54 | https://leetcode.com/company/arcesium
55 | https://leetcode.com/company/lyft
56 | https://leetcode.com/company/paytm
57 | https://leetcode.com/company/grab
58 | https://leetcode.com/company/twilio
59 | https://leetcode.com/company/wish
60 | https://leetcode.com/company/mathworks
61 | https://leetcode.com/company/yelp
62 | https://leetcode.com/company/capital-one
63 | https://leetcode.com/company/shopee
64 | https://leetcode.com/company/sap
65 | https://leetcode.com/company/twitch
66 | https://leetcode.com/company/american-express
67 | https://leetcode.com/company/rubrik
68 | https://leetcode.com/company/quora
69 | https://leetcode.com/company/roblox
70 | https://leetcode.com/company/palantir-technologies
71 | https://leetcode.com/company/zoho
72 | https://leetcode.com/company/dropbox
73 | https://leetcode.com/company/docusign
74 | https://leetcode.com/company/akuna-capital
75 | https://leetcode.com/company/hrt
76 | https://leetcode.com/company/zenefits
77 | https://leetcode.com/company/cruise-automation
78 | https://leetcode.com/company/sprinklr
79 | https://leetcode.com/company/medianet
80 | https://leetcode.com/company/swiggy
81 | https://leetcode.com/company/karat
82 | https://leetcode.com/company/phonepe
83 | https://leetcode.com/company/coupang
84 | https://leetcode.com/company/dunzo
85 | https://leetcode.com/company/makemytrip
86 | https://leetcode.com/company/c3-iot
87 | https://leetcode.com/company/databricks
88 | https://leetcode.com/company/zoom
89 | https://leetcode.com/company/bookingcom
90 | https://leetcode.com/company/tusimple
91 | https://leetcode.com/company/pocket-gems
92 | https://leetcode.com/company/reddit
93 | https://leetcode.com/company/two-sigma
94 | https://leetcode.com/company/nagarro
95 | https://leetcode.com/company/hbo
96 | https://leetcode.com/company/arista-networks
97 | https://leetcode.com/company/godaddy
98 | https://leetcode.com/company/accolite
99 | https://leetcode.com/company/accenture
100 | https://leetcode.com/company/robinhood
101 | https://leetcode.com/company/blackrock
102 | https://leetcode.com/company/netflix
103 | https://leetcode.com/company/hotstar
104 | https://leetcode.com/company/coinbase
105 | https://leetcode.com/company/audible
106 | https://leetcode.com/company/bolt
107 | https://leetcode.com/company/factset
108 | https://leetcode.com/company/epam-systems
109 | https://leetcode.com/company/sharechat
110 | https://leetcode.com/company/coursera
111 | https://leetcode.com/company/ixl
112 | https://leetcode.com/company/mindtickle
113 | https://leetcode.com/company/citrix
114 | https://leetcode.com/company/huawei
115 | https://leetcode.com/company/instacart
116 | https://leetcode.com/company/baidu
117 | https://leetcode.com/company/directi
118 | https://leetcode.com/company/deutsche-bank
119 | https://leetcode.com/company/dell
120 | https://leetcode.com/company/cognizant
121 | https://leetcode.com/company/codenation
122 | https://leetcode.com/company/sumologic
123 | https://leetcode.com/company/affirm
124 | https://leetcode.com/company/hulu
125 | https://leetcode.com/company/mckinsey
126 | https://leetcode.com/company/epic-systems
127 | https://leetcode.com/company/cohesity
128 | https://leetcode.com/company/hudson-river-trading
129 | https://leetcode.com/company/liveramp
130 | https://leetcode.com/company/virtu
131 | https://leetcode.com/company/myntra
132 | https://leetcode.com/company/ponyai
133 | https://leetcode.com/company/jane-street
134 | https://leetcode.com/company/zscaler
135 | https://leetcode.com/company/capgemini
136 | https://leetcode.com/company/mercari
137 | https://leetcode.com/company/redfin
138 | https://leetcode.com/company/duolingo
139 | https://leetcode.com/company/zynga
140 | https://leetcode.com/company/houzz
141 | https://leetcode.com/company/cloudera
142 | https://leetcode.com/company/groupon
143 | https://leetcode.com/company/drw
144 | https://leetcode.com/company/optum
145 | https://leetcode.com/company/zomato
146 | https://leetcode.com/company/alibaba
147 | https://leetcode.com/company/razorpay
148 | https://leetcode.com/company/toptal
149 | https://leetcode.com/company/asana
150 | https://leetcode.com/company/poshmark
151 | https://leetcode.com/company/tableau
152 | https://leetcode.com/company/juspay
153 | https://leetcode.com/company/opendoor
154 | https://leetcode.com/company/epifi
155 | https://leetcode.com/company/gsn-games
156 | https://leetcode.com/company/point72
157 | https://leetcode.com/company/akamai
158 | https://leetcode.com/company/alation
159 | https://leetcode.com/company/tencent
160 | https://leetcode.com/company/works-applications
161 | https://leetcode.com/company/dataminr
162 | https://leetcode.com/company/payu
163 | https://leetcode.com/company/athenahealth
164 | https://leetcode.com/company/clari
165 | https://leetcode.com/company/riot-games
166 | https://leetcode.com/company/box
167 | https://leetcode.com/company/appdynamics
168 | https://leetcode.com/company/deloitte
169 | https://leetcode.com/company/pure-storage
170 | https://leetcode.com/company/inmobi
171 | https://leetcode.com/company/united-health-group
172 | https://leetcode.com/company/siemens
173 | https://leetcode.com/company/airtel
174 | https://leetcode.com/company/persistent-systems
175 | https://leetcode.com/company/barclays
176 | https://leetcode.com/company/jump-trading
177 | https://leetcode.com/company/snapdeal
178 | https://leetcode.com/company/trilogy
179 | https://leetcode.com/company/commvault
180 | https://leetcode.com/company/didi
181 | https://leetcode.com/company/paypay
182 | https://leetcode.com/company/lucid
183 | https://leetcode.com/company/activision
184 | https://leetcode.com/company/quip
185 | https://leetcode.com/company/postmates
186 | https://leetcode.com/company/info-edge
187 | https://leetcode.com/company/softwire
188 | https://leetcode.com/company/zopsmart
189 | https://leetcode.com/company/societe-generale
190 | https://leetcode.com/company/tripadvisor
191 | https://leetcode.com/company/mindtree
192 | https://leetcode.com/company/lending-club
193 | https://leetcode.com/company/national-instruments
194 | https://leetcode.com/company/sapient
195 | https://leetcode.com/company/tiger-analytics
196 | https://leetcode.com/company/avalara
197 | https://leetcode.com/company/aqr-capital-management-llc
198 | https://leetcode.com/company/maq-software
199 | https://leetcode.com/company/canonical
200 | https://leetcode.com/company/cashfree
201 | https://leetcode.com/company/stripe
202 | https://leetcode.com/company/garena
203 | https://leetcode.com/company/netease
204 | https://leetcode.com/company/helix
205 | https://leetcode.com/company/machine-zone
206 | https://leetcode.com/company/honeywell
207 | https://leetcode.com/company/fleetx
208 | https://leetcode.com/company/wayve
209 | https://leetcode.com/company/kakao
210 | https://leetcode.com/company/veritas
211 | https://leetcode.com/company/soundhound
212 | https://leetcode.com/company/netsuite
213 | https://leetcode.com/company/thomson-reuters
214 | https://leetcode.com/company/lowe
215 | https://leetcode.com/company/analytics-quotient
216 | https://leetcode.com/company/electronic-arts
217 | https://leetcode.com/company/blizzard
218 | https://leetcode.com/company/aetion
219 | https://leetcode.com/company/rackspace
220 | https://leetcode.com/company/fallible
221 | https://leetcode.com/company/zappos
222 | https://leetcode.com/company/gilt-groupe
223 | https://leetcode.com/company/valve
224 | https://leetcode.com/company/poynt
225 | https://leetcode.com/company/ge-digital
226 | https://leetcode.com/company/triplebyte
227 | https://leetcode.com/company/yatra
228 | https://leetcode.com/company/radius
229 | https://leetcode.com/company/drawbridge
230 | https://leetcode.com/company/jingchi
231 | https://leetcode.com/company/forusall
232 | https://leetcode.com/company/iit-bombay
233 | https://leetcode.com/company/leap-motion
234 | https://leetcode.com/company/affinity
235 | https://leetcode.com/company/nextjump
236 | https://leetcode.com/company/edabit
237 | https://leetcode.com/company/allincall
238 | https://leetcode.com/company/general-electric
239 | https://leetcode.com/company/vimeo
240 | https://leetcode.com/company/codeagon
241 | https://leetcode.com/company/mobisy
242 | https://leetcode.com/company/quince
243 | https://leetcode.com/company/moengage
244 | https://leetcode.com/company/alphonso
245 | https://leetcode.com/company/xing
246 | https://leetcode.com/company/ge-healthcare
247 | https://leetcode.com/company/code-studio
248 | https://leetcode.com/company/tiaa
249 | https://leetcode.com/company/ascend
250 | https://leetcode.com/company/t-system
251 | https://leetcode.com/company/sony
252 | https://leetcode.com/company/jeavio
253 | https://leetcode.com/company/bitgo
254 | https://leetcode.com/company/mishipay
255 | https://leetcode.com/company/retailmenot
256 | https://leetcode.com/company/zeta-suite
257 | https://leetcode.com/company/fpt
258 | https://leetcode.com/company/t-mobiles
259 | https://leetcode.com/company/wealthfront
260 | https://leetcode.com/company/pickrr
261 | https://leetcode.com/company/opentext
262 | https://leetcode.com/company/discord
263 | https://leetcode.com/company/altimetrik
264 | https://leetcode.com/company/dailyhunt
265 | https://leetcode.com/company/fourkites
266 | https://leetcode.com/company/bridgewater-associates
267 | https://leetcode.com/company/unbxd
268 | https://leetcode.com/company/zendesk
269 | https://leetcode.com/company/machinezone
270 | https://leetcode.com/company/coderbyte
271 | https://leetcode.com/company/instagram
272 | https://leetcode.com/company/strava
273 | https://leetcode.com/company/warnermedia
274 |
--------------------------------------------------------------------------------
/urls/problemUrls.txt:
--------------------------------------------------------------------------------
1 | https://leetcode.com/problems/two-sum/
2 | https://leetcode.com/problems/add-two-numbers/
3 | https://leetcode.com/problems/longest-substring-without-repeating-characters/
4 | https://leetcode.com/problems/median-of-two-sorted-arrays/
5 |
--------------------------------------------------------------------------------
/urls/problemsetUrls.txt:
--------------------------------------------------------------------------------
1 | https://leetcode.com/problemset/all/?page=1
2 | https://leetcode.com/problemset/all/?page=2
3 | https://leetcode.com/problemset/all/?page=3
4 | https://leetcode.com/problemset/all/?page=4
5 | https://leetcode.com/problemset/all/?page=5
6 | https://leetcode.com/problemset/all/?page=6
7 | https://leetcode.com/problemset/all/?page=7
8 | https://leetcode.com/problemset/all/?page=8
9 | https://leetcode.com/problemset/all/?page=9
10 | https://leetcode.com/problemset/all/?page=10
11 | https://leetcode.com/problemset/all/?page=11
12 | https://leetcode.com/problemset/all/?page=12
13 | https://leetcode.com/problemset/all/?page=13
14 | https://leetcode.com/problemset/all/?page=14
15 | https://leetcode.com/problemset/all/?page=15
16 | https://leetcode.com/problemset/all/?page=16
17 | https://leetcode.com/problemset/all/?page=17
18 | https://leetcode.com/problemset/all/?page=18
19 | https://leetcode.com/problemset/all/?page=19
20 | https://leetcode.com/problemset/all/?page=20
21 | https://leetcode.com/problemset/all/?page=21
22 | https://leetcode.com/problemset/all/?page=22
23 | https://leetcode.com/problemset/all/?page=23
24 | https://leetcode.com/problemset/all/?page=24
25 | https://leetcode.com/problemset/all/?page=25
26 | https://leetcode.com/problemset/all/?page=26
27 | https://leetcode.com/problemset/all/?page=27
28 | https://leetcode.com/problemset/all/?page=28
29 | https://leetcode.com/problemset/all/?page=29
30 | https://leetcode.com/problemset/all/?page=30
31 | https://leetcode.com/problemset/all/?page=31
32 | https://leetcode.com/problemset/all/?page=32
33 | https://leetcode.com/problemset/all/?page=33
34 | https://leetcode.com/problemset/all/?page=34
35 | https://leetcode.com/problemset/all/?page=35
36 | https://leetcode.com/problemset/all/?page=36
37 | https://leetcode.com/problemset/all/?page=37
38 | https://leetcode.com/problemset/all/?page=38
39 | https://leetcode.com/problemset/all/?page=39
40 | https://leetcode.com/problemset/all/?page=40
41 | https://leetcode.com/problemset/all/?page=41
42 | https://leetcode.com/problemset/all/?page=42
43 | https://leetcode.com/problemset/all/?page=43
44 | https://leetcode.com/problemset/all/?page=44
45 | https://leetcode.com/problemset/all/?page=45
46 | https://leetcode.com/problemset/all/?page=46
47 | https://leetcode.com/problemset/all/?page=47
48 | https://leetcode.com/problemset/all/?page=48
49 | https://leetcode.com/problemset/all/?page=49
50 | https://leetcode.com/problemset/all/?page=50
51 | https://leetcode.com/problemset/all/?page=51
52 | https://leetcode.com/problemset/all/?page=52
53 | https://leetcode.com/problemset/all/?page=53
54 | https://leetcode.com/problemset/all/?page=54
55 | https://leetcode.com/problemset/all/?page=55
56 | https://leetcode.com/problemset/all/?page=56
57 |
--------------------------------------------------------------------------------