You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)