目的
- 获取个人空间的在学课程列表数据
- 目标网址:aHR0cHM6Ly9pLmNoYW94aW5nLmNvbS9iYXNl
过程
找对请求接口
-
在xhr中确定了课程的内容返回的请求,可在返回数据中直接搜索页面上存在的关键字眼。如下图:
-
然后请求重放,能返回同样的值,然后剔除不需要的值。剔除完后,在python中进行复现。
Pyhton请求复现报错
报错:requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
- 一开始以为是代理有问题,然后改为直连后问题依旧。
- 既然reqable能重放成功,那python为啥不行。后面想到是不是请求时候auto改用了http2协议通信的问题,结果是指定http1.1也能正常返回结果。
- 后面想起python还有tls指纹问题,然后我就用curl_cffi库修改了urllib3中对于某些浏览器啥的信息的加密算法调用顺序(我自己是这样理解的,有错的话请大家多多包涵并指教)。
- 然后就可以正常返回数据了。
cookie出处
- 其实这20来个cookie,都是来自学习通服务器返回的,如下图:
- 第一次/fanyalogin请求返回。
- 第二次/base返回。
- 最后在第三次请求把/base请求后的cookie复制出来,与刚刚在requable复现的cookie进行文本比对,看看有没有遗漏的值。笔者使用notepad++中的插件jstool格式化和compare文本对比,如下图:
- 发现全都是服务器返回的,没有本地生成的值…
- 所以最后提取个在学课程内容就结束了吧。
源码
from curl_cffi import requests
from lxml import etree
import urllib3
import execjs
import time
urllib3.util.ssl_.DEFAULT_CIPHERS = ":".join(
[
# "ECDHE+AESGCM",
# "ECDHE+CHACHA20",
# "DHE+AESGCM",
# "DHE+CHACHA20",
# "ECDH+AESGCM",
"DH+AESGCM",
"ECDH+AES",
"DH+AES",
"RSA+AESGCM",
"RSA+AES",
"!aNULL",
"!eNULL",
"!MD5",
"!DSS",
]
)
def get_html(username, password, isProxy, Port):
"""
目的:学习通登录并返回个人页面的课程列表页内容
"""
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
cookies = {}
data = {
'uname': '',
'password': '',
'refer': 'https%3A%2F%2Fi.chaoxing.com',
't': 'true',
}
# 代理
proxies = {} if not isProxy else {
'http': f'http://127.0.0.1:{Port}',
'https': f'http://127.0.0.1:{Port}',
}
# 该秘钥在加密函数入口处上方
aeskey = "u2oh6Vu^HWe4_AES" # arg1 aes加密秘钥写死,后面可能要改
# 导入加密函数文件
with open('./xxt.js', 'r', encoding="utf-8") as f:
js_code = f.read()
# 编译js代码
code = execjs.compile(js_code)
# js代码执行
encoded_username = code.call("encryptByAES", username, aeskey)
encoded_password = code.call("encryptByAES", password, aeskey)
# 修改payload中的值
data["uname"] = encoded_username
data["password"] = encoded_password
print(f"加密后的账户名 ------->>> {encoded_username}")
print(f" 加密后的密码 ------->>> {encoded_password}")
# 建立session会话
session = requests.Session()
# 第一次请求返回固定值: 'https%3A%2F%2Fi.chaoxing.com%2F' ,其实就是经过了uri编码,encodeURIComponent("https://i.chaoxing.com/")
session.post('https://passport2.chaoxing.com/fanyalogin', headers=headers, cookies=cookies, data=data, proxies=proxies)
# 第二次请求重定向可加可不加
# second_response = session.get("https://i.chaoxing.com/", headers=headers, cookies=cookies, data=data)
# 第三次请求返回数据仅可获取个人空间少部分数据,课程数据在另一个ajax请求返回.所以也不需要加上了
# timestamp = int(time.time()*1000)
# third_response = session.get(f"https://i.chaoxing.com/base?t={timestamp}", headers=headers, cookies=cookies, data=data)
# payload参数修改
data = {'courseType': '1'}
response = session.post("https://mooc1-1.chaoxing.com/mooc-ans/visit/courselistdata", headers=headers, cookies=cookies, data=data, impersonate='chrome101', proxies=proxies)
return response.text
def data_extract(tags):
"""
目的:使用xpath在中获取课程列表
"""
# 解析为html对象
tags = etree.HTML(tags)
# 使用xpath获取课程列表数据
course_lst = tags.xpath("//ul[@id='courseList']//li//span/text()")
print(course_lst, "\n", f"你目前在学的有: {len(course_lst)} 门课程")
if __name__ == "__main__":
print("*******************************************>>>> 记得要修改默认的账号和密码 <<<<*************************************************************")
# 输入你的用户名和密码
username = "12345678910"
password = "123456"
# isProxy标识是否使用代理,Port为代理端口,默认不使用。若要使用代理访问网页,请设置为True,代理默认使用7890端口
isProxy = False
Port = 7890
tags = get_html(username, password, isProxy, Port)
course_list = data_extract(tags)
const CryptoJS = require("crypto-js");
function encryptByAES(message, key){
let CBCOptions = {
iv: CryptoJS.enc.Utf8.parse(key),
mode:CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
};
let aeskey = CryptoJS.enc.Utf8.parse(key);
let secretData = CryptoJS.enc.Utf8.parse(message);
let encrypted = CryptoJS.AES.encrypt(
secretData,
aeskey,
CBCOptions
);
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}
// console.log(encryptByAES("12345678910", "u2oh6Vu^HWe4_AES"));
总结
- 本章节主要是练习下常规爬虫流程和xpath语法。
-
免责声明:本文仅供学习和研究目的,禁止用于任何商业用途。读者在使用爬虫技术时需遵守相关法律法规,本文作者不对读者在使用爬虫技术时可能产生的任何法律风险负责。如有任何侵权或违法行为,请及时联系作者删除相关内容。
-
如果读者使用了本人提供的脚本,因操作不当,导致账号被网站封禁,无法完成必修或选修课程,从而影响学分的取得,本人概不承担任何法律责任。