5
5
6
6
import requests
7
7
8
- new_content = """# [{}. {}]({})
9
-
10
- [English Version]({})
11
-
12
- ## 题目描述
13
-
14
- <!-- 这里写题目描述 -->
15
-
16
- {}
17
-
18
- """
19
-
20
- new_content_en = """# [{}. {}]({})
21
-
22
- [中文文档]({})
23
-
24
- ## Description
25
-
26
- {}
27
-
28
- """
29
-
30
8
31
9
class LCSpider :
32
10
graph_url = 'https://leetcode-cn.com/graphql'
@@ -66,7 +44,7 @@ def get_question_detail(self, question_title_slug):
66
44
'Connection' : 'keep-alive' ,
67
45
'Content-Type' : 'application/json' ,
68
46
'Referer' : 'https://leetcode-cn.com/problems/' + question_title_slug ,
69
- # leetcode -cn.com cookie here
47
+ # lc -cn cookie here
70
48
# 'cookie': ''
71
49
}
72
50
self .session .post (url = LCSpider .graph_url ,
@@ -79,7 +57,21 @@ def get_question_detail(self, question_title_slug):
79
57
'variables' : {
80
58
'titleSlug' : question_title_slug
81
59
},
82
- 'query' : """query questionData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n categoryTitle\n boundTopicId\n title\n titleSlug\n content\n translatedTitle\n translatedContent\n isPaidOnly\n difficulty\n likes\n dislikes\n isLiked\n similarQuestions\n contributors {\n username\n profileUrl\n avatarUrl\n __typename\n }\n langToValidPlayground\n topicTags {\n name\n slug\n translatedName\n __typename\n }\n companyTagStats\n codeSnippets {\n lang\n langSlug\n code\n __typename\n }\n stats\n hints\n solution {\n id\n canSeeDetail\n __typename\n }\n status\n sampleTestCase\n metaData\n judgerAvailable\n judgeType\n mysqlSchemas\n enableRunCode\n envInfo\n book {\n id\n bookName\n pressName\n source\n shortDescription\n fullDescription\n bookImgUrl\n pressImgUrl\n productUrl\n __typename\n }\n isSubscribed\n isDailyQuestion\n dailyRecordStatus\n editorType\n ugcQuestionId\n style\n exampleTestcases\n __typename\n }\n }\n """
60
+ 'query' : 'query questionData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n '
61
+ 'questionId\n questionFrontendId\n categoryTitle\n boundTopicId\n title\n '
62
+ 'titleSlug\n content\n translatedTitle\n translatedContent\n isPaidOnly\n '
63
+ 'difficulty\n likes\n dislikes\n isLiked\n similarQuestions\n '
64
+ 'contributors {\n username\n profileUrl\n avatarUrl\n __typename\n '
65
+ '}\n langToValidPlayground\n topicTags {\n name\n slug\n '
66
+ 'translatedName\n __typename\n }\n companyTagStats\n codeSnippets {\n '
67
+ 'lang\n langSlug\n code\n __typename\n }\n stats\n hints\n '
68
+ 'solution {\n id\n canSeeDetail\n __typename\n }\n status\n '
69
+ 'sampleTestCase\n metaData\n judgerAvailable\n judgeType\n mysqlSchemas\n '
70
+ 'enableRunCode\n envInfo\n book {\n id\n bookName\n pressName\n '
71
+ 'source\n shortDescription\n fullDescription\n bookImgUrl\n '
72
+ 'pressImgUrl\n productUrl\n __typename\n }\n isSubscribed\n '
73
+ 'isDailyQuestion\n dailyRecordStatus\n editorType\n ugcQuestionId\n style\n '
74
+ 'exampleTestcases\n __typename\n }\n }\n '
83
75
}
84
76
85
77
# get question detail
@@ -97,7 +89,7 @@ def get_all_questions(self):
97
89
'content-type' : 'application/json' ,
98
90
'user-agent' : LCSpider .user_agent ,
99
91
'x-requested-with' : 'XMLHttpRequest' ,
100
- # leetcode.com cookie here
92
+ # lc cookie here
101
93
# 'cookie': ''
102
94
}
103
95
resp = self .session .get (url = 'https://leetcode.com/api/problems/all/' ,
@@ -127,7 +119,7 @@ def get_all_questions(self):
127
119
128
120
print (f'{ frontend_question_id } . { question_title_en } ' )
129
121
topic_tags = question_detail .get ('topicTags' )
130
-
122
+
131
123
item = {
132
124
'question_id' : str (question ['stat' ]['question_id' ]).zfill (4 ),
133
125
'frontend_question_id' : frontend_question_id ,
@@ -186,10 +178,10 @@ def generate_readme():
186
178
187
179
# generate README.md
188
180
items = []
189
- table_cn = " \n | 题号 | 题解 | 标签 | 难度 | 备注 |\n | --- | --- | --- | --- | --- |"
181
+ table_cn = ' \n | 题号 | 题解 | 标签 | 难度 | 备注 |\n | --- | --- | --- | --- | --- |'
190
182
for item in sorted (md_table_cn , key = lambda x : x [0 ]):
191
- items .append (" \n | {} | {} | {} | {} | {} |" . format ( item [0 ], item [ 1 ], item [ 2 ], item [ 3 ], item [ 4 ]) )
192
- table_cn += "" .join (items )
183
+ items .append (f' \n | { item [ 0 ] } | { item [ 1 ] } | { item [ 2 ] } | { item [ 3 ] } | { item [4 ] } |' )
184
+ table_cn += '' .join (items )
193
185
194
186
with open ('./readme_template.md' , 'r' , encoding = 'utf-8' ) as f :
195
187
readme_cn = f .read ()
@@ -198,11 +190,11 @@ def generate_readme():
198
190
199
191
# generate README_EN.md
200
192
items = []
201
- table_en = " \n | # | Solution | Tags | Difficulty | Remark |\n | --- | --- | --- | --- | --- |"
193
+ table_en = ' \n | # | Solution | Tags | Difficulty | Remark |\n | --- | --- | --- | --- | --- |'
202
194
for item in sorted (md_table_en , key = lambda x : x [0 ]):
203
- items .append (
204
- " \n | {} | {} | {} | {} | {} |" . format ( item [ 0 ], item [ 1 ], item [ 2 ], item [ 3 ], item [ 4 ]) )
205
- table_en += "" . join ( items )
195
+ items .append (f' \n | { item [ 0 ] } | { item [ 1 ] } | { item [ 2 ] } | { item [ 3 ] } | { item [ 4 ] } |' )
196
+ table_en += '' . join ( items )
197
+
206
198
with open ('./readme_template_en.md' , 'r' , encoding = 'utf-8' ) as f :
207
199
readme_en = f .read ()
208
200
with open ('./README_EN.md' , 'w' , encoding = 'utf-8' ) as f :
@@ -246,32 +238,32 @@ def generate_question_readme(self):
246
238
readme_template_cn = readme_cn
247
239
readme_template_en = readme_en
248
240
249
- # generate lc problem readme cn
241
+ # generate lc-cn problem readme
250
242
with open (f'{ path } /README.md' , 'w' , encoding = 'utf-8' ) as f1 :
251
243
f1 .write (readme_template_cn .format (int (item ['frontend_question_id' ]),
252
- item ["title_cn" ],
253
- item ['url_cn' ],
254
- item ['relative_path_en' ],
255
- item ['content_cn' ]))
244
+ item ["title_cn" ],
245
+ item ['url_cn' ],
246
+ item ['relative_path_en' ],
247
+ item ['content_cn' ]))
256
248
257
- # generate lc problem readme en
249
+ # generate lc-en problem readme
258
250
with open (f'{ path } /README_EN.md' , 'w' , encoding = 'utf-8' ) as f2 :
259
251
f2 .write (readme_template_en .format (int (item ['frontend_question_id' ]),
260
- item ["title_en" ],
261
- item ['url_en' ],
262
- item ['relative_path_cn' ],
263
- item ['content_en' ]))
252
+ item ["title_en" ],
253
+ item ['url_en' ],
254
+ item ['relative_path_cn' ],
255
+ item ['content_en' ]))
264
256
265
257
@staticmethod
266
258
def generate_summary ():
267
259
"""generate summary files"""
268
- summary_cn = ""
269
- summary_en = ""
270
- for file in os .listdir ("./" ):
260
+ summary_cn = ''
261
+ summary_en = ''
262
+ for file in os .listdir ('./' ):
271
263
if os .path .isdir ("./" + file ) and file != '__pycache__' :
272
- summary_cn += ( " \n - " + file + " \n " )
273
- summary_en += ( " \n - " + file + " \n " )
274
- for sub in os .listdir ("./" + file ):
264
+ summary_cn += f' \n - { file } \n '
265
+ summary_en += f' \n - { file } \n '
266
+ for sub in os .listdir ('./' + file ):
275
267
sub = sub .replace ('`' , ' ' )
276
268
enc = quote (sub )
277
269
summary_cn += f' - [{ sub } ](/solution/{ file } /{ enc } /README.md)\n '
@@ -285,96 +277,13 @@ def generate_summary():
285
277
with open ('./summary_en.md' , 'w' , encoding = 'utf-8' ) as f :
286
278
f .write (summary_en )
287
279
288
- @staticmethod
289
- def remove_empty_folders ():
290
- """remove empty sub folders"""
291
- sub_folders = [str (i * 100 ).zfill (4 ) + '-' + str (i * 100 + 99 ).zfill (4 ) for i in range (100 )]
292
-
293
- for item in sub_folders :
294
- if not os .path .isdir (f'./{ item } ' ):
295
- continue
296
- files = os .listdir (f'./{ item } ' )
297
- for f in files :
298
- if os .path .isdir (f'./{ item } /{ f } ' ):
299
- if not os .listdir (f'./{ item } /{ f } ' ):
300
- os .rmdir (f'./{ item } /{ f } ' )
301
-
302
- @staticmethod
303
- def replace_content ():
304
- with open ('./result.json' , 'r' , encoding = 'utf-8' ) as f :
305
- result = f .read ()
306
- result = json .loads (result )
307
- mapper = {item ['frontend_question_id' ]: item for item in result }
308
- sub_folders = [str (i * 100 ).zfill (4 ) + '-' + str (i * 100 + 99 ).zfill (4 ) for i in range (100 )]
309
- for item in sub_folders :
310
- if not os .path .isdir (f'./{ item } ' ):
311
- continue
312
- files = os .listdir (f'./{ item } ' )
313
- for f in files :
314
- if os .path .isdir (f'./{ item } /{ f } ' ):
315
- with open (f'./{ item } /{ f } /README.md' , 'r' , encoding = 'utf-8' ) as f1 :
316
- readme = f1 .read ()
317
- with open (f'./{ item } /{ f } /README_EN.md' , 'r' , encoding = 'utf-8' ) as f2 :
318
- readme_en = f2 .read ()
319
- question = mapper [f [:4 ]]
320
- b = new_content .format (int (question ['frontend_question_id' ]),
321
- question ["title_cn" ],
322
- question ['url_cn' ],
323
- question ['relative_path_en' ],
324
- question ['content_cn' ])
325
- index_cn = readme .index ("## 解法" )
326
- a = b + readme [index_cn :]
327
- with open (f'./{ item } /{ f } /README.md' , 'w' , encoding = 'utf-8' ) as f1 :
328
- f1 .write (a )
329
- index_en = readme_en .index ("## Solutions" )
330
- b = new_content_en .format (int (question ['frontend_question_id' ]),
331
- question ["title_en" ],
332
- question ['url_en' ],
333
- question ['relative_path_cn' ],
334
- question ['content_en' ])
335
- a = b + readme_en [index_en :]
336
- with open (f'./{ item } /{ f } /README_EN.md' , 'w' , encoding = 'utf-8' ) as f2 :
337
- f2 .write (a )
338
-
339
- @staticmethod
340
- def download_image ():
341
- sub_folders = [str (i * 100 ).zfill (4 ) + '-' + str (i * 100 + 99 ).zfill (4 ) for i in range (100 )]
342
- for item in sub_folders :
343
- if not os .path .isdir (f'./{ item } ' ):
344
- continue
345
- files = os .listdir (f'./{ item } ' )
346
- for f in files :
347
- if os .path .isdir (f'./{ item } /{ f } ' ):
348
- with open (f'./{ item } /{ f } /README.md' , 'r' , encoding = 'utf-8' ) as f1 :
349
- readme = f1 .read ()
350
- with open (f'./{ item } /{ f } /README_EN.md' , 'r' , encoding = 'utf-8' ) as f2 :
351
- readme_en = f2 .read ()
352
-
353
- res_cn = re .findall (r'src="(.*?)"' , readme , re .S ) or []
354
- for url in res_cn :
355
- file_name = os .path .basename (url )
356
- new_url = f'https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/{ item } /{ quote (f )} /images/{ file_name } '
357
- readme = readme .replace (url , new_url )
358
- with open (f'./{ item } /{ f } /README.md' , 'w' , encoding = 'utf-8' ) as f1 :
359
- f1 .write (readme )
360
-
361
- res_en = re .findall (r'src="(.*?)"' , readme_en , re .S ) or []
362
- for url in res_en :
363
- file_name = os .path .basename (url )
364
- new_url = f'https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/{ item } /{ quote (f )} /images/{ file_name } '
365
- readme_en = readme_en .replace (url , new_url )
366
- with open (f'./{ item } /{ f } /README_EN.md' , 'w' , encoding = 'utf-8' ) as f1 :
367
- f1 .write (readme_en )
368
-
369
280
370
281
if __name__ == '__main__' :
371
282
spider = LCSpider ()
372
283
373
284
spider .get_all_questions ()
374
285
spider .save_result ()
375
-
286
+
376
287
spider .generate_readme ()
377
288
spider .generate_question_readme ()
378
289
spider .generate_summary ()
379
- # spider.replace_content()
380
- # spider.download_image()
0 commit comments