Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 30ce47a

Browse files
committed
feat: add python scripts
1 parent b5b03b4 commit 30ce47a

File tree

7 files changed

+180
-0
lines changed

7 files changed

+180
-0
lines changed

‎solution/__init__.py‎

Whitespace-only changes.
1.15 KB
Binary file not shown.
1.44 KB
Binary file not shown.

‎solution/config.py‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# urls
2+
from enum import unique, Enum
3+
4+
cn_graphql_url = 'https://leetcode-cn.com/graphql'
5+
problems_url = 'https://leetcode-cn.com/problems/'
6+
all_problems_url = 'https://leetcode.com/api/problems/all/'
7+
lcof_problems_url = 'https://leetcode-cn.com/api/problems/lcof/'
8+
lcci_problems_url = 'https://leetcode-cn.com/api/problems/lcci/'
9+
10+
# http
11+
fetch_timeout = 5
12+
async_headers = {
13+
'accept': 'application/json, text/javascript, */*; q=0.01',
14+
'content-type': 'application/json',
15+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
16+
'Chrome/77.0.3865.120 Safari/537.36',
17+
'x-requested-with': 'XMLHttpRequest'
18+
}
19+
20+
# retrying
21+
retry_max_number = 8
22+
retry_min_random_wait = 50 # ms
23+
retry_max_random_wait = 100 # ms
24+
25+
# maps
26+
difficulties = {
27+
'1': '简单',
28+
'2': '中等',
29+
'3': '困难'
30+
}
31+
32+
33+
# request
34+
@unique
35+
class Req(Enum):
36+
GET = 0
37+
POST = 1

‎solution/fetch.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import requests
2+
from requests import Response
3+
from retrying import retry
4+
5+
from config import Req, retry_max_number, retry_min_random_wait, retry_max_random_wait, fetch_timeout
6+
7+
8+
def need_retry(exception):
9+
result = isinstance(exception, (requests.ConnectionError,
10+
requests.ReadTimeout,
11+
requests.exceptions.ConnectTimeout,
12+
requests.exceptions.ReadTimeout,
13+
requests.exceptions.Timeout))
14+
if result:
15+
print('Exception:{} occurred, retrying...'.format(type(exception)))
16+
return result
17+
18+
19+
def fetch(url, method=Req.GET, **kwargs):
20+
@retry(stop_max_attempt_number=retry_max_number, wait_random_min=retry_min_random_wait,
21+
wait_random_max=retry_max_random_wait, retry_on_exception=need_retry)
22+
def _fetch(url, **kwargs) -> Response:
23+
# kwargs.update({'verify': False})
24+
kwargs.update({'timeout': fetch_timeout})
25+
response = requests.post(url, **kwargs) if method == Req.POST else requests.get(url, **kwargs)
26+
if response.status_code != 200:
27+
raise requests.ConnectionError('Expected status code 200, but got {}'.format(response.status_code))
28+
return response
29+
30+
try:
31+
resp = _fetch(url, **kwargs)
32+
return resp
33+
except Exception as e:
34+
print('Something got wrong, error msg:{}'.format(e))
35+
return None

‎solution/leetcode_spider.py‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import json
2+
from urllib.parse import quote
3+
4+
from config import async_headers, cn_graphql_url, Req, all_problems_url, difficulties, lcof_problems_url, \
5+
lcci_problems_url, problems_url
6+
from fetch import fetch
7+
8+
9+
def get_cn_questions() -> dict:
10+
"""获取所有题目的ID和中文标题"""
11+
form_data = {
12+
'operationName': 'getQuestionTranslation',
13+
'variables': {
14+
15+
},
16+
'query': 'query getQuestionTranslation($lang: String) {\n translations: '
17+
'allAppliedQuestionTranslations(lang: $lang) {\n title\n questionId\n __typename\n }\n}\n'
18+
}
19+
20+
resp = fetch(url=cn_graphql_url, method=Req.POST, headers=async_headers, data=json.dumps(form_data))
21+
if resp is None:
22+
return dict()
23+
res = resp.json()
24+
questions = res['data']['translations']
25+
final_res = dict()
26+
for q in questions:
27+
qid = str(q['questionId']).zfill(4)
28+
final_res[qid] = q['title']
29+
return final_res
30+
31+
32+
def get_all_questions():
33+
"""获取所有题目"""
34+
cn_res = get_cn_questions()
35+
resp = fetch(url=all_problems_url, headers=async_headers)
36+
if resp is None:
37+
return
38+
res = resp.json()
39+
questions = res['stat_status_pairs']
40+
41+
for question in questions:
42+
qid = str(question['stat']['question_id']).zfill(4)
43+
title = question['stat']['question__title']
44+
link = problems_url + question['stat']['question__title_slug']
45+
git_link = '/solution/{}/README.md'.format(qid + '.' + quote(title))
46+
cn_title = cn_res.get(qid) or title
47+
col1 = '[{}]({})'.format(qid, link)
48+
col2 = '[{}]({})'.format(cn_title, git_link)
49+
col3 = difficulties.get(str(question['difficulty']['level']))
50+
yield [col1, col2, col3]
51+
52+
53+
def get_lcof_questions():
54+
"""获取剑指Offer题目"""
55+
resp = fetch(url=lcof_problems_url, headers=async_headers)
56+
if resp is None:
57+
return None
58+
res = resp.json()
59+
questions = res['stat_status_pairs']
60+
for question in questions:
61+
fe_qid = question['stat']['frontend_question_id']
62+
qno = fe_qid.replace('面试题', '').strip()
63+
title = question['stat']['question__title'].replace(' LCOF', '').strip()
64+
link = problems_url + question['stat']['question__title_slug']
65+
git_link = '/lcof/{}/README.md'.format(quote(fe_qid + '. ' + title))
66+
col1 = '[{}]({})'.format(qno, link)
67+
col2 = '[{}]({})'.format(title, git_link)
68+
col3 = difficulties.get(str(question['difficulty']['level']))
69+
yield [col1, col2, col3]
70+
71+
72+
def get_lcci_questions():
73+
"""获取程序员面试金典题目"""
74+
cn_res = get_cn_questions()
75+
resp = fetch(url=lcci_problems_url, headers=async_headers)
76+
if resp is None:
77+
return None
78+
res = resp.json()
79+
questions = res['stat_status_pairs']
80+
for question in questions:
81+
qid = question['stat']['question_id']
82+
fe_qid = question['stat']['frontend_question_id']
83+
qno = fe_qid.replace('面试题', '').strip()
84+
cn_title = cn_res.get(str(qid))
85+
link = problems_url + question['stat']['question__title_slug']
86+
git_link = '/lcci/{}/README.md'.format(quote(fe_qid + '. ' + cn_title))
87+
col1 = '[{}]({})'.format(qno, link)
88+
col2 = '[{}]({})'.format(cn_title, git_link)
89+
col3 = difficulties.get(str(question['difficulty']['level']))
90+
yield [col1, col2, col3]
91+
92+
93+
def generate_md_table_for_questions(res):
94+
"""生成markdown形式的表格"""
95+
print("""
96+
| 题号 | 题解 | 难度 |
97+
| --- | --- | --- |""")
98+
for item in sorted(res, key=lambda x: x[0]):
99+
print("| {} | {} | {} |".format(item[0], item[1], item[2]))
100+
101+
print('-------------------------')
102+
103+
104+
if __name__ == '__main__':
105+
generate_md_table_for_questions(get_all_questions())
106+
generate_md_table_for_questions(get_lcof_questions())
107+
generate_md_table_for_questions(get_lcci_questions())

‎solution/requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
retrying

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /