Code Monkey home page Code Monkey logo

cxkitty's Introduction

超星学习通答题姬

CxKitty

Github Stars Github Forks Github License Code style: black Image Size

本项目旨在研究学习爬虫技术和网络接口编程技术,同时致力于以开源方式抵制并消灭各种付费“刷课平台”和“黑产”

Ps: 本项目不提供任何题库资源,有相关测试需求者请按照文档自行解决。本项目仅供学习参考使用,请在下载部署后 24 小时内删除,由于使用本项目不当所造成的挂科或不良学习记录作者一概不负责。

✨Features

Supports

  • 会话管理
    • ✅支持手机号+密码登录、二维码登录,可以自动 / 手动重登账号
    • ✅内置多账号管理器,自动存取账号信息,自动判断会话 ck 有效性,以 json 格式存档在本地
  • 交互
    • ✅以 Terminal-UI 方式进行人机交互,展示工作流程、章节任务点状态,输出详细信息到 log 文件,作为一个理工男,不觉得很酷吗?
    • ✅批量选择课程(使用序号 / courseId / 课程名)
  • 协议实现
    • ✅使用 requestsbs4 分别进行协议模拟和 HTML 解析,故无需浏览器,更无需油猴脚本
    • ✅无惧接口风控,基于 OpenCVddddocr 对验证码进行识别,进而解除接口风控状态
    • ✅接口请求 retry 支持,针对网络环境不佳以及使用移动流量的场景优化
    • ✅人脸识别弹窗自动上传提交,支持课程进入、任务点进入、考试进入三种类型,可使用预先上传的人脸图片,也可自定义图片上传提交
  • 任务点
    • ✅视频课程任务点模拟播放(无需消耗流量播放流媒体内容)
    • ✅文档任务点模拟浏览(如 word ppt pdf 等)
  • 考试及测验
    • ✅章节测验任务点自动答题,支持单选题、多选题、填空题、判断题,试题未完成可临时保存
    • ✅课程考试(考试模式)自动答题,支持单选题、多选题、填空题、判断题(使用手机客户端接口)
    • ✅可以跳过考试承诺书(不支持自动提交)、可以跳过重考须知
    • ✅自动过滤题干和选项中的空白 Unicode 字符,eg:u+2002、u+200b、u+3000
    • ✅遇到匹配失败的题,可使用 fuzzer 方式填充答案并提交(默认关闭)
    • ✅章节测验试题 / 课程考试可完整导出,信息全、无加密无乱码,可导出临时保存的答案,现支持 json 格式
    • ✅自动答题功能需要至少一种的 题库后端 支持,现支持REST APIJSONSQLite三种类型的 题库后端,同时已适配Enncy网课小工具(Go题)题库海冷月题库Muke题库柠檬题库六种第三方题库,可并行搜索,择优匹配答案(建议使用自建题库)
    • REST API类型 题库后端 (用户接口)支持使用 JsonPath 语法进行答案字段提取,允许用户注入 HTTP header 和 params 依赖字段
    • ✅日志中将记录未完成的题目,并自动导出未完成的题目到 json

TODO

以下特性有可能逐渐被添加

  • ⭕短信验证码登录、学号登录
  • ⭕直播任务点、文章阅读任务点
  • ⭕简答题、论述题等题型支持
  • ⭕富文本答题,匹配选项为图片的情况
  • ⭕使用 Gotify 或 MQTT 上报任务进度以及完成情况
  • ⭕使用 args 直接传参登录账号以及选课
  • ⭕导出已批阅的章节测验
  • ⭕试题自动等待交卷

❤️Contributing Guide

若发现程序存在任何 bug 或有好的想法,欢迎提交 Issue,提交 bug 反馈时需要带上报错信息截图(截全)以及对应 log 文件,并说明触发条件

