Last active
August 11, 2022 05:21
-
-
Save ImSingee/5a852b8358d2e99ca9a45b38427b7856 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/opt/bin/python3 | |
# pip install markdownify | |
import os | |
import requests | |
import markdownify | |
question_id = os.environ.get('KMVAR_LeetCodeID', 'add-two-numbers') | |
session = '' | |
cookies={ | |
"LEETCODE_SESSION": session | |
} | |
def get_csrf_cookie() -> str: | |
response = requests.get( | |
"https://leetcode.com/", | |
cookies=cookies, | |
) | |
return response.cookies["csrftoken"] | |
HEADERS = { | |
'x-csrftoken': get_csrf_cookie(), | |
} | |
def find_until(lines, prefix) -> int: | |
for i, line in enumerate(lines): | |
if line.startswith(prefix): | |
return i | |
return len(lines) | |
def format_lines(lines): | |
result = [] | |
while len(lines) != 0: | |
line = lines[0] | |
if line.strip() == "": | |
lines = lines[1:] | |
continue | |
if line.startswith('<p><strong>') and line.endswith('</strong></p>'): | |
result.append('- ' + markdownify.markdownify(line).strip()) | |
inner_line_count = find_until(lines[1:], '<p><strong>') | |
inner_result = format_lines(lines[1:1+inner_line_count]) | |
for r in inner_result: | |
result.append('\t' + r) | |
lines = lines[1+inner_line_count:] | |
continue | |
if line.startswith("<pre>"): | |
#result.append('- ```') | |
inner_line_count = find_until(lines[1:], '</pre>') | |
for line in lines[1:1+inner_line_count]: | |
result.append('- '+markdownify.markdownify(line)) | |
#result.append('```') | |
lines = lines[2+inner_line_count:] | |
continue | |
if line.startswith("<ul>"): | |
inner_line_count = find_until(lines[1:], '</ul>') | |
for line in lines[1:1+inner_line_count]: | |
result.append(markdownify.markdownify(line).strip()) | |
lines = lines[2+inner_line_count:] | |
continue | |
if line.startswith("<ol>"): | |
inner_line_count = find_until(lines[1:], '</ol>') | |
for line in lines[1:1+inner_line_count]: | |
result.append(markdownify.markdownify(line).strip()) | |
lines = lines[2+inner_line_count:] | |
continue | |
if line.startswith('<p>') and line.endswith('</p>'): | |
result.append('- ' + markdownify.markdownify(line).strip()) | |
lines = lines[1:] | |
continue | |
if line.startswith('<img ') and line.endswith(' />'): | |
result.append('- ' + markdownify.markdownify(line).strip()) | |
lines = lines[1:] | |
continue | |
result.append(lines[0]) | |
lines = lines[1:] | |
return result | |
def html_to_markdown(html): | |
return '\n'.join(format_lines(html.replace('\xa0', ' ').strip().split('\n'))) | |
def get_leetcode_question_detail(title_slug: str): | |
query = '''query questionData($titleSlug: String!) { | |
question(titleSlug: $titleSlug) { | |
questionId | |
questionFrontendId | |
categoryTitle | |
boundTopicId | |
title | |
titleSlug | |
content | |
translatedTitle | |
translatedContent | |
isPaidOnly | |
difficulty | |
similarQuestions | |
langToValidPlayground | |
companyTagStats | |
codeSnippets { | |
lang | |
langSlug | |
code | |
__typename | |
} | |
topicTags { | |
name | |
slug | |
translatedName | |
__typename | |
} | |
stats | |
hints | |
status | |
sampleTestCase | |
metaData | |
judgerAvailable | |
judgeType | |
mysqlSchemas | |
enableRunCode | |
isDailyQuestion | |
dailyRecordStatus | |
editorType | |
ugcQuestionId | |
style | |
exampleTestcases | |
__typename | |
} | |
} | |
''' | |
request_body = { | |
'operationName': "questionData", | |
'query': query, | |
'variables': { | |
'titleSlug': title_slug, | |
} | |
} | |
response = requests.post('https://leetcode-cn.com/graphql/', headers=HEADERS, cookies=cookies, json=request_body) | |
detail = response.json()['data']['question'] | |
# detail['topicTagsLogseq'] = ''.join([' #[['+x['name']+']]' for x in detail['topicTags']]) | |
# detail['contentMarkdown'] = markdownify.markdownify(detail['content']) | |
# detail['translatedContentMarkdown'] = markdownify.markdownify(detail['translatedContent']) | |
# detail['translatedContentMarkdownLogseq'] = '\n'.join(['\t'+ x for x in html_to_markdown(detail['translatedContent']).split('\n')]) | |
return detail | |
def get_lintcode_question_detail(title_slug: str): | |
response = requests.get('https://www.lintcode.com/problem/{}/'.format(title_slug), allow_redirects=False) | |
if response.status_code != 301: | |
raise RuntimeError('invalid response: status_code = {}'.format(response.status_code)) | |
location = response.headers['location'] | |
if location == 'https://www.lintcode.com/problem/': | |
return None | |
return { | |
'questionId': int(location.split('/')[-2]), | |
} | |
def get_question_detail(title_slug: str): | |
leetcode_detail = get_leetcode_question_detail(title_slug) | |
lintcode_detail = get_lintcode_question_detail(title_slug) | |
detail = { | |
'titleSlug': title_slug, | |
'leetcode': leetcode_detail, | |
'lintcode': lintcode_detail, | |
} | |
detail['title'] = leetcode_detail['title'] | |
detail['chinese-title'] = leetcode_detail['translatedTitle'] | |
detail['difficulty'] = leetcode_detail['difficulty'] | |
detail['content'] = '\n'.join(['\t'+ x for x in html_to_markdown(leetcode_detail['translatedContent']).split('\n')]) | |
tags = {x['translatedName'] for x in leetcode_detail['topicTags']} | |
detail['tags'] = ' '.join(['#[[' + x + ']]' for x in tags]) | |
detail['leetcodeQuestionId'] = leetcode_detail['questionFrontendId'] | |
detail['leetcodeLine'] = '#Leetcode #Leetcode-{leetcodeQuestionId} [LC国际](https://leetcode.com/problems/{titleSlug}/) [LC中国](https://leetcode.cn/problems/{titleSlug}/)'.format(**detail) | |
detail['ojLine'] = '- ' + detail['leetcodeLine'] | |
if lintcode_detail is not None: | |
detail['lintcodeQuestionId'] = lintcode_detail['questionId'] | |
detail['lintcodeLine'] = '#lintcode #Lintcode-{lintcodeQuestionId} [LintCode](https://www.lintcode.com/problem/{lintcodeQuestionId}/)'.format(**detail) | |
detail['ojLine'] += '\n- ' + detail['lintcodeLine'] | |
return detail | |
detail = get_question_detail(question_id) | |
template = ''' | |
- alias:: {title} | |
- #Algorithm #{difficulty} {tags} | |
{ojLine} | |
- # 题目 | |
{content} | |
''' | |
print(template.format(**detail).strip()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment