|
|
|
@ -1,33 +1,123 @@
|
|
|
|
|
import asyncio
|
|
|
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
|
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'])
|
|
|
|
|
|
|
|
|
|
class Tree: # 任务树
|
|
|
|
|
def __init__(self, task):
|
|
|
|
|
self.task = task
|
|
|
|
|
self.child = []
|
|
|
|
|
return int(100 * score / total), time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def ainput(prompt: str = ''):
|
|
|
|
|
with ThreadPoolExecutor(1, 'ainput') as executor:
|
|
|
|
|
return (
|
|
|
|
|
await asyncio.get_event_loop().run_in_executor(executor, input, prompt)
|
|
|
|
|
).rstrip()
|
|
|
|
|
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']
|
|
|
|
|
|
|
|
|
|
async def flash_recent(): # 对当前书籍执行刷课
|
|
|
|
|
if configs['browser']['mode'] == 'launch':
|
|
|
|
|
browser = Browser.launch()
|
|
|
|
|
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:
|
|
|
|
|
browser = Browser.connect()
|
|
|
|
|
page = await browser.wait_for_book()
|
|
|
|
|
params = dict(parser.parse_qsl(parser.urlsplit(page.url).query))
|
|
|
|
|
# noinspection PyTypeChecker
|
|
|
|
|
book_id, course_id = params['bookId'], params['courseId']
|
|
|
|
|
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)
|
|
|
|
|