如果有能力一同开发项目,欢迎使用 PR 提交代码(注意合并 Origin 和修改内容

提交 Issue 时应当遵守 提问的智慧 以及别像弱智一样提问,切勿以不懂萌新问个问题小白啥也不会浇浇整个xxx呗作为标题,否则一律忽略

Issue 为本项目的唯一反馈渠道,任何包括不限于在 QQ、B站私信、Telegram、微信 的提问一律忽略

🧩Typographical

🚀Build

💻本地化构建项目

使用 Python 版本 >= 3.10.0

clone 项目到本地,并使用 poetry 安装依赖和管理 venv

git clone 'https://github.com/SocialSisterYi/CxKitty'
cd CxKitty
poetry install

运行主程序

poetry run python3 main.py

🐋使用 Docker 构建项目

从 DockerHub 拉取最新镜像

docker pull socialsisteryi/cx-kitty

或手动构建镜像

展开

clone 项目到本地,并开始构建镜像

git clone 'https://github.com/SocialSisterYi/CxKitty'
cd CxKitty
docker build --tag socialsisteryi/cx-kitty .

运行容器

请按实际情况映射以下容器内路径:

/app/session会话存档目录

/app/logs程序日志目录

/app/export试题导出目录 (根据配置文件修改,如不需要可不映射)

/app/faces人脸上传目录 (根据配置文件修改,如不需要可不映射)

/app/config.yml程序配置文件

/app/questions.jsonjson题库 (根据配置文件修改,如不需要可不映射)

/app/questions.dbsqlite题库 (根据配置文件修改,如不需要可不映射)

由于程序使用 TUI,Docker 的日志服务会自动捕获并保存容器的 stdo,所以建议使用参数--log-opt max-size=xx限制容器的日志大小,以免造成过多的磁盘占用

docker run -it \
  --name cx_kitty \
  -v "$PWD/session:/app/session"  \
  -v "$PWD/export:/app/export" \
  -v "$PWD/logs:/app/logs" \
  -v "$PWD/faces:/app/faces" \
  -v "$PWD/config.yml:/app/config.yml" \
  #-v "$PWD/questions.json:/app/questions.json" \
  #-v "$PWD/questions.db:/app/questions.db" \
  --log-opt max-size=10m \
  socialsisteryi/cx-kitty

▶️可执行文件构建 (Windows/Linux/MacOS) (不建议使用)

Action中获取最新的自动构建文件,解压后执行文件

详细步骤

点击Action

右侧点击绿色的 最上面的名为Package Executable

跳转后拖到最底下

选择你自己的系统,点一下就会下载

解压出来后,先配置配置文件,然后执行文件就可以正常启动了

🔨Configuration

主程序配置

配置文件使用 Yaml 语法编写,存放于 config.yml

请根据注释修改配置内容

人脸识别配置

人脸识别图片要求必须 .jpg 格式,存放于face_image_path配置的路径下,默认为faces/

fetch_uploaded_face字段为true,在登录成功后立即尝试拉取该用户预先上传的人脸图片,成功后以用户 puid 命名(eg:114514.jpg),存放于face_image_path配置的路径下,以备需要识别时读取

人脸识别图片还可以自定义,要求图片文件名以 puid 命名,存放于face_image_path配置的路径下,但需要注意将fetch_uploaded_face设置为false,否则登录成功后会被覆盖

也可以为每个自定义一组多张人脸图片,图片以 puid+序号 命名(eg:114514_1.jpg114514_2.jpg),程序中使用正则/\d+(_d+)?\.jpg/遍历筛选,需要识别人脸时会从这组图片中随机抽取一张并上传

题库配置

单选题问题与答案应当一一对应,多选题使用#;分隔每个选项,判断题答案只能为正确错误×

REST API 搜题接口配置,确保接口searcher->restApiSearcher->url可以正确访问访问(若使用 Docker 搭建,而题库 API 服务在宿主机运行,应使用宿主机虚拟网关 IP 地址而不是本地回环地址)

返回值必须为 JSON 格式,使用rsp_field字段作为选择器传入,使用 JsonPath 语法编写,如$.data$.data.answer[*]

eg:

curl 'http://127.0.0.1:88/v1/cx' \
  --data-urlencode 'question=国字的演变的过程告诉我们,国防就是国家的防务,国防与()是密不可分的'  #  这里`question`为请求字段名
{
    "code": 1,
    "question": "国字的演变的过程告诉我们,国防就是国家的防务,国防与()是密不可分的",
    "data": "国家",  // 这里的`data`为响应字段名
    "hit": true
}

JSON 题库,确保searcher->jsonFileSearcher->file_path可以访问(使用 Docker 需要设置映射),key 为题目,value 为与之对应的答案

eg:

{
  "国字的演变的过程告诉我们,国防就是国家的防务,国防与()是密不可分的": "国家"
}

SQLite 题库,确保searcher->sqliteSearcher->file_path可以访问(使用 Docker 需要设置映射),表中应存在配置的请求和响应字段

eg:

SELECT answer FROM questions WHERE question = '国字的演变的过程告诉我们,国防就是国家的防务,国防与()是密不可分的';
国家

Enncy 题库,使用前请注册并获取 Token 填写在配置文件中(第三方题库)

通过此 链接 获取 Token

网课小工具(Go题)题库,使用前请注册并获取 Token 填写在配置文件中(第三方题库)

获取 Token 方式见 文档

题库海 题库,使用前请注册并获取 Token 填写在配置文件中(第三方题库)

通过此 链接 获取 Token

柠檬题库,使用前请注册并获取 Token 填写在配置文件中(第三方题库)

通过此 链接 获取 Token

📖Usage & Demo

注:本项目并非小白向“开箱即用”类型,需要一定的计算机专业技术能力;如需使用自动答题功能,请确保您拥有准确无误的题库资源

修改正确的配置文件,并提供配置中定义的资源,运行主程序,进行选择会话存档,若少于一个会话存档,则直接进入登录界面

登录界面输入手机号后按回车键输入密码,再按回车键进行登录

登录界面直接按下回车键则会显示二维码,使用学习通手机客户端扫描登录

按照提示选择目标课程,多个课程之间使用,分隔,使用课程选择器语法,如下:

  • 课程序号:012
  • 课程序号范围:0-35-10
  • 课程名:"解析几何""马克思主义"(非重复项可省略后半部分)
  • 课程 courseId:#23026xxx#22928xx

程序会自动完成视频及测验任务点,并展示章节任务点情况

如需要完成课程0、课程1-3、课程解析几何则输入:0,1-3,"解析几何"

如需进入考试模式,那么需要在指定课程(使用课程选择器语法)前输入EXAM|,即可进入二级菜单,如:

EXAM|0EXAM|"解析几何"

若配置文件的exam->confirm_submittrue那么在交卷前会提示确认,否则将自动交卷

如需导出题库到 export 路径,需在考试选择界面输入e+序号

💡About Repo Name

项目的中文名超星学习通答题姬早已确定,英文名想到过CxHimeCxExamHimeCxCourseHime然而都非常拗口,故弃用

又想到CxHelper这个名,但helper一词易使人联想到木马病毒可执行程序的文件名,很不吉利

最后由CxKit衍生出CxKitty这个名,一语双关kitty自有“猫娘”含义,同时由于项目首字母缩写是cxk,亦可解释为答题只因

⚠️Disclaimers

  • 本项目以 GPL-3.0 License 作为开源协议,这意味着你需要遵守相应的规则
  • 本项目仅适用于学习研究,任何人不得以此用于盈利
  • 使用本项目造成的任何后果与本人无关

📈Stargazers

Stargazers over time

🔗Link Repos

Samueli924/chaoxing: 超星学习通/超星尔雅/泛雅超星全自动无人值守完成任务点 (github.com)

RainySY/chaoxing-xuexitong-autoflush: 超星学习通全自动无人值守视频刷课程序,使用协议发包来实现。 (github.com)

lyj0309/chaoxing-xuexitong-autoflush: 超星学习通全自动无人值守刷课程序,使用协议发包来实现,无需浏览器,支持自动过测验、过视频。 (github.com)

chettoy/FxxkStar: API and unofficial client for the SuperStar mooc platform | 超星学习通的API和非官方客户端脚本,为学生提供更好的学习体验 (github.com)

ocsjs/ocsjs: OCS 网课助手,网课脚本,帮助大学生解决网课难题 ,目前支持网课:超星学习通,知道智慧树 , 支持脚本猫以及油猴脚本运行。 (github.com)

SocialSisterYi/xuexiaoyi-to-xuexitong-tampermonkey-proxy: 基于“学小易”搜题API的学习通答题/考试油猴脚本题库代理 (github.com)

CodFrm/cxmooc-tools: 一个 超星(学习通)/智慧树(知到)/**大学mooc 学习工具,火狐,谷歌,油猴支持.全自动任务,视频倍速秒过,作业考试题库,验证码自动打码(੧ᐛ੭挂科模式,启动) (github.com)

cxkitty's People

Contributors

esdrin avatar guowang23333 avatar hanbings avatar kituin avatar olixn avatar socialsisteryi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cxkitty's Issues

export()函数不工作

        for task_point in chap[index]:
            try:
                # 开始分类讨论任务点类型
                # 章节测验类型
                if isinstance(task_point, PointWorkDto) and (config.WORK_EN or config.WORK["export"] is True):
                    
                   
                    # 导出作业试题
                    if config.WORK["export"] is True:

                        # 预拉取任务点数据
                        task_point.pre_fetch()
                        # 保存 json 文件
                        task_point.export(config.EXPORTPATH / f"work_{task_point.work_id}.json")

这是main.py的一段代码config.WORK["export"] 为Ture 可是export()怎么都不运行

答题出错 选择器匹配失败

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ D:\尤恩\Desktop\xxt脚本\CxKitty-main\main.py:130 in │
│ │
│ 127 │ │ classes = api.fetch_classes() # 拉取该账号下所学的课程 │
│ 128 │ │ course_seq = dialog.select_class(console, classes) # 进行课程选择 │
│ 129 │ │ for chapter in course_seq: # 迭代返回课程章节 │
│ ❱ 130 │ │ │ fuck_task_worker(chapter) │
│ 131 │ except Exception as err: │
│ 132 │ │ console.print_exception(show_locals=False) │
│ 133 │ │ api.logger.error('-----程序运行异常退出-----', exc_info=True) │
│ │
│ D:\尤恩\Desktop\xxt脚本\CxKitty-main\main.py:83 in fuck_task_worker │
│ │
│ 80 │ │ │ │ # 试题类型 │
│ 81 │ │ │ │ if isinstance(task_point, ChapterExam) and CONF_EN_EXAM: │
│ 82 │ │ │ │ │ task_point.mount_searcher(searcher) │
│ ❱ 83 │ │ │ │ │ task_point.fill_and_commit(lay_main) │
│ 84 │ │ │ │ │ # 开始等待 │
│ 85 │ │ │ │ │ wait_for_class(lay_main, CONF_WAIT_EXAM, f'试题《{task_point.title} │
│ 86 │
│ │
│ D:\尤恩\Desktop\xxt脚本\CxKitty-main\cxapi\jobs\exam.py:259 in fill_and_commit │
│ │
│ 256 │ │ │ │ │ JSON.from_data(search_resp, ensure_ascii=False), │
│ 257 │ │ │ │ │ title='题库接口返回' │
│ 258 │ │ │ │ )) │
│ ❱ 259 │ │ │ │ status = self.__fill_answer(question, search_resp) # 填充选项 │
│ 260 │ │ │ │ tb.add_row( │
│ 261 │ │ │ │ │ str(question.q_id), │
│ 262 │ │ │ │ │ question.q_type.name, │
│ │
│ D:\尤恩\Desktop\xxt脚本\CxKitty-main\cxapi\jobs\exam.py:176 in __fill_answer │
│ │
│ 173 │ │ log_suffix = f'[{question.value}(Id.{question.q_id})]' │
│ 174 │ │ self.logger.debug(f'开始填充题目 {log_suffix}') │
│ 175 │ │ if search_resp.get('code') == 1: │
│ ❱ 176 │ │ │ if (r := self.searcher.rsp_query.parse(search_resp)): │
│ 177 │ │ │ │ search_answer: str = r[0].strip() │
│ 178 │ │ │ else: │
│ 179 │ │ │ │ return False # JsonPath 选择器匹配失败返回 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'NoneType' object has no attribute 'parse'
程序运行出现错误, 请截图保存并附上 log 文件在 issue 提交
image

可以添加一个匹配不到题目随机选择并提交

在每一章都有章节测验,这个章节测验是无关紧要的,但是章节测验不提交就看不了下一章导致程序报错,可以在章节测验搜不到题目的时候随机填写或者“都选B”然后点提交以便顺利进入下一章

KeyError: 'description'

image
2023-01-12 19:25:09,233 [MainAPI] INFO -> 账号会话验证成功
2023-01-12 19:25:09,233 [MainAPI] INFO -> -----任务开始执行-----
2023-01-12 19:25:09,374 [MainAPI] INFO -> 课程列表拉取成功 共 56 个
2023-01-12 19:25:12,874 [Classes] INFO -> 获取课程 章节列表成功 共 220 个 [大学国文(上)(Cou.232482133/Cla.71724353)]
2023-01-12 19:25:12,905 [Chapters] INFO -> 任务点状态已更新
2023-01-12 19:25:12,952 [Chapters] INFO -> 获取章节任务节点卡片成功 共 0 个 [1:总论(Id.512142648)]
2023-01-12 19:25:12,952 [Chapters] INFO -> 章节 任务节点解析成功 共 0 个 [1:总论(Id.512142648)]
2023-01-12 19:25:12,952 [Chapters] INFO -> 忽略完成任务点 [1.1:总论(Id.512142685)]
2023-01-12 19:25:13,061 [Chapters] INFO -> 忽略完成任务点 [1.2:诗经概述(Id.512142734)]
2023-01-12 19:25:13,170 [Chapters] INFO -> 忽略完成任务点 [1.3:孔子编纂说及非孔子编纂说(Id.512142823)]
2023-01-12 19:25:13,280 [Chapters] INFO -> 忽略完成任务点 [1.4:采诗说(Id.512142824)]
2023-01-12 19:25:13,389 [Chapters] INFO -> 忽略完成任务点 [1.5:诗经的内容、艺术特色及传播(Id.512142825)]
2023-01-12 19:25:13,499 [Chapters] INFO -> 忽略完成任务点 [1.6:章节测验(Id.512142828)]
2023-01-12 19:25:13,639 [Chapters] INFO -> 获取章节任务节点卡片成功 共 0 个 [2:诗经(Id.512142649)]
2023-01-12 19:25:13,639 [Chapters] INFO -> 章节 任务节点解析成功 共 0 个 [2:诗经(Id.512142649)]
2023-01-12 19:25:13,639 [Chapters] INFO -> 忽略完成任务点 [2.1:卫风•伯兮(Id.512142682)]
2023-01-12 19:25:13,749 [Chapters] INFO -> 忽略完成任务点 [2.2:王风•黍离(Id.512142712)]
2023-01-12 19:25:13,858 [Chapters] INFO -> 忽略完成任务点 [2.3:《黍离》赏析(Id.512142826)]
2023-01-12 19:25:13,967 [Chapters] INFO -> 忽略完成任务点 [2.4:“黍离麦秀”的文化现象(Id.512142827)]
2023-01-12 19:25:14,077 [Chapters] INFO -> 忽略完成任务点 [2.5:章节测验(Id.512142829)]
2023-01-12 19:25:14,217 [Chapters] INFO -> 获取章节任务节点卡片成功 共 1 个 [3:屈原(Id.512142650)]
2023-01-12 19:25:14,342 [MainAPI] ERROR -> -----程序运行异常退出-----
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\CxKitty-main\main.py", line 129, in
fuck_task_worker(chapter)
File "C:\Users\Administrator\Desktop\CxKitty-main\main.py", line 66, in fuck_task_worker
for task_point in chap.fetch_points_by_index(index): # 获取当前章节的所有任务点, 并遍历
File "C:\Users\Administrator\Desktop\CxKitty-main\cxapi\chapters.py", line 168, in fetch_points_by_index
if card["description"] == "":
KeyError: 'description'
易姐,这门课运行到这个点就会崩,别的课试了下不会

小白问个问题

084f8a1b2a98add9a72b8d4fd9c2b02
我实在不懂这个怎么解决,昨天从下午弄到晚上三点我也没弄明白怎么搞,可以教教我这是为啥吗?

RuntimeError: 视频预拉取出错

pre_fetch 阶段:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /root/CxKitty/cxapi/jobs/video.py:97 in pre_fetch                                                │
│                                                                                                  │
│    94 │   │   │   print(html)                                                                    │
│    95 │   │   │   if r := re.search(                                                             │
│    96 │   │   │   │   r"window\.AttachmentSetting *= *(.+?);",                                   │
│ ❱  97 │   │   │   │   html.head.find("script", type="text/javascript").text,                     │
│    98 │   │   │   ):                                                                             │
│    99 │   │   │   │   attachment = json.loads(r.group(1))                                        │
│   100 │   │   │   else:                                                                          │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'NoneType' object has no attribute 'text'

During handling of the above exception, another exception occurred:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /root/CxKitty/main.py:129 in <module>                                                            │
│                                                                                                  │
│   126 │   │   classes = api.fetch_classes()  # 拉取该账号下所学的课程                            │
│   127 │   │   course_seq = dialog.select_class(console, classes)  # 进行课程选择                 │
│   128 │   │   for chapter in course_seq:  # 迭代返回课程章节                                     │
│ ❱ 129 │   │   │   fuck_task_worker(chapter)                                                      │
│   130 │   except Exception as err:                                                               │
│   131 │   │   console.print_exception(show_locals=False)                                         │
│   132 │   │   api.logger.error("-----*程序运行异常退出*-----", exc_info=True)                    │
│                                                                                                  │
│ /root/CxKitty/main.py:68 in fuck_task_worker                                                     │
│                                                                                                  │
│    65 │   │   │   │   continue                                                                   │
│    66 │   │   │   for task_point in chap.fetch_points_by_index(index):  # 获取当前章节的所有任   │
│    67 │   │   │   │   # 预拉取任务点数据                                                         │
│ ❱  68 │   │   │   │   prefetch_status = task_point.pre_fetch()                                   │
│    69 │   │   │   │   if not prefetch_status:                                                    │
│    70 │   │   │   │   │   del task_point                                                         │
│    71 │   │   │   │   │   continue                                                               │
│                                                                                                  │
│ /root/CxKitty/cxapi/jobs/video.py:123 in pre_fetch                                               │
│                                                                                                  │
│   120 │   │   │   return False                                                                   │
│   121 │   │   except Exception:                                                                  │
│   122 │   │   │   self.logger.error("预拉取失败")                                                │
│ ❱ 123 │   │   │   raise RuntimeError("视频预拉取出错")                                           │
│   124 │                                                                                          │
│   125 │   def fetch(self) -> bool:                                                               │
│   126 │   │   "拉取视频"                                                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: 视频预拉取出错
程序运行出现错误, 请截图保存并附上 log 文件在 issue 提交

html 内容如下:

<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no" name="viewport"/>
<meta content="no-cache" http-equiv="pragma"/>
<meta content="no-cache" http-equiv="cache-control"/>
<meta content="0" http-equiv="expires"/>
<meta charset="utf-8"/>
<title>提示页面</title>
<style type="text/css">
                *{margin:0;padding:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-appearance:none;}
                body{font:14px/1.5 微软雅黑;background:#fff;color:#333;}
                ul{list-style-type:none;}
                input,select,textarea{vertical-align:middle; font:14px 微软雅黑; color:#333;}
                a:link,a:hover,a:active,a:visited{text-decoration:none;color:#333;}
                table{border-spacing:0px; border-collapse:collapse;width:100%; border:0px;margin:0;padding:0;}
                img{border:0px;}
                em{font-style:normal;}
                .clearfix{overflow:hidden;zoom:1;}

                .warn{display:inline-block;width:18px;height:18px;background:url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAACIA
AAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i7
7u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlID
UuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzI
yLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht
bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuM
C8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iODBFMzI4MzBEODhCM0U2ODNFRTNFNTIwNDVBQ0E5RjUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjU5MTZBRj
RDRUE3MTFFNzg3NzRCQ0EzRTg3RTU5REMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjU5MTZBRjNDRUE3MTFFNzg3NzRCQ0EzRTg3RTU5REMiIHhtcDpDcmVhdG9
yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpmMjYwN2Q4
Ny0wYWNjLTRkYjEtOTNjMi04M2I5NGMwNzlhYjkiIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpjY2IyNmUyZi0wZTYzLTExN2ItYWQzMS05M
jc0ZDNkM2M0NWIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4QaypsAAACKUlEQVR42syYv04CQR
DG904okcZAQYFgqQWFpQRLBV9ALbSk0cpQGCMRYkNr5QPoEyha6tlYkJgQLFEoiF6J0CHizGUuQXLAzcJ5fMkv2YTbmY/b2z+zSqlUEgwFgCSQAFaARWCefvsCakAFeAT
ugU+7gT02n4sDGWBjRJ8FYhXYB7rAHVAAnsYlUMf8HgVuAA3YYhhHzVEfjWJEZY1sAy9ASkyuFMXa4Ro5Ba77xn8awlhXFNuWkWPgTDgnjH0yzggOx7lwXnnKZTlrIsAl
J1ooFBLBYNBo67ouGo0GpzvmegbeB9/IBeDjREITiqIYmIYY8lHOP0OzJjM70IBVmzmb4v1GMsI9HZlGcNnedNEIbhkBlRoeF41g7qRKG5jbWldpF3Vbyypt5W4ronLXD
ofkQyPKDBgxpm9rBny0VHOtl1Gv17NsS6iGRl5le+NGhwYQbE+gCi4mD8CeTG/cbZk77jA9qnTA/Xbx+8DcRTSi09HfLWFu3dxjCnTiZsnv94twOGy06/W6aDabMkYK/c
cArDtuuRHQhNfrNTANMVU0a57+E9rhP68pmOvA6vD8BqQ5kXA4Op2OAbaZSlNOy5ITa5klIGcnEn4T5XJZ5m1kKdfIuiZPDzqlrNUfHVbp4YO7QHuKBtoUM8etffHVxWR
m05DZERscDs5tQJXWlwRV9F1G8h/qk6CyoTqN+xGNCFBQ86IGFw+/+e3iRKKLGo22jg+7rn8FGADyGIf3miWVwQAAAABJRU5ErkJggg==) 
no-repeat;background-size:100%;vertical-align:middle;margin-right:5px}
                .yzmTips{text-align:center;font-size:15px;width:95%;margin:0 auto;margin-top:40px;color:#666}
                .yzmInp{width:64%;height:44px;border:solid 1px #e7e7e7;border-radius:3px;outline:none;padding:0 10px;float:left}
                .marTop{margin-top:40px}
                .yzmImg{float:right;width:104px;height:44px;border:solid 1px 
#e7e7e7;border-radius:3px;overflow:hidden;cursor:pointer}
                .submit{width:95%;height:44px;background:#0099ff;color:#fff;line-height:44px;text-align:center;display:block;marg
in:30px auto;border-radius:3px;font-size:14px;border:none;cursor:pointer}

                @media screen and (min-width: 700px) {
                        .yzmTips{margin-top:15%}
                        .yzmTips,.submit{width:320px}
                        .submit{font-size:16px;height:36px;line-height:36px}

                }
        </style>
</head>
<body>
<form action="/html/processVerify.ac" onsubmit="return /[0-9a-zA-Z]{4}/g.test(document.getElementById('ucode').value)">
<div class="yzmTips">
<p>【9010】操作异常,请输入图片中的验证码</p>
<p class="marTop clearfix">
<input name="app" type="hidden" value="0"/>
<input autofocus="" class="yzmInp" id="ucode" maxlength="4" name="ucode" placeholder="输入验证码" type="text"/>
<span class="yzmImg"><img height="44" id="ccc" onclick="this.src='/processVerifyPng.ac?t='+Math.floor(2147483647 * 
Math.random())" width="104"/></span>
</p>
</div>
<input class="submit" type="submit" value="提交"/>
</form>
<script>
        setTimeout(function(){
                document.getElementById("ccc").click();
        },1000);
</script>
</body>
</html>

手机刷课

您好,可以实习手机刷课吗,以前有个项目可以用termux执行,但是停止维护了

提问

我的流程pycharm新建项目地址是https://github.com/SocialSisterYi/CxKitty
然后新建本届3.10的解释器pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -v Poetry==1.5.1
然后install poetry出现下面错误

我的办法是看pyproject.toml和poetry.lock这个看看我还少什么 不然肯定跑不起来

CalledProcessError

Command '['F:\code\CxKitty\venv\Scripts\python.exe', '-m', 'pip', 'uninstall', 'charset-normalizer', '-y']' returned non-zero exit status 2.

at ~\AppData\Local\Programs\Python\Python310\lib\subprocess.py:524 in run
520│ # We don't call process.wait() as .exit does that for us.
521│ raise
522│ retcode = process.poll()
523│ if check and retcode:
→ 524│ raise CalledProcessError(retcode, process.args,
525│ output=stdout, stderr=stderr)
526│ return CompletedProcess(process.args, retcode, stdout, stderr)
527│
528│

The following error occurred when trying to handle this error:

EnvCommandError

Command ['F:\code\CxKitty\venv\Scripts\python.exe', '-m', 'pip', 'uninstall', 'charset-normalizer', '-y'] errored with the following return code 2

Output:
Found existing installation: charset-normalizer 3.2.0
Uninstalling charset-normalizer-3.2.0:
Successfully uninstalled charset-normalizer-3.2.0
ERROR: Exception:
Traceback (most recent call last):
File "F:\code\CxKitty\venv\lib\site-packages\pip_internal\cli\base_command.py", line 160, in exc_logging_wrapper
status = run_func(*args)
File "F:\code\CxKitty\venv\lib\site-packages\pip_internal\commands\uninstall.py", line 103, in run
uninstall_pathset.commit()
File "F:\code\CxKitty\venv\lib\site-packages\pip_internal\req\req_uninstall.py", line 424, in commit
self.moved_paths.commit()
File "F:\code\CxKitty\venv\lib\site-packages\pip_internal\req\req_uninstall.py", line 277, in commit
save_dir.cleanup()
File "F:\code\CxKitty\venv\lib\site-packages\pip_internal\utils\temp_dir.py", line 173, in cleanup
rmtree(self.path)
File "F:\code\CxKitty\venv\lib\site-packages\pip_vendor\tenacity_init
.py", line 328, in wrapped_f
return self(f, *args, **kw)
File "F:\code\CxKitty\venv\lib\site-packages\pip_vendor\tenacity_init
.py", line 408, in call
do = self.iter(retry_state=retry_state)

docker 无法运行

docker run  socialsisteryi/cx-kitty                                                            root@akg 10:40:27
   █████████              █████   ████  ███   █████     █████
  ███░░░░░███            ░░███   ███░  ░░░   ░░███     ░░███
 ███     ░░░  █████ █████ ░███  ███    ████  ███████   ███████   █████ ████
░███         ░░███ ░░███  ░███████    ░░███ ░░░███░   ░░░███░   ░░███ ░███
░███          ░░░█████░   ░███░░███    ░███   ░███      ░███     ░███ ░███
░░███     ███  ███░░░███  ░███ ░░███   ░███   ░███ ███  ░███ ███ ░███ ░███
 ░░█████████  █████ █████ █████ ░░████ █████  ░░█████   ░░█████  ░░███████
  ░░░░░░░░░  ░░░░░ ░░░░░ ░░░░░   ░░░░ ░░░░░    ░░░░░     ░░░░░    ░░░░░███
                                                                  ███ ░███
                                                                 ░░██████
                                                                  ░░░░░░
超星学习通答题姬 Ver0.4.2
SocialSisterYi
─────────────────────────────────────
会话存档为空, 请登录账号
请输入手机号, 留空为二维码登录: ╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /app/main.py:262 in <module>                                                 │
│                                                                              │
│   259 │   # 会话存档为空                                                     │
│   260 │   else:                                                              │
│   261 │   │   console.print("[yellow]会话存档为空, 请登录账号")              │
│ ❱ 262 │   │   dialog.login(console, api)                                     │
│   263 │   logger.info("\n-----*任务开始执行*-----")                          │
│   264 │   dialog.accinfo(console, api)                                       │
│   265 │   try:                                                               │
│                                                                              │
│ /app/dialog.py:64 in login                                                   │
│                                                                              │
│    61 def login(tui_ctx: Console, api: ChaoXingAPI):                         │
│    62 │   "交互-登录账号"                                                    │
│    63 │   while True:                                                        │
│ ❱  64 │   │   uname = Prompt.ask("[yellow]请输入手机号, 留空为二维码登录[/]" │
│    65 │   │   tui_ctx.print('')                                              │
│    66 │   │   # 二维码登录                                                   │
│    67 │   │   if uname == "":                                                │
│                                                                              │
│ /app/.venv/lib/python3.10/site-packages/rich/prompt.py:141 in ask            │
│                                                                              │
│   138 │   │   │   show_default=show_default,                                 │
│   139 │   │   │   show_choices=show_choices,                                 │
│   140 │   │   )                                                              │
│ ❱ 141 │   │   return _prompt(default=default, stream=stream)                 │
│   142 │                                                                      │
│   143 │   def render_default(self, default: DefaultType) -> Text:            │
│   144 │   │   """Turn the supplied default in to a Text instance.            │
│                                                                              │
│ /app/.venv/lib/python3.10/site-packages/rich/prompt.py:274 in __call__       │
│                                                                              │
│   271 │   │   while True:                                                    │
│   272 │   │   │   self.pre_prompt()                                          │
│   273 │   │   │   prompt = self.make_prompt(default)                         │
│ ❱ 274 │   │   │   value = self.get_input(self.console, prompt, self.password │
│   275 │   │   │   if value == "" and default != ...:                         │
│   276 │   │   │   │   return default                                         │
│   277 │   │   │   try:                                                       │
│                                                                              │
│ /app/.venv/lib/python3.10/site-packages/rich/prompt.py:203 in get_input      │
│                                                                              │
│   200 │   │   Returns:                                                       │
│   201 │   │   │   str: String from user.                                     │
│   202 │   │   """                                                            │
│ ❱ 203 │   │   return console.input(prompt, password=password, stream=stream) │
│   204 │                                                                      │
│   205 │   def check_choice(self, value: str) -> bool:                        │
│   206 │   │   """Check value is in the list of valid choices.                │
│                                                                              │
│ /app/.venv/lib/python3.10/site-packages/rich/console.py:2102 in input        │
│                                                                              │
│   2099 │   │   │   if stream:                                                │
│   2100 │   │   │   │   result = stream.readline()                            │
│   2101 │   │   │   else:                                                     │
│ ❱ 2102 │   │   │   │   result = input()                                      │
│   2103 │   │   return result                                                 │
│   2104 │                                                                     │
│   2105 │   def export_text(self, *, clear: bool = True, styles: bool = False │
╰──────────────────────────────────────────────────────────────────────────────╯
EOFError: EOF when reading a line

docker

docker容器拉取报错

题库录入功能

是否可以实现一键录入题库,用同学已经做完的账号录入该课程的题目,然后给自己账号做的时候就方便很多了

RuntimeError: 视频预拉取出错

RuntimeError: 视频预拉取出错

运行环境

  • 操作系统:Debian 11 bullseye
  • 内核版本:x86_64 Linux 5.10.0-11-amd64
  • Python版本:Python 3.10.8
  • Poetry版本:Poetry (version 1.3.1)

报错内容

RuntimeError: 视频预拉取出错

报错截图

报错文本
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/lighthouse/RemoteWorking/CxKitty/cxapi/jobs/video.py:73 in pre_fetch                       │
│                                                                                                  │
│    70 │   │   resp.raise_for_status()                                                            │
│    71 │   │   html = BeautifulSoup(resp.text, 'lxml')                                            │
│    72 │   │   try:                                                                               │
│ ❱  73 │   │   │   if r := re.search(r'window\.AttachmentSetting *= *(.+?);', html.head.find('s   │
│    74 │   │   │   │   attachment = json.loads(r.group(1))                                        │
│    75 │   │   │   else:                                                                          │
│    76 │   │   │   │   raise ValueError                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'NoneType' object has no attribute 'text'

During handling of the above exception, another exception occurred:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/lighthouse/RemoteWorking/CxKitty/main.py:131 in <module>                                   │
│                                                                                                  │
│   128 │   │   classes = api.fetch_classes()  # 拉取该账号下所学的课程                            │
│   129 │   │   inp = dialog.select_class(console, classes)  # 进行选择课程                        │
│   130 │   │   chap = classes.fetch_chapters_by_index(int(inp))                                   │
│ ❱ 131 │   │   fuck_task_worker(chap)                                                             │
│   132 │   except Exception as err:                                                               │
│   133 │   │   console.print_exception(show_locals=False)                                         │
│   134 │   │   api.logger.error('-----*程序运行异常退出*-----', exc_info=True)                    │
│                                                                                                  │
│ /home/lighthouse/RemoteWorking/CxKitty/main.py:69 in fuck_task_worker                            │
│                                                                                                  │
│    66 │   │   │   │   continue                                                                   │
│    67 │   │   │   for task_point in chap.fetch_points_by_index(index):  # 获取当前章节的所有任   │
│    68 │   │   │   │   # 预拉取任务点数据                                                         │
│ ❱  69 │   │   │   │   prefetch_status = task_point.pre_fetch()                                   │
│    70 │   │   │   │   if not prefetch_status:                                                    │
│    71 │   │   │   │   │   del task_point                                                         │
│    72 │   │   │   │   │   continue                                                               │
│                                                                                                  │
│ /home/lighthouse/RemoteWorking/CxKitty/cxapi/jobs/video.py:89 in pre_fetch                       │
│                                                                                                  │
│    86 │   │   │   return False  # 非任务点视频不需要完成                                         │
│    87 │   │   except Exception:                                                                  │
│    88 │   │   │   self.logger.error('预拉取失败')                                                │
│ ❱  89 │   │   │   raise RuntimeError('视频预拉取出错')                                           │
│    90 │                                                                                          │
│    91 │   def fetch(self) -> bool:                                                               │
│    92 │   │   '拉取视频'                                                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: 视频预拉取出错
程序运行出现错误, 请截图保存并附上 log 文件在 issue 提交

错误日志

2022-12-18 14:08:21,193 [Chapters] INFO -> 获取章节任务节点卡片成功 共 1 个 [8.1:历年真题一(Id.657778397)]
2022-12-18 14:08:21,195 [Chapters] DEBUG -> (0) 解析卡片成功 共 3 个任务点
2022-12-18 14:08:21,195 [Chapters] DEBUG -> (0, 0) 视频任务点 schema: {'objectid': 'a11c45576b67c1ad70ebac4f936da27a', 'name': '2019-12-25-1历年真题一填空单选.avi', 'type': '.avi', 'size': 379664384, 'hsize': '362.08 MB', 'mid': '8266337055801577437367671', '_jobid': '1577437370044633', 'doublespeed': 1, 'retract': 'true'}
2022-12-18 14:08:21,195 [Chapters] DEBUG -> (0, 1) 视频任务点 schema: {'objectid': 'b08b0011303fc585228a5f78c9b13250', 'name': '2019-12-25-3历年真题一计算B.avi', 'type': '.avi', 'size': 520065536, 'hsize': '495.97 MB', 'mid': '11492115890911577437559470', '_jobid': '1577437561660449', 'doublespeed': 1}
2022-12-18 14:08:21,196 [Chapters] DEBUG -> (0, 2) 视频任务点 schema: {'objectid': 'ff885a3c7d5cef1d3c17a2fc3f9c76e6', 'name': '2019-12-25-2历年真题一计算A.avi', 'type': '.avi', 'size': 69211136, 'hsize': '66 MB', 'mid': '15727121474031577437410292', '_jobid': '157743741223550', 'doublespeed': 1}
2022-12-18 14:08:21,196 [Chapters] INFO -> 章节 任务节点解析成功 共 3 个 [8.1:历年真题一(Id.657778397)]
2022-12-18 14:08:21,250 [PointVideo] DEBUG -> attachment: {'hiddenConfig': False, 'attachments': [{'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886-rt_d-ds_1-ff_d-be_0_0-vt_1-v_6-enc_f8482df47669eeefc8867e6f2f8e1436&courseId=228640141', 'customType': 0, 'ends': 0, 'property': {'size': 379664384, 'hsize': '362.08 MB', 'retract': 'true', 'module': 'insertvideo', 'name': '2019-12-25-1历年真题一填空单选.avi', 'mid': '8266337055801577437367671', 'type': '.avi', 'doublespeed': 1, 'objectid': 'a11c45576b67c1ad70ebac4f936da27a', '_jobid': '1577437370044633'}, 'mid': '8266337055801577437367671', 'jumpTimePointList': [], 'type': 'video', 'aid': 1274104218, 'objectId': 'a11c45576b67c1ad70ebac4f936da27a'}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886-rt_d-ds_1-ff_d-be_0_0-vt_1-v_6-enc_f8482df47669eeefc8867e6f2f8e1436&courseId=228640141', 'customType': 0, 'ends': 0, 'property': {'size': 520065536, 'hsize': '495.97 MB', 'module': 'insertvideo', 'name': '2019-12-25-3历年真题一计算B.avi', 'mid': '11492115890911577437559470', 'type': '.avi', 'doublespeed': 1, 'objectid': 'b08b0011303fc585228a5f78c9b13250', '_jobid': '1577437561660449'}, 'mid': '11492115890911577437559470', 'jumpTimePointList': [], 'type': 'video', 'aid': 1274104219, 'objectId': 'b08b0011303fc585228a5f78c9b13250'}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886-rt_d-ds_1-ff_d-be_0_0-vt_1-v_6-enc_f8482df47669eeefc8867e6f2f8e1436&courseId=228640141', 'customType': 0, 'ends': 0, 'property': {'size': 69211136, 'hsize': '66 MB', 'module': 'insertvideo', 'name': '2019-12-25-2历年真题一计算A.avi', 'mid': '15727121474031577437410292', 'type': '.avi', 'doublespeed': 1, 'objectid': 'ff885a3c7d5cef1d3c17a2fc3f9c76e6', '_jobid': '157743741223550'}, 'mid': '15727121474031577437410292', 'jumpTimePointList': [], 'type': 'video', 'aid': 1274104220, 'objectId': 'ff885a3c7d5cef1d3c17a2fc3f9c76e6'}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886', 'ends': 0, 'property': {'module': 'insertimage', 'objectid': '58a7296b1e34bc79591396d5acb36550'}, 'aid': 1274104221}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886', 'ends': 0, 'property': {'module': 'insertimage', 'objectid': '49f9dca34c979716348408faaaa0c696'}, 'aid': 1274104222}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886', 'ends': 0, 'property': {'module': 'insertimage', 'objectid': '255a6fbc3341652e9cfb282bef54283c'}, 'aid': 1274104223}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886', 'ends': 0, 'property': {'module': 'insertimage', 'objectid': '3f28d62b72e334187b8e4b9cc82b20a1'}, 'aid': 1274104224}, {'begins': 0, 'otherInfo': 'nodeId_657778397-cpi_264685886', 'ends': 0, 'property': {'module': 'insertimage', 'objectid': '2d73ffe8bfff3becf9b641422f0aa176'}, 'aid': 1274104225}], 'coursename': '高等数学B—微积分(一)2022-2023上', 'defaults': {'fid': '7', 'ktoken': '948523e4f02bbead8afe497048a8fef8', 'mtEnc': '548163c6252309d2086531ffb3a3a3b6', 'playingCapture': 1, 'videoAutoPlay': 0, 'userid': '238341800', 'reportTimeInterval': 60, 'endCapture': 0, 'defenc': 'edd946f4c9b993903e6e3f4fbee849ed', 'cardid': 610689214, 'imageUrl': 'https://p.ananas.chaoxing.com/star3/origin/1e8e06d8884895a0065af6a603d38033.jpg', 'state': 0, 'cpi': 264685886, 'captureInterval': 10, 'playAginCapture': 0, 'startCapture': 1, 'isFiled': 0, 'ignoreVideoCtrl': 0, 'reportUrl': 'https://mooc1-api.chaoxing.com/multimedia/log/a/264685886', 'chapterCapture': 0, 'initdataUrl': 'https://mooc1-api.chaoxing.com/richvideo/initdatawithviewer', 'knowledgeid': 657778397, 'videoTopicCloud': 0, 'qnenc': '74c28c3083cbe081537560c22e6ae6db', 'clazzId': 63591612, 'chapterCollectionType': 0, 'lastmodifytime': 1671205888000, 'courseid': 228640141, 'subtitleUrl': 'https://mooc1-api.chaoxing.com/richvideo/subtitle', 'playingLoopCapture': 0}, 'mooc2': 0, 'knowledgename': '历年真题一', 'control': True, 'chapterVideoTranslate': 0, 'isErya': 2}
2022-12-18 14:08:21,250 [PointVideo] INFO -> 不存在任务已忽略
2022-12-18 14:08:21,327 [PointVideo] ERROR -> 预拉取失败
2022-12-18 14:08:21,416 [MainAPI] ERROR -> -----*程序运行异常退出*-----
Traceback (most recent call last):
  File "/home/lighthouse/RemoteWorking/CxKitty/cxapi/jobs/video.py", line 73, in pre_fetch
    if r := re.search(r'window\.AttachmentSetting *= *(.+?);', html.head.find('script', type='text/javascript').text):
AttributeError: 'NoneType' object has no attribute 'text'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/lighthouse/RemoteWorking/CxKitty/main.py", line 131, in <module>
    fuck_task_worker(chap)
  File "/home/lighthouse/RemoteWorking/CxKitty/main.py", line 69, in fuck_task_worker
    prefetch_status = task_point.pre_fetch()
  File "/home/lighthouse/RemoteWorking/CxKitty/cxapi/jobs/video.py", line 89, in pre_fetch
    raise RuntimeError('视频预拉取出错')
RuntimeError: 视频预拉取出错

全部日志如下:

cxkitty_15533181757.log

感谢

感谢大佬,已经成功封装成exe并且用的很顺手

No such file or directory: 'questions.json'

Traceback (most recent call last):
File "/app/main.py", line 41, in
searcher = JsonFileSearcher(
File "/app/searcher.py", line 58, in init
with open(file_path, 'r', encoding='utf8') as fp:
FileNotFoundError: [Errno 2] No such file or directory: 'questions.json'

RuntimeError: 视频预拉取出错

2022-12-16 17:29:17,890 [MainAPI] INFO -> -----任务开始执行-----
2022-12-16 17:29:19,410 [MainAPI] INFO -> 课程列表拉取成功 共 38 个
2022-12-16 17:29:32,937 [Classes] INFO -> 获取课程 章节列表成功 共 67 个 [美术鉴赏(Cou.210599244/Cla.63236432)]
2022-12-16 17:29:33,048 [Chapters] INFO -> 任务点状态已更新
2022-12-16 17:29:35,488 [Chapters] INFO -> 获取章节任务节点卡片成功 共 0 个 [1:美术鉴赏(Id.283986394)]
2022-12-16 17:29:35,488 [Chapters] INFO -> 章节 任务节点解析成功 共 0 个 [1:美术鉴赏(Id.283986394)]
2022-12-16 17:29:40,169 [Chapters] INFO -> 获取章节任务节点卡片成功 共 3 个 [1.1:美术作品和艺术哲学(Id.283986397)]
2022-12-16 17:29:40,172 [Chapters] DEBUG -> (0) 解析卡片成功 共 0 个任务点
2022-12-16 17:29:40,173 [Chapters] DEBUG -> (1) 解析卡片成功 共 1 个任务点
2022-12-16 17:29:40,173 [Chapters] DEBUG -> (1, 0) 视频任务点 schema: {'objectid': '53a80cd1a3103c3a4ed90b5e', 'name': 'TS127A60277A1.mp4', 'size': 187172901, 'hsize': '178.5 MB', 'type': '.mp4', 'mid': '523990373441404114462982', '_jobid': 1404114463260, 'fastforward': 'true', 'switchwindow': 'true', 'jobid': 1404114463260, 'retract': 'true'}
2022-12-16 17:29:40,174 [Chapters] DEBUG -> (2) 解析卡片成功 共 1 个任务点
2022-12-16 17:29:40,174 [Chapters] DEBUG -> (2, 0) 测验任务点 schema: {'workid': 'd5ea0aed5ecf4c6287247bd3b83a9906', 'title': '美术作品和艺术哲学', 'worktype': 'workA', 'mid': '11011725886731533366345488', '_jobid': 'work-d5ea0aed5ecf4c6287247bd3b83a9906', 'jobid': 'work-d5ea0aed5ecf4c6287247bd3b83a9906'}
2022-12-16 17:29:40,174 [Chapters] INFO -> 章节 任务节点解析成功 共 2 个 [1.1:美术作品和艺术哲学(Id.283986397)]
2022-12-16 17:29:49,648 [PointVideo] ERROR -> 预拉取失败
2022-12-16 17:29:49,882 [MainAPI] ERROR -> -----程序运行异常退出-----
Traceback (most recent call last):
File "d:\网课\CxKitty\cxapi\jobs\video.py", line 76, in pre_fetch
raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "d:\网课\CxKitty\main.py", line 131, in
fuck_task_worker(chap)
File "d:\网课\CxKitty\main.py", line 69, in fuck_task_worker
prefetch_status = task_point.pre_fetch()
File "d:\网课\CxKitty\cxapi\jobs\video.py", line 89, in pre_fetch
raise RuntimeError('视频预拉取出错')
RuntimeError: 视频预拉取出错
QQ图片20221216174244

解析章节卡片页面attachment的json异常

log里的

2023-09-10 19:01:49,528 [Chapters] DEBUG -> (0, 0) 视频任务点 schema: {'jobid': '1658751832167113', 'switchwindow': 'true', 'rt': '0.9', 'size': 608615583, 'fastforward': 'true', 'hsize': '580.42 MB', 'name': '“沙棘红”映照不渝初心.mp4', 'mid': '1726023073961658751831780', 'type': '.mp4', 'doublespeed': 1, 'objectid': '8dbeeb707a23a25745f764087ad6bad7', '_jobid': '1658751832167113', 'ywbf': 1}
2023-09-10 19:01:49,528 [Chapters] INFO -> 章节 任务节点解析成功 共 1 个 [7.2.1:"沙棘红"映照不渝初心(Id.765173883)]
2023-09-10 19:01:49,748 [Main] ERROR -> 
-----*程序运行异常退出*-----
Traceback (most recent call last):
  File "D:\My_Project\CxKitty-main\CxKitty-main\main.py", line 362, in <module>
    fuck_task_worker(task_obj)
  File "D:\My_Project\CxKitty-main\CxKitty-main\main.py", line 164, in fuck_task_worker
    task_point.fetch_attachment()
  File "D:\My_Project\CxKitty-main\CxKitty-main\cxapi\base.py", line 134, in fetch_attachment
    self.attachment = json.loads(r.group(1))
  File "D:\Program Files\Anaconda\envs\py310\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "D:\Program Files\Anaconda\envs\py310\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "D:\Program Files\Anaconda\envs\py310\lib\json\decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 1718 (char 1717)

命令行里的

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ D:\My_Project\CxKitty-main\CxKitty-main\main.py:362 in <module>                                  │
│                                                                                                  │
│   359 │   │   for task_obj in ClassSelector(command, classes):                                   │
│   360 │   │   │   # 章节容器 执行章节任务                                                        │
│   361 │   │   │   if isinstance(task_obj, ChapterContainer):                                     │
│ ❱ 362 │   │   │   │   fuck_task_worker(task_obj)                                                 │
│   363 │   │   │                                                                                  │
│   364 │   │   │   # 考试对象 执行考试任务                                                        │
│   365 │   │   │   elif isinstance(task_obj, ExamDto):                                            │
│                                                                                                  │
│ D:\My_Project\CxKitty-main\CxKitty-main\main.py:164 in fuck_task_worker                          │
│                                                                                                  │
│   161 │   │   │   for task_point in chap[index]:                                                 │
│   162 │   │   │   │   # 拉取任务卡片 Attachment                                                  │
│   163 │   │   │   │   try:                                                                       │
│ ❱ 164 │   │   │   │   │   task_point.fetch_attachment()                                          │
│   165 │   │   │   │   except ChapterNotOpened:                                                   │
│   166 │   │   │   │   │   lay_left.unsplit()                                                     │
│   167 │   │   │   │   │   lay_left.update(                                                       │
│                                                                                                  │
│ D:\My_Project\CxKitty-main\CxKitty-main\cxapi\base.py:134 in fetch_attachment                    │
│                                                                                                  │
│   131 │   │   │   r"window\.AttachmentSetting *= *(.+?);",                                       │
│   132 │   │   │   html.head.find("script", type="text/javascript").text,                         │
│   133 │   │   ):                                                                                 │
│ ❱ 134 │   │   │   self.attachment = json.loads(r.group(1))                                       │
│   135 │   │   │   self.logger.debug(f"Attachment: {self.attachment}")                            │
│   136 │   │   else:                                                                              │
│   137 │   │   │   if t := html.select_one("p.blankTips"):                                        │
│                                                                                                  │
│ D:\Program Files\Anaconda\envs\py310\lib\json\__init__.py:346 in loads                           │
│                                                                                                  │
│   343 │   if (cls is None and object_hook is None and                                            │
│   344 │   │   │   parse_int is None and parse_float is None and                                  │
│   345 │   │   │   parse_constant is None and object_pairs_hook is None and not kw):              │
│ ❱ 346 │   │   return _default_decoder.decode(s)                                                  │
│   347 │   if cls is None:                                                                        │
│   348 │   │   cls = JSONDecoder                                                                  │
│   349 │   if object_hook is not None:                                                            │
│                                                                                                  │
│ D:\Program Files\Anaconda\envs\py310\lib\json\decoder.py:337 in decode                           │
│                                                                                                  │
│   334 │   │   containing a JSON document).                                                       │
│   335 │   │                                                                                      │
│   336 │   │   """                                                                                │
│ ❱ 337 │   │   obj, end = self.raw_decode(s, idx=_w(s, 0).end())                                  │
│   338 │   │   end = _w(s, end).end()                                                             │
│   339 │   │   if end != len(s):                                                                  │
│   340 │   │   │   raise JSONDecodeError("Extra data", s, end)                                    │
│                                                                                                  │
│ D:\Program Files\Anaconda\envs\py310\lib\json\decoder.py:353 in raw_decode                       │
│                                                                                                  │
│   350 │   │                                                                                      │
│   351 │   │   """                                                                                │
│   352 │   │   try:                                                                               │
│ ❱ 353 │   │   │   obj, end = self.scan_once(s, idx)                                              │
│   354 │   │   except StopIteration as err:                                                       │
│   355 │   │   │   raise JSONDecodeError("Expecting value", s, err.value) from None               │
│   356 │   │   return obj, end                                                                    │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
JSONDecodeError: Unterminated string starting at: line 1 column 1718 (char 1717)
JSON 解析失败, 可能为账号 ck 失效, 请重新登录该账号 (序号+r)

出现以下报错:RuntimeError: 视频预拉取出错 以下是log日志文件

2023-04-10 23:52:29,915 [PointVideo] ERROR -> 预拉取失败
2023-04-10 23:52:29,956 [MainAPI] ERROR -> -----程序运行异常退出-----
Traceback (most recent call last):
File "cxapi\jobs\video.py", line 95, in pre_fetch
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "main.py", line 129, in
File "main.py", line 68, in fuck_task_worker
File "cxapi\jobs\video.py", line 117, in pre_fetch
RuntimeError: 视频预拉取出错

账号密码登录没有反应

你好,我尝试登录发现目前只有二维码可以登录,用账号密码登陆的话程序一直在运行但是无法登录
image

上报时出错

2023-03-28 19:21:21,876 [PointVideo] DEBUG -> 上报 resp: {'isPassed': False, 'videoTimeLimit': False, 'hasJobLimit': False}
2023-03-28 19:21:21,876 [PointVideo] INFO -> 播放上报成功 580/925
2023-03-28 19:22:42,424 [MainAPI] ERROR -> -----*程序运行异常退出*-----
Traceback (most recent call last):
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
                       ^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 449, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 444, in _make_request
    httplib_response = conn.getresponse()
                       ^^^^^^^^^^^^^^^^^^
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 1374, in getresponse
    response.begin()
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 318, in begin
    version, status, reason = self._read_status()
                              ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 287, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\requests\adapters.py", line 489, in send
    resp = conn.urlopen(
           ^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 787, in urlopen
    retries = retries.increment(
              ^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\util\retry.py", line 550, in increment
    raise six.reraise(type(error), error, _stacktrace)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\packages\six.py", line 769, in reraise
    raise value.with_traceback(tb)
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
                       ^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 449, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\urllib3\connectionpool.py", line 444, in _make_request
    httplib_response = conn.getresponse()
                       ^^^^^^^^^^^^^^^^^^
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 1374, in getresponse
    response.begin()
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 318, in begin
    version, status, reason = self._read_status()
                              ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TR\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 287, in _read_status
    raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Download\Projects\CxKitty\main.py", line 129, in <module>
    fuck_task_worker(chapter)
  File "D:\Download\Projects\CxKitty\main.py", line 87, in fuck_task_worker
    task_point.playing(lay_main, config.VIDEO["speed"], config.VIDEO["report_rate"])
  File "D:\Download\Projects\CxKitty\cxapi\jobs\video.py", line 196, in playing
    report_result = self.__play_report(playing_time)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\cxapi\jobs\video.py", line 138, in __play_report
    resp = self.session.get(
           ^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\requests\sessions.py", line 600, in get
    return self.request("GET", url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\requests\sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\requests\sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Download\Projects\CxKitty\.venv\Lib\site-packages\requests\adapters.py", line 547, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.