web逆向实战(三)-学习通-课程列表

目的

  • 获取个人空间的在学课程列表数据
  • 目标网址: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语法。
  • 免责声明:本文仅供学习和研究目的,禁止用于任何商业用途。读者在使用爬虫技术时需遵守相关法律法规,本文作者不对读者在使用爬虫技术时可能产生的任何法律风险负责。如有任何侵权或违法行为,请及时联系作者删除相关内容。

  • 如果读者使用了本人提供的脚本,因操作不当,导致账号被网站封禁,无法完成必修或选修课程,从而影响学分的取得,本人概不承担任何法律责任。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值