66import requests
77
88
9- def generate_number_mapper () -> dict :
10- numbers = [i for i in range (100 )]
11- number_mapper = dict ()
12- for number in numbers :
13- start = number * 100
14- end = start + 99
15- subdir = str (start ).zfill (4 ) + '-' + str (end ).zfill (4 )
16- number_mapper [str (number )] = subdir
17- return number_mapper
18-
19-
20- def generate_difficulty_mapper () -> dict :
21- return {
22- 'Easy' : '简单' ,
23- 'Medium' : '中等' ,
24- 'Hard' : '困难'
25- }
26-
27-
28- def generate_difficulty_level_mapper () -> dict :
29- return {
30- '1' : '简单' ,
31- '2' : '中等' ,
32- '3' : '困难'
33- }
34-
35-
36- def generate_difficulty_level_mapper_en () -> dict :
37- return {
38- '1' : 'Easy' ,
39- '2' : 'Medium' ,
40- '3' : 'Hard'
41- }
42-
43-
449class LCSpider :
4510 graph_url = 'https://leetcode-cn.com/graphql'
4611 user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' \
@@ -50,18 +15,16 @@ def __init__(self):
5015 self .session = requests .session ()
5116
5217 # mapper
53- self .number_mapper = generate_number_mapper ()
54- self .difficulty_mapper = generate_difficulty_mapper ()
55- self .difficulty_level_mapper = generate_difficulty_level_mapper ()
56- self .difficulty_level_mapper_en = generate_difficulty_level_mapper_en ()
18+ self .number_mapper = [str (i * 100 ).zfill (4 ) + '-' + str (i * 100 + 99 ).zfill (4 ) for i in range (100 )]
19+ self .difficulty_mapper = dict (Easy = '简单' , Medium = '中等' , Hard = '困难' )
5720
5821 # result
5922 self .result = []
6023 self .md_table_cn = []
6124 self .md_table_en = []
6225
6326 def get_question_detail (self , question_title_slug ):
64- """获取题目详情 """
27+ """fetch question detail by leetcode's api """
6528 form_data = {
6629 'operationName' : 'globalData' ,
6730 'query' : 'query globalData {\n feature {\n questionTranslation\n subscription\n signUp\n '
@@ -83,7 +46,8 @@ def get_question_detail(self, question_title_slug):
8346 'User-Agent' : LCSpider .user_agent ,
8447 'Connection' : 'keep-alive' ,
8548 'Content-Type' : 'application/json' ,
86- 'Referer' : 'https://leetcode-cn.com/problems/' + question_title_slug }
49+ 'Referer' : 'https://leetcode-cn.com/problems/' + question_title_slug
50+ }
8751 self .session .post (LCSpider .graph_url , data = json .dumps (form_data ), headers = headers , timeout = 10 )
8852
8953 form_data = {
@@ -106,14 +70,14 @@ def get_question_detail(self, question_title_slug):
10670 __typename\n }\n }\n """
10771 }
10872
109- # 获取题目详情
73+ # get question detail
11074 resp = self .session .post (url = LCSpider .graph_url , data = json .dumps (form_data ).encode ('utf-8' ), headers = headers ,
11175 timeout = 10 )
11276 res = resp .json ()
11377 return res ['data' ]['question' ]
11478
11579 def get_all_questions (self ):
116- """获取所有题目 """
80+ """fetch all question by leetcode's api """
11781 headers = {
11882 'accept' : 'application/json, text/javascript, */*; q=0.01' ,
11983 'content-type' : 'application/json' ,
@@ -137,9 +101,9 @@ def get_all_questions(self):
137101 url_cn = 'https://leetcode-cn.com/problems/' + question_title_slug
138102 url_en = 'https://leetcode.com/problems/' + question_title_slug
139103
140- path_cn = '/solution/{}/{}.{}/README.md' .format (self .number_mapper . get ( str ( no )) , frontend_question_id ,
104+ path_cn = '/solution/{}/{}.{}/README.md' .format (self .number_mapper [ no ] , frontend_question_id ,
141105 quote (question_title_en ))
142- path_en = '/solution/{}/{}.{}/README_EN.md' .format (self .number_mapper . get ( str ( no )) , frontend_question_id ,
106+ path_en = '/solution/{}/{}.{}/README_EN.md' .format (self .number_mapper [ no ] , frontend_question_id ,
143107 quote (question_title_en ))
144108 print (frontend_question_id )
145109 item = {
@@ -199,37 +163,41 @@ def save_result(self):
199163 with open ('result.json' , 'a' , encoding = 'utf-8' ) as f :
200164 f .write (json .dumps (self .result ))
201165
202- def generate_md_table (self ):
203- """生成md题目列表"""
204- print ("""
205- | 题号 | 题解 | 标签 | 难度 | 备注 |
206- | --- | --- | --- | --- | --- |""" )
166+ def generate_readme (self ):
167+ """generate README.md and README_EN.md files"""
168+ items = []
169+ table_cn = "\n | 题号 | 题解 | 标签 | 难度 | 备注 |\n | --- | --- | --- | --- | --- |"
207170 for item in sorted (self .md_table_cn , key = lambda x : x [0 ]):
208- print ("| {} | {} | {} | {} | {} |" .format (item [0 ], item [1 ], item [2 ], item [3 ], item [4 ]))
171+ items .append ("\n | {} | {} | {} | {} | {} |" .format (item [0 ], item [1 ], item [2 ], item [3 ], item [4 ]))
172+ table_cn += "" .join (items )
209173
210- print ('-------------------------' )
174+ with open ('./readme_template.md' , 'r' , encoding = 'utf-8' ) as f :
175+ readme_cn = f .read ()
176+ with open ('./README.md' , 'w' , encoding = 'utf-8' ) as f :
177+ f .write (readme_cn .format (table_cn ))
211178
212- print ("""
213- | # | Solution | Tags | Difficulty | Remark |
214- | --- | --- | --- | --- | --- |""" )
179+ items = []
180+ table_en = "\n | # | Solution | Tags | Difficulty | Remark |\n | --- | --- | --- | --- | --- |"
215181 for item in sorted (self .md_table_en , key = lambda x : x [0 ]):
216- print ("| {} | {} | {} | {} | {} |" .format (item [0 ], item [1 ], item [2 ], item [3 ], item [4 ]))
217-
218- print ('-------------------------' )
182+ items .append ("\n | {} | {} | {} | {} | {} |" .format (item [0 ], item [1 ], item [2 ], item [3 ], item [4 ]))
183+ table_en += "" .join (items )
184+ with open ('./readme_template_en.md' , 'r' , encoding = 'utf-8' ) as f :
185+ readme_en = f .read ()
186+ with open ('./README_EN.md' , 'w' , encoding = 'utf-8' ) as f :
187+ f .write (readme_en .format (table_en ))
219188
220189 def generate_question_readme (self ):
221- with open ('./README_TEMPLATE .md' , 'r' , encoding = 'utf-8' ) as f :
190+ with open ('./problem_readme_template .md' , 'r' , encoding = 'utf-8' ) as f :
222191 readme_cn = f .read ()
223- with open ('./README_TEMPLATE_EN .md' , 'r' , encoding = 'utf-8' ) as f :
192+ with open ('./problem_readme_template_en .md' , 'r' , encoding = 'utf-8' ) as f :
224193 readme_en = f .read ()
225194
226195 with open ('./result.json' , 'r' , encoding = 'utf-8' ) as f :
227196 result = f .read ()
228197 result = json .loads (result )
229198 for item in result :
230199 no = int (item ['frontend_question_id' ]) // 100
231-
232- path = f'./{ self .number_mapper .get (str (no ))} /{ item ["frontend_question_id" ]} .{ item ["title_en" ]} '
200+ path = f'./{ self .number_mapper [no ]} /{ item ["frontend_question_id" ]} .{ item ["title_en" ]} '
233201 path = path .replace (":" , " " )
234202
235203 if os .path .isdir (path ):
@@ -254,12 +222,21 @@ def generate_question_readme(self):
254222
255223 @staticmethod
256224 def generate_summary ():
225+ summary_cn = ""
226+ summary_en = ""
257227 for file in os .listdir ("./" ):
258228 if os .path .isdir ("./" + file ) and file != '__pycache__' :
259- print ("\n - " + file + "\n " )
229+ summary_cn += ("\n - " + file + "\n " )
230+ summary_en += ("\n - " + file + "\n " )
260231 for sub in os .listdir ("./" + file ):
261232 enc = quote (sub )
262- print (f'\t - [{ sub } ](/solution/{ file } /{ enc } /README.md)' )
233+ summary_cn += f'\t - [{ sub } ](/solution/{ file } /{ enc } /README.md)\n '
234+ summary_en += f'\t - [{ sub } ](/solution/{ file } /{ enc } /README_EN.md)\n '
235+
236+ with open ('./summary.md' , 'w' , encoding = 'utf-8' ) as f :
237+ f .write (summary_cn )
238+ with open ('./summary_en.md' , 'w' , encoding = 'utf-8' ) as f :
239+ f .write (summary_en )
263240
264241
265242if __name__ == '__main__' :
@@ -268,6 +245,6 @@ def generate_summary():
268245 spider .get_all_questions ()
269246 spider .save_result ()
270247
271- spider .generate_md_table ()
248+ spider .generate_readme ()
272249 spider .generate_question_readme ()
273250 spider .generate_summary ()
0 commit comments