import json import urllib.parse as parser from random import uniform, randint from bs4 import BeautifulSoup from loguru import logger from configs import configs from .devtools import Browser from .spider import Spider PLACEHOLDER = '. ' _paper_config = configs['paper'] async def list_books(detail): async with Spider() as spider: await spider.login(**configs['user']) courses = await spider.get_courses() for cr in courses: if detail: hint = f'{cr["courseName"]} ({cr["teacherName"]})' else: hint = cr['courseName'] print(hint) books = await spider.get_books(cr["courseId"]) for book in books: if detail: hint = f'> [{cr["courseId"]}#{book["bookId"]}] {book["bookName"]} ({book["percent"]}%)' else: hint = f'> {book["bookName"]}' print(PLACEHOLDER + hint) async def _random(spider, paper_id): # 随机的分数和学习时长 paper = BeautifulSoup((await spider.get_paper(paper_id))['paperData'], 'lxml-xml') questions = paper.select('element[knowledge]:has(> question_type)') if not questions: return 100, 5 total = 0 score, time = 0, 0 for q in questions: q_type = int(q.select_one('question_type').text) q_score = float(q.select_one('question_score').text) total += q_score ranges = _paper_config['random-score'] if q_type <= len(ranges) and (r := ranges[q_type-1]) is not None: if not isinstance(ranges[q_type-1], list): r = [r, r] score += q_score * uniform(*r) else: q_no = q.select_one('question_no').text logger.warning(f'T{q_no}:未知的题型!') if (r := _paper_config['defaults']) == 'pause': score += float(input('请手动输入该题得分 [0-1]:')) else: # defaults score += q_score * uniform(*r) time += randint(*_paper_config['random-time']) return int(100 * score / total), time async def _flash(course_id, book_id, spider): async def dfs(node, depth=0): task = node.task print(PLACEHOLDER * depth + task['name']) if _paper_config['skip-finished'] and task['unitStudyPercent'] == 100: print(PLACEHOLDER * depth + '# Skipped') return if 'paperId' in task: # 如果有任务则提交 chapter_id = task['chapterId'] task_id = task['id'] score, time = await _random(spider, task['paperId']) result = await page.submit(book_id, chapter_id, task_id, score, time, 100, user_id) if result['wasThrown'] or not result['result']['value']: logger.warning(f'任务 {task["name"]} 可能提交失败,请留意最终结果!') for ch in node.child: await dfs(ch, depth + 1) browser = await Browser.connect() page = await browser.wait_for_page(r'https?://pc\.ismartin\.com.*') # With Spider await spider.login(**configs['user']) user_id = (await spider.user_info())['data']['uid'] book_type = (await spider.book_info(book_id))['bookType'] root = await spider.get_tasks(book_id, book_type, course_id) await dfs(root) async def flash_by_id(identity): async with Spider() as spider: await _flash(*identity.split('#'), spider) async def flash_current(): # 对当前课程或书籍执行刷课 browser = await Browser.connect() course_id, book_id = await browser.get_current() async with Spider() as spider: if book_id: await _flash(course_id, book_id, spider) else: await spider.login(**configs['user']) books = await spider.get_books(course_id) for book in books: await _flash(course_id, book['bookId'], spider) async def flash_all(): async with Spider() as spider: await spider.login(**configs['user']) courses = await spider.get_courses() for course in courses: course_id = course['courseId'] books = await spider.get_books(course_id) for book in books: await _flash(course_id, book['bookId'], spider)