学霸的烦恼
试想这样一个场景:一个经过第一轮集中采摘的苹果园,每棵树的枝条上必然或多或少剩下些果子。而采摘工每次采摘时都要从第一棵树摘起,哪怕第一棵树上已经没有果子了。今天收工了,明天又要从第一棵树开始,是不是很让人崩溃?
XX学里的课程学习现在就是这种样子。
拥有上万门各类课程的XX学,对打工人来说简直就是知识的海洋。但是这个站的界面在用户友好度方面还有点瑕疵。目前该站上线的课程有8432门,每个网页显示20门课,共有422个页面,每学完一课,在课程的缩略图上会显示“已完成”。
课程页面的下边是页面跳转,初始是
的样子,点击3,就会变成
依此类推,6以后,将显示前三页和后三页,
直到< 1 2 3 … 420 421 422 >。没有跳转到指定页的功能倒也忍了,最让人不可忍受的是:如果这时候刷新页面,那就会直接跳转到最初< 1 2 3 > 的样式,也就是前面的翻页白翻了,一切重新开始。
早些年完成的课程比较少而且课程总数也不多的时候,基本上只会看前几页的内容,如果时间充裕了,则会往后面多翻几页,看看遗漏的课程。但是现在不一样了,由于课程增加的速度很快,而且完成的课程数量也多了起来,开始迈进学霸级别,导致后面页码中的未学课程欠账越来越多。如果能增加指定页面跳转功能,或者增加个筛选功能,可以把未完成的课程筛选出来,显示到前面的页面,效果就会好多了。
当然这对学渣不是问题,毕竟前面几页的内容都没学完,哈哈哈哈…
野生程序员的解决办法
尝试和客服来回了几次邮件沟通,最终得到的答复是:程序人员说了,页面是按照模块刷新,因此改不了。
没办法,只好自己动手解决问题了。折腾了一天,折腾出一个油猴脚本。在主页上手动增加一个按钮,每点击一次,可以爬取当前页面的课程明细,包括课程名称、学分、学时、完成情况。每一课的信息保存成一个对象,格式如{name:“XX课”,score:“共1学时”,status:“已完成”},然后将这个对象放入到一个数组中,最后将这个数组保存成一个以当前页面为文件名的文本文件。自动跳转到下一页,再点击按钮,就会重复上面的动作。这样点400多下,会生成400多个文本文件。再用python写个小脚本,将所有信息汇总到一个Excel表格中。
上代码:
(function() {
'use strict';
// Your code here...
// 定义一个函数getInfo,抓取当前页的课程明细,并保存为文本文件。
function getInfo() {
let div = document.querySelectorAll("li.list-item");
let courses = [];
for (let i = 0; i < div.length; i++) {
const a = {
name: div[i].querySelector(".text-overflow.title").innerText,
score: div[i].querySelector("div.course-chapter").innerText,
status: div[i].querySelector(".study-status")
? div[i].querySelector(".study-status").innerText
: "",
};
courses.push(a);
}
console.log(courses);
let data = new Blob([JSON.stringify(courses)], {
type: "text/plain;charset=utf-8",
});
let pageNumber = document.querySelector('.pagination div.active').innerText
let e = document.createElement("a");
e.href = URL.createObjectURL(data);
e.download = `${pageNumber}.txt`;
document.body.appendChild(e);
e.click();
document.body.removeChild(e);
document.querySelector('div[data-dir="next"]').click()
}
//在网页右上角新增一个按钮,用来决定是否对当前页进行抓取
let btn = document.createElement("button");
btn.innerHTML = "抓一抓";
btn.style.position = "fixed";
btn.style.top = "10px";
btn.style.right = "10px";
btn.style.backgroundColor = "red";
btn.style.color = "white";
btn.style.fontSize = "20px";
btn.style.borderRadius = "10px";
btn.style.padding = "10px";
btn.style.textAlign = "center"
btn.style.lineHeight = "1"
btn.style.zIndex = 9999
btn.onclick = getInfo;
document.body.appendChild(btn);
})();
合并文本文件的Python代码比较简单,首先把所有文本文件放到一个文件夹里,我的是course
import os
import pandas as pd
# 遍历course文件夹下的所有TXT文件
txt_files = [f for f in os.listdir('course') if f.endswith('.txt')]
data_list = []
# 读取每个TXT文件中的大数组并将对象转换为字典
for txt_file in txt_files:
with open(os.path.join('course', txt_file), 'r', encoding='utf-8') as f:
content = f.read()
data_list.extend(eval(content))
# 将列表转换为DataFrame
df = pd.DataFrame(data_list)
# 将DataFrame保存为Excel文件
df.to_excel('output.xlsx', index=False, header=True)
汇总422个文件用时十来秒,输出为output.xlsx,最后对表格调调格式就完成了。用Excel筛选功能,选出未完成的课程,到XX学主页里搜索,然后直达课程学习页面,爽得很。每隔几个月运行一下脚本更新,以便掌握最新数据,所谓求人不如求己,用在此处十分应景。