diff --git a/__pycache__/get_in.cpython-310.pyc b/__pycache__/get_in.cpython-310.pyc new file mode 100644 index 0000000..081c6af Binary files /dev/null and b/__pycache__/get_in.cpython-310.pyc differ diff --git a/__pycache__/get_info.cpython-310.pyc b/__pycache__/get_info.cpython-310.pyc index 0fb95b6..c0e7691 100644 Binary files a/__pycache__/get_info.cpython-310.pyc and b/__pycache__/get_info.cpython-310.pyc differ diff --git a/__pycache__/initialization.cpython-310.pyc b/__pycache__/initialization.cpython-310.pyc new file mode 100644 index 0000000..d7e6c6d Binary files /dev/null and b/__pycache__/initialization.cpython-310.pyc differ diff --git a/__pycache__/kill_course.cpython-310.pyc b/__pycache__/kill_course.cpython-310.pyc index d479e03..0e9fb44 100644 Binary files a/__pycache__/kill_course.cpython-310.pyc and b/__pycache__/kill_course.cpython-310.pyc differ diff --git a/__pycache__/single_course.cpython-310.pyc b/__pycache__/single_course.cpython-310.pyc index a3b6f98..b4c882c 100644 Binary files a/__pycache__/single_course.cpython-310.pyc and b/__pycache__/single_course.cpython-310.pyc differ diff --git a/course_info.json b/course_info.json index 62ec159..1290d90 100644 --- a/course_info.json +++ b/course_info.json @@ -1 +1 @@ -{"6349": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7436": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7367": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7366": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7033": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7517": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7032": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7516": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7031": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7515": {"rate": 100, "type": "\u5fc5\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "6937": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6938": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6991": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6992": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6993": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "6995": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7006": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7007": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7010": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7011": {"rate": 100, "type": "\u57f9\u8bad", "status": "\u5df2\u5b66\u5b8c"}, "7554": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7553": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7552": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7551": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7550": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7549": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7548": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7547": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7546": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7545": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}, "7564": {"rate": 100, "type": "\u9009\u4fee", "status": "\u5df2\u5b66\u5b8c"}} \ No newline at end of file +{"7033": {"name": "\u300a\u5171\u4ea7\u515a\u5ba3\u8a00\u300b\u7684\u65b0\u65f6\u4ee3\u9610\u8ff0", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7517": {"name": "\u4ee5\u4e2d\u56fd\u5f0f\u73b0\u4ee3\u5316\u5168\u9762\u63a8\u8fdb\u4e2d\u534e\u6c11\u65cf\u4f1f\u5927\u590d\u5174", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7032": {"name": "\u5927\u56fd\u535a\u5f08\u8c01\u80fd\u7b11\u5230\u6700\u540e", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7516": {"name": "\u4e60\u8fd1\u5e73\u603b\u4e66\u8bb0\u5173\u4e8e\u575a\u6301\u548c\u52a0\u5f3a\u515a\u7684\u5168\u9762\u9886\u5bfc\u91cd\u8981\u8bba\u8ff0", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7031": {"name": "\u5168\u7403\u7f51\u7edc\u7a7a\u95f4\u600e\u4e48\u7ba1", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7515": {"name": "\u4e60\u8fd1\u5e73\u65b0\u65f6\u4ee3\u4e2d\u56fd\u7279\u8272\u793e\u4f1a\u4e3b\u4e49\u601d\u60f3\u7684\u4e16\u754c\u89c2\u548c\u65b9\u6cd5\u8bba", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6349": {"name": "\u6d3b\u7684\u9a6c\u514b\u601d\u4e3b\u4e49", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7436": {"name": "\u4e60\u8fd1\u5e73\u603b\u4e66\u8bb0\u5173\u4e8e\u9752\u5e74\u5de5\u4f5c\u7684\u91cd\u8981\u601d\u60f3\u6982\u8bba", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7367": {"name": "\u4e3a\u4ec0\u4e48\u8981\u6df1\u5165\u6279\u5224\u5386\u53f2\u865a\u65e0\u4e3b\u4e49\uff1f", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7366": {"name": "\u793e\u4f1a\u4e3b\u4e49\u6838\u5fc3\u4ef7\u503c\u89c2\u4e0e\u9752\u5e74", "type": "\u5fc5\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6937": {"name": "\u589e\u5f3a\u56db\u529b\u6253\u9020\u8fc7\u786c\u5ba3\u4f20\u601d\u60f3\u5de5\u4f5c\u961f\u4f0d\uff08\u4e0a\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6938": {"name": "\u589e\u5f3a\u56db\u529b\u6253\u9020\u8fc7\u786c\u5ba3\u4f20\u601d\u60f3\u5de5\u4f5c\u961f\u4f0d\uff08\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6991": {"name": "\u201c\u4e92\u8054\u7f51\uff0b\u201d\u80cc\u666f\u4e0b\u5386\u53f2\u865a\u65e0\u4e3b\u4e49\u7684\u5371\u5bb3\u53ca\u5e94\u5bf9\uff08\u4e0a\u3001\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6992": {"name": "\u5168\u7403\u4f20\u64ad\u65f6\u4ee3\u7684\u7f51\u7edc\u6587\u5316\u4e0e\u610f\u8bc6\u5f62\u6001", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6993": {"name": "\u300a\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd\u7f51\u7edc\u5b89\u5168\u6cd5\u300b\u89e3\u8bfb", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "6995": {"name": "\u7f51\u7edc\u4e92\u8054\u65f6\u4ee3\u4e0e\u5fc3\u7406\u5065\u5eb7\u4fc3\u8fdb", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7006": {"name": "\u7f51\u7edc\u66b4\u529b\u7814\u7a76\uff08\u4e0a\u3001\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7007": {"name": "\u8425\u9020\u98ce\u6e05\u6c14\u6b63\u7684\u7f51\u7edc\u7a7a\u95f4\uff08\u4e0a\u3001\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7010": {"name": "\u8c03\u8282\u60c5\u7eea\u7684\u6709\u6548\u65b9\u6cd5\uff08\u4e0a\u3001\u4e2d\u3001\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7011": {"name": "\u7528\u6838\u5fc3\u4ef7\u503c\u89c2\u5f15\u9886\u7f51\u7edc\u6587\u5316\u5efa\u8bbe\uff08\u4e0a\u3001\u4e0b\uff09", "type": "\u57f9\u8bad", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7554": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u771f\u6293\u5b9e\u5e72\u505a\u597d\u65b0\u53d1\u5c55\u9636\u6bb5\u201c\u4e09\u519c\u201d\u5de5\u4f5c", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7553": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u52aa\u529b\u5b9e\u73b0\u9ad8\u6c34\u5e73\u79d1\u6280\u81ea\u7acb\u81ea\u5f3a", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7552": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u6df1\u5165\u8d2f\u5f7b\u65b0\u53d1\u5c55\u7406\u5ff5", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7551": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u51c6\u786e\u628a\u63e1\u65b0\u53d1\u5c55\u9636\u6bb5", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7550": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u6784\u5efa\u65b0\u53d1\u5c55\u683c\u5c40\u8981\u628a\u63e1\u597d\u51e0\u4e2a\u91cd\u8981\u7740\u529b\u70b9", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7549": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u4ee5\u65b0\u53d1\u5c55\u683c\u5c40\u91cd\u5851\u65b0\u7ade\u4e89\u4f18\u52bf", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7548": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u52a0\u5feb\u6784\u5efa\u65b0\u53d1\u5c55\u683c\u5c40", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7547": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u5411\u7b2c\u4e8c\u4e2a\u767e\u5e74\u594b\u6597\u76ee\u6807\u8fdb\u519b", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7546": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u59cb\u7ec8\u575a\u6301\u4eba\u6c11\u81f3\u4e0a", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7545": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u575a\u6301\u548c\u52a0\u5f3a\u515a\u7684\u5168\u9762\u9886\u5bfc", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7564": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u63a8\u52a8\u201c\u4e00\u5e26\u4e00\u8def\u201d\u5efa\u8bbe\u9ad8\u8d28\u91cf\u53d1\u5c55", "type": "\u9009\u4fee", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7494": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u4e94\uff1a\u4e3a\u4ec0\u4e48\u8981\u575a\u6301\u63a8\u52a8\u6784\u5efa\u4eba\u7c7b\u547d\u8fd0\u5171\u540c\u4f53", "type": "\u4e13\u9898", "rate": 100, "status": "\u5df2\u5b66\u5b8c"}, "7493": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u56db\uff1a\u575a\u6301\u548c\u5b8c\u5584\u201c\u4e00\u56fd\u4e24\u5236\u201d \u63a8\u8fdb\u7956\u56fd\u7edf\u4e00", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "6567": {"name": "4.\u6c38\u4e0d\u51cb\u8c22\u7684\u5170\u82b1", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7565": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u4ee5\u4f1f\u5927\u81ea\u6211\u9769\u547d\u5f15\u9886\u4f1f\u5927\u793e\u4f1a\u9769\u547d", "type": "\u9009\u4fee", "rate": 32, "status": "\u672a\u5b66\u5b8c"}, "7492": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u4e09\uff1a\u5f00\u521b\u56fd\u9632\u548c\u519b\u961f\u73b0\u4ee3\u5316\u65b0\u5c40\u9762", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "6193": {"name": "\u9a6c\u514b\u601d\u4e3b\u4e49\u54f2\u5b66\u7684\u57fa\u672c\u89c2\u70b9\u4e0e\u65b9\u6cd5\uff08\u4e0a\u3001\u4e0b\uff09", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7536": {"name": "\u5173\u4e8e\u515a\u7684\u5386\u53f2\u7684\u91cd\u8981\u8bba\u8ff0\u4e4b\u516b\uff1a\u4e2d\u56fd\u5171\u4ea7\u515a\u7684\u4f1f\u5927\u7cbe\u795e\u6c38\u4e0d\u8fc7\u65f6", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7563": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u63a8\u52a8\u6784\u5efa\u4eba\u7c7b\u547d\u8fd0\u5171\u540c\u4f53", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7561": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u5c55\u793a\u4e2d\u56fd\u6587\u827a\u65b0\u6c14\u8c61 \u94f8\u5c31\u4e2d\u534e\u6587\u5316\u65b0\u8f89\u714c", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7562": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u575a\u6301\u8d70\u4e2d\u56fd\u7279\u8272\u5f3a\u519b\u4e4b\u8def", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7560": {"name": "\u300a\u4e60\u8fd1\u5e73\u8c08\u6cbb\u56fd\u7406\u653f\u300b\u7b2c\u56db\u5377\uff1a\u5982\u4f55\u505a\u597d\u65b0\u65f6\u4ee3\u515a\u7684\u6c11\u65cf\u5de5\u4f5c", "type": "\u9009\u4fee", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7491": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u4e03\uff1a\u5982\u4f55\u7406\u89e3\u201c\u4e94\u4e2a\u7262\u7262\u628a\u63e1\u201d", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7490": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u516d\uff1a\u6df1\u5165\u63a8\u8fdb\u65b0\u65f6\u4ee3\u515a\u7684\u5efa\u8bbe\u65b0\u7684\u4f1f\u5927\u5de5\u7a0b", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7489": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u4e5d\uff1a\u515a\u7684\u4e8c\u5341\u5927\u62a5\u544a\u4e2d\u7684\u65b0\u8868\u8ff0\u65b0\u6982\u62ec\u65b0\u8bba\u65ad", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}, "7488": {"name": "\u5b66\u4e60\u8d2f\u5f7b\u515a\u7684\u4e8c\u5341\u5927\u7cbe\u795e\u7cfb\u5217\u4e4b\u5341\u516b\uff1a\u515a\u7684\u4e8c\u5341\u5927\u62a5\u544a\u4e2d\u7684\u9ad8\u9891\u8bcd\u6c47", "type": "\u4e13\u9898", "rate": 0, "status": "\u672a\u5b66\u5b8c"}} \ No newline at end of file diff --git a/demo.py b/demo.py index 38451ce..8038806 100644 --- a/demo.py +++ b/demo.py @@ -1,20 +1,10 @@ -from DrissionPage import ChromiumPage -from DrissionPage.common import * -from loguru import logger -import subprocess -from get_info import login -# page = ChromiumPage() -# page.get('http://hnqmgc.17el.cn/') -# try: -# if page.ele('@onclick=cha()',timeout=3): -# page.ele('@onclick=cha()').click() -# # -# elif page.ele('tag:img@@style=width: 25px;height: 25px;',timeout=3): -# page.ele('tag:img@@style=width: 25px;height: 25px;').click() -# except BaseException: -# logger.error('不能进入课程页面') -# subprocess.run(["python", __file__]) -# exit() -# page.ele('tag:a@@text():青马课堂').hover() -# page.ele('tag:a@@text():全部').click().for_new_tab() -login(first=True,init=True) \ No newline at end of file +import json +dic = json.load(open('course_info.json', 'r')) +l1 = [ i for i in dic.keys() if dic[i]['type'] == '选修' ] +l2 = [ i for i in dic.keys() if dic[i]['type'] == '必修' ] +l3 = [ i for i in dic.keys() if dic[i]['type'] == '专题' ] +l4 = [ i for i in dic.keys() if dic[i]['type'] == '培训' ] +print(len(l1)) +print(len(l2)) +print(len(l3)) +print(len(l4)) \ No newline at end of file diff --git a/file.log b/file.log deleted file mode 100644 index bb1db5f..0000000 --- a/file.log +++ /dev/null @@ -1 +0,0 @@ -2024-03-10T12:13:35.955107+0800 DEBUG 这是一条具有自定义格式的日志信息 diff --git a/get_in.py b/get_in.py new file mode 100644 index 0000000..da919f6 --- /dev/null +++ b/get_in.py @@ -0,0 +1,70 @@ +import tkinter as tk +from tkinter import ttk +import json + + +def create_login_window(): + # 创建主窗口 + root = tk.Tk() + root.title("Integrated Window") + + # 设置窗口的初始大小并居中显示 + window_width = 600 + window_height = 400 + screen_width = root.winfo_screenwidth() + screen_height = root.winfo_screenheight() + center_x = int(screen_width / 2 - window_width / 2) + center_y = int(screen_height / 2 - window_height / 2) + root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") + + # 用户名和密码变量 + username_var = tk.StringVar() + password_var = tk.StringVar() + + # 下拉选择框的选项 + options = ['网络文明志愿者', '团学干部', '大学生心理健康教育', '入党积极分子'] + + # 创建下拉选择框 + combo_label = tk.Label(root, text="选择学习类型", font=('Helvetica', 12)) + combo_label.pack(pady=(10, 5)) + + combo = ttk.Combobox(root, values=options, width=15, state="readonly") + combo.pack(pady=(0, 20)) # pady增加垂直外边距,有助于在窗口中垂直居中 + + # 创建用户名和密码的标签和输入框 + username_label = tk.Label(root, text="账号", font=('Helvetica', 12)) + username_label.pack(pady=(5, 5)) + + username_entry = tk.Entry( + root, textvariable=username_var, font=('Helvetica', 12)) + username_entry.pack(pady=(0, 10)) + + password_label = tk.Label(root, text="密码", font=('Helvetica', 12)) + password_label.pack(pady=(5, 5)) + + password_entry = tk.Entry( + root, textvariable=password_var, font=('Helvetica', 12), show="*") + password_entry.pack(pady=(0, 20)) + + # 确定按钮的事件处理函数 + def submit_action(): + username = username_var.get().upper() + password = password_var.get() + study_type = combo.get() + if study_type not in options: + return + with open('info.json', 'w') as f: + json.dump({'username': username, 'password': password, + 'study_type': study_type}, f) + root.destroy() + + submit_button = tk.Button(root, text="提交", command=submit_action) + submit_button.pack(pady=(10, 0)) + + # 运行主循环 + root.mainloop() + + +# 调用函数以创建和显示登录窗口 +if __name__ == "__main__": + create_login_window() diff --git a/get_info.py b/get_info.py index 96fdd42..6b0ff96 100644 --- a/get_info.py +++ b/get_info.py @@ -1,4 +1,4 @@ -from DrissionPage import ChromiumPage,ChromiumOptions +from DrissionPage import ChromiumPage, ChromiumOptions from DrissionPage.common import * from collections import * import time @@ -6,47 +6,53 @@ import json from loguru import logger import subprocess from typing import * +from get_in import create_login_window # http://hnqmgc.17el.cn/grzx/ # 单独实现登录操作 -def get_into_center(cpage:ChromiumPage): - cpage.ele('#login_btn').click() - cpage.ele('@value=进入个人中心').click() -def login(first:bool=True,init:bool=False): + + +def get_into_center(cpage: ChromiumPage): + cpage.ele('#login_btn').click() + cpage.ele('@value=进入个人中心').click() + + +def login(first: bool = True, init: bool = False, username: str = None, pwd: str = None): if not first: return # 先检查当前页面是否已经登录 page = ChromiumPage() try: - if page.ele('tag:div@@text():欢迎您,',timeout=3): + if page.ele('tag:div@@text():欢迎您,', timeout=3): logger.info('当前页面已登录') return except BaseException: logger.info('准备登录') if first: try: - page.get('http://hnqmgc.17el.cn/grzx/',retry=5,timeout=5,interval=1) + page.get('http://hnqmgc.17el.cn/grzx/', + retry=5, timeout=5, interval=1) except BaseException: logger.error('网络连接失败') # 定位到账号文本框,获取文本框元素 - ele = page.ele('#userName') # #的意思是通过id定位元素 + ele = page.ele('#userName') # 的意思是通过id定位元素 # 输入对文本框输入账号 - ele.input('51140220050507901X') + ele.input(username) # 定位到密码文本框并输入密码 - page.ele('#password').input('hnqm123456') + page.ele('#password').input(pwd) # 定位到验证码文本框并输入验证码 - inpcode = page.ele('#yzcode').text # 湖南青马太可爱了吧,验证码居然直接放在页面源码里:) + inpcode = page.ele('#yzcode').text # 湖南青马太可爱了吧,验证码居然直接放在页面源码里:) page.ele('#inpcode').input(inpcode) # 点击登录按钮 page.ele('#btnLogin').click() page.wait.new_tab(3) # 进入课程页面 try: - if page.ele('@onclick=cha()',timeout=3): + if page.ele('@onclick=cha()', timeout=3): page.ele('@onclick=cha()').click() # - elif page.ele('tag:img@@style=width: 25px;height: 25px;',timeout=3): + elif page.ele('tag:img@@style=width: 25px;height: 25px;', timeout=3): page.ele('tag:img@@style=width: 25px;height: 25px;').click() except BaseException: logger.error('不能进入课程页面') @@ -54,24 +60,30 @@ def login(first:bool=True,init:bool=False): exit() if not init: get_into_center(page) -def get_info(first:bool=True): + + +def get_info(first: bool = True): # 创建页面对象,并启动或接管浏览器 page = ChromiumPage() + try: + info = json.load(open('info.json', 'r')) + except BaseException: + create_login_window() + info = json.load(open('info.json', 'r')) + username = info['username'] + pwd = info['password'] # 登录 - login(first) + login(first, init=False, username=username, pwd=pwd) # 提取课程信息 time.sleep(2) if not first: page.refresh() time.sleep(2) - page.ele('@value=0',timeout=3).click() + page.ele('@value=0', timeout=3).click() # 获取总页数 course_info = {} - #
1 / 4
- # total_page = int(page.ele('.paginationjs-nav J-paginationjs-nav').text) - total_page = 4 logger.debug('读取课程信息中...') - for i in range(total_page): + while 1: # 逐页读取课程信息和完成状态并存放到字典中 tbodys = page.ele('#tbody') # 获取tbody下的所有tr @@ -79,18 +91,24 @@ def get_info(first:bool=True): for tr in trs: cur_info = tr.text.split('\t') course_id = cur_info[0] # 课程id - course_type = cur_info[2] # 课程类型 + course_name = cur_info[1] # 课程名称 + course_type = cur_info[2] # 课程类型 course_rate = int(cur_info[3][:-1]) # 课程完成百分比 course_status = cur_info[4] # 课程完成状态(是否完成习题/评价) # 存放到字典中 - course_info[course_id] = {'rate': course_rate,'type': course_type,'status': course_status} - if i != total_page - 1: + course_info[course_id] = { + 'name': course_name, 'type': course_type, 'rate': course_rate, 'status': course_status} + try: page.ele('@title=Next page').click() time.sleep(1) + except BaseException: + break logger.success('课程信息读取完成,共有{}门课程'.format(len(course_info))) # 写入json文件中 with open('course_info.json', 'w') as f: json.dump(course_info, f) + if __name__ == '__main__': - get_info() \ No newline at end of file + create_login_window() + get_info() diff --git a/info.json b/info.json new file mode 100644 index 0000000..3e13eb7 --- /dev/null +++ b/info.json @@ -0,0 +1 @@ +{"username": "51140220050507901X", "password": "hnqm123456", "study_type": "\u7f51\u7edc\u6587\u660e\u5fd7\u613f\u8005"} \ No newline at end of file diff --git a/initialization.py b/initialization.py index 3e88721..bdeafd5 100644 --- a/initialization.py +++ b/initialization.py @@ -13,7 +13,8 @@ from get_info import get_info from collections import * from get_info import login -def click_videoes(study_type:str) -> None: + +def click_videoes(study_type: str, class_info: dict) -> None: ''' study_type:只能在如下选项中选择 1、入党积极分子 @@ -21,33 +22,100 @@ def click_videoes(study_type:str) -> None: 3、团学干部 4、大学生心理健康教育 ''' - # 由于各位学员的培训种类不同,这里交给用户输入 + click_page = ChromiumPage() # 接管当前页面 + valid_type = ['入党积极分子', '网络文明志愿者', '团学干部', '大学生心理健康教育'] + if study_type not in valid_type: + logger.critical('study_type参数错误! 请检查后重新输入!') + return + must = [class_info[k]['name'] + for k in class_info.keys() if class_info[k]['type'] == '必修'] + elective = [class_info[k]['name'] + for k in class_info.keys() if class_info[k]['type'] == '选修'] + column = [class_info[k]['name'] + for k in class_info.keys() if class_info[k]['type'] == '专题'] + # 去空格 + must = [i.strip() for i in must] + elective = [i.strip() for i in elective] + column = [i.strip() for i in column] + # 处理不同的身份用户的个性化专栏 - # 必修,选修,专栏学习是每人都要学习的,统一处理 - def must_study(): - pass - def elective_study(): + def go_special_page(study_type: str) -> None: + click_page.ele(f'tag:a@@text():{study_type}').click() + time.sleep(1) + kcs = click_page.eles('.kclist') + for kc in kcs: + kc_name = kc.ele('.kcmc').text.strip() + if kc_name in column: + continue + else: + kc.ele('.xx').click() + time.sleep(1) + click_page.wait.new_tab(timeout=3) + tab = click_page.latest_tab + try: + tab.ele('tag:input@@text():继续学习').click() + except BaseException: + pass + time.sleep(5) + click_page.close_tabs([tab]) + time.sleep(5) pass - def column_study(): - pass - + # 所有用户都需要进入的视频 + def go_video_page(course_type: str) -> None: + if len(must) >= 10 and len(elective) >= 10 and len(column) >= 10: + return + if course_type == '专题': + course_type = '专栏学习' + dic = {'必修': must, '选修': elective, '专栏学习': column} + # 进入视频一次页 + click_page.ele(f'tag:a@@text():{course_type}').click() + time.sleep(1) + kcs = click_page.eles('.kclist') + for kc in kcs: + kc_name = kc.ele('.kcmc').text.strip() # 空格太抽象了 :) + if kc_name in dic[course_type]: + continue + else: + kc.ele('.xx').click() + click_page.wait.new_tab(timeout=3) + time.sleep(1) + tab = click_page.latest_tab + try: + tab.ele('tag:a@@text():继续学习').click() + except BaseException: + pass + time.sleep(5) + click_page.close_tabs([tab]) + time.sleep(5) + if len(must) < 10: + go_video_page('必修') + if len(elective) < 10: + go_video_page('选修') + if len(column) < 10: + go_video_page('专题') + go_special_page(study_type) # 读取课程数量信息 -def init(): + + +def init(study_type: str = '网络文明志愿者'): ''' 初始化,检测是否需要进入视频一次页以及进行进入视频一次操作 ''' # 获取课程数量信息 get_info() - class_info = json.load(open('course_info.json','r')) + class_info = json.load(open('course_info.json', 'r')) # 读取各个类别的课程数量 cnt = Counter(class_info[k]['type'] for k in class_info.keys()) # 检测是否存在小于10的课程数量 less_10 = [k for k, v in cnt.items() if v < 10] if not less_10: # 直接进行刷课和检测 + logger.info('所有课程数量均大于10,无需初始化') return else: + logger.debug(f'存在课程数量小于10的课程类型:{less_10}') + logger.debug('正在进行初始化...') ''' 回到首页,逐个点击相应视频,每个视频页面停留3秒后推出,并进入下一个视频。 结束调用get_info()函数,更新课程数量信息 @@ -55,8 +123,11 @@ def init(): # 接管当前页面 page = ChromiumPage() # 进入青马课堂页 - login(first=True,init=True) + login(first=True, init=True) page.ele('tag:a@@text():青马课堂').hover() - page.ele('tag:a@@text():全部').click().for_new_tab() - click_videoes() - # 今日はこれで終わりです \ No newline at end of file + page.ele('tag:a@@text():全部').click() + click_videoes(study_type=study_type, class_info=class_info) + + +if __name__ == '__main__': + init() diff --git a/kill_course.py b/kill_course.py index 2444f02..8e27a9e 100644 --- a/kill_course.py +++ b/kill_course.py @@ -4,14 +4,16 @@ from collections import * import json from single_course import one_course from loguru import logger -def kill_course(again:bool=False): + + +def kill_course(again: bool = False): # 统计课程完成情况 cnt = defaultdict(list) # 读取课程信息 info = json.load(open('course_info.json', 'r')) for k, v in info.items(): if v['rate'] < 100: - cnt[v['type']].append((k,v['rate'])) # 课程类型作为键,课程id作为值 + cnt[v['type']].append((k, v['rate'])) # 课程类型作为键,课程id作为值 logger.info('{}'.format(cnt)) if not cnt: logger.info('所有课程均已完成') @@ -29,15 +31,16 @@ def kill_course(again:bool=False): if elective: course_info = elective.pop() logger.info('当前刷课序号:{}'.format(course_info[0])) - one_course(course_info[0], '选修', course_info[1],again=again) + one_course(course_info[0], '选修', course_info[1], again=again) if special: course_info = special.pop() logger.info('当前刷课序号:{}'.format(course_info[0])) - one_course(course_info[0], '专题', course_info[1],again=again) + one_course(course_info[0], '专题', course_info[1], again=again) if train: course_info = train.pop() logger.info('当前刷课序号:{}'.format(course_info[0])) - one_course(course_info[0], '培训', course_info[1],again=again) + one_course(course_info[0], '培训', course_info[1], again=again) + if __name__ == '__main__': - kill_course() \ No newline at end of file + kill_course() diff --git a/kill_quiz.py b/kill_quiz.py deleted file mode 100644 index d717169..0000000 --- a/kill_quiz.py +++ /dev/null @@ -1,5 +0,0 @@ -# 实现答题和评分 -''' -检测课程状态是否存在“未评价”或者“未答题”状态 -''' -from get_info import get_info diff --git a/main.py b/main.py index ecc7d99..3e881aa 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,5 @@ +from kill_course import kill_course +from initialization import init, click_videoes import json from get_info import get_info from collections import * @@ -7,13 +9,18 @@ from typing import * from DrissionPage import ChromiumPage from DrissionPage.common import * import time -# 获取课程信息 +from get_in import create_login_window +import os +# 录入账号密码 +if not os.path.exists('info.json'): + create_login_window() -# 这里以后会放一个初始化模块 +study_type = json.load(open('info.json', 'r'))['study_type'] -get_info(first=False) +# 这里以后会放一个初始化模块 +get_info(first=True) +init(study_type=study_type) # 执行刷课 -from kill_course import kill_course kill_course() # 完成刷课后,判定是否存在需要答题或者评分的课程 ''' @@ -22,15 +29,19 @@ kill_course() 2. 对于其他课存在3种情况:未完成,已完成,未评分 ''' # 重新获取课程信息 -def new_info() -> DefaultDict[str, List[Tuple[str,int,str]]]: + + +def new_info() -> DefaultDict[str, List[Tuple[str, int, str]]]: get_info(first=False) - new_info = json.load(open('course_info.json','r')) + new_info = json.load(open('course_info.json', 'r')) # 读取各个类别的课程状态 new_cnt = defaultdict(list) for k, v in new_info.items(): - new_cnt[v['type']].append((k,v['rate'],v['status'])) # 课程类型作为键,课程id作为值 + new_cnt[v['type']].append( + (k, v['rate'], v['status'])) # 课程类型作为键,课程id作为值 return new_cnt + new_cnt = new_info() # 首先检查是否还存在未完成的课程 for k, v in new_cnt.items(): @@ -49,15 +60,15 @@ not_quiz = [] for k, v in new_cnt.items(): for i in v: if i[2] == '未评分': - not_judged.append((i[0],k)) + not_judged.append((i[0], k)) elif i[2] == '未答题': - not_quiz.append(i[0],k) + not_quiz.append(i[0], k) # 实现自动评分 -def auto_judge(course_id:str,course_type:str) -> None: +def auto_judge(course_id: str, course_type: str) -> None: # 根据课程类型和id进行定位 - j_page = ChromiumPage() # 接管当前页面 + j_page = ChromiumPage() # 接管当前页面 # 判定课程类别 if course_type == '必修': j_page.ele('@value=1').click() @@ -78,17 +89,23 @@ def auto_judge(course_id:str,course_type:str) -> None: j_page.ele('tag:a@@text():保存').click() time.sleep(1) pass + + # 实现自动评分 if not_judged: for i in not_judged: logger.info('正在对课程:{}进行评分'.format(i[0])) - auto_judge(i[0],i[1]) + auto_judge(i[0], i[1]) logger.success('已完成对课程:{}的评分'.format(i[0])) else: logger.info('没有需要评分的课程') # 实现题目答案显示 -def auto_quiz(course_id:str) -> None: + + +def auto_quiz(course_id: str) -> None: pass + + if not_quiz: for i in not_quiz: logger.info('正在获取课程:{}的答案'.format(i[0])) @@ -106,13 +123,13 @@ not_quiz = [] for k, v in new_cnt.items(): for i in v: if i[2] == '未评分': - not_judged.append((i[0],k)) - elif i[2] == '未答题': - not_quiz.append(i[0],k) + not_judged.append((i[0], k)) + elif i[2] == '未完成作业': + not_quiz.append(i[0], k) if not not_judged and not not_quiz: logger.warning('所有课程均已完成,页面即将关闭') page = ChromiumPage() page.close_tabs() else: subprocess.run(["python", __file__]) - exit() \ No newline at end of file + exit() diff --git a/single_course.py b/single_course.py index e1db538..f733e2c 100644 --- a/single_course.py +++ b/single_course.py @@ -4,7 +4,8 @@ import time from loguru import logger # 实现单个课程的刷课逻辑 -def one_course(cid:str,ctype:str,crate:int,again:bool=False): + +def one_course(cid: str, ctype: str, crate: int, again: bool = False): ''' cid: 课程id ctype: 课程类型 @@ -38,17 +39,18 @@ def one_course(cid:str,ctype:str,crate:int,again:bool=False): if tr.ele('tag:td').text.split('\t')[0] == cid: # 进入视频页面 tr.ele('tag:button@@text():进入学习').click() - cur_page.wait.new_tab(timeout=3) # 等待新标签页出现 - tab = cur_page.get_tab(cur_page.latest_tab) # 获取新标签页 + cur_page.wait.new_tab(timeout=3) # 等待新标签页出现 + tab = cur_page.get_tab(cur_page.latest_tab) # 获取新标签页 time.sleep(1) if crate == 100: print('当前课程已完成') cur_page.close_tabs(tabs_or_ids=[tab]) # 进入后,获得当前视频的完成率,决定操作方式 - if tab.ele('tag:a@@text():继续学习',timeout=2): + if tab.ele('tag:a@@text():继续学习', timeout=2): tab.ele('tag:a@@text():继续学习').click() else: - tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() + tab.ele( + 'c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() # 建立循环,检测当前视频是否完播 '''
@@ -78,7 +80,7 @@ def one_course(cid:str,ctype:str,crate:int,again:bool=False): # 每60秒先检测是否有视频播放完毕 try: - if tab.ele('tag:div@@text():本小结已经学习完,是否进入下一节?',timeout=2): + if tab.ele('tag:div@@text():本小结已经学习完,是否进入下一节?', timeout=2): tab.ele('tag:a@@text():是').click() except: pass @@ -86,15 +88,19 @@ def one_course(cid:str,ctype:str,crate:int,again:bool=False): # 有时候没有弹窗提示,用以下方式手动检测 for i in l: if i != 100: - tab.ele('#normalModel_nodeList').eles('tag:div')[l.index(i)+1].click() + tab.ele('#normalModel_nodeList').eles( + 'tag:div')[l.index(i)+1].click() time.sleep(1) try: - if tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path',timeout=2): - tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() + if tab.ele('c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path', timeout=2): + tab.ele( + 'c:#normalModel_video > xg-start > div.xgplayer-icon-play > svg > path').click() except: pass - time.sleep(60) # 每次监测间隔60秒 + time.sleep(60) # 每次监测间隔60秒 + + break # なぜここにbreakがいるのですか?あかしいなあ。 + - break # なぜここにbreakがいるのですか?あかしいなあ。 if __name__ == '__main__': - one_course('6992','培训',68) \ No newline at end of file + one_course('6992', '培训', 68)