本文仅用于技术交流,不得以危害或者是侵犯他人利益为目的使用文中介绍的代码模块,若有侵权请练习作者更改。
网站链接:
aHR0cHM6Ly93d3cuc2h1cWkuY29tLw==
分析加密
开始的时候直接进入小说正文,打开抓包工具,直接进行检索。我们会发现这是一个ajax请求发送。
我们查看请求参数,只有这个看起来像是加密过的,我们直接搜索这个sign
这里边有几个sign,我们依次查找。这里我直接明说吧,最下面的就是结果。但是我还是想按流程给大家跑一下,这样我们面对不同场景的话可以有着自己的分析。
开始调试js代码
打开第一个,打上断点,开始调试。
但是你会发现,就算你刷新页面或者是拉到下一章节,他都没有进入调试状态,那么这个加密可能不是我们需要的网络请求中的一个,先筛出他
打开第二个,打上断点,开始调试。
和第一个一样的情况,依旧没有进入调试状态,那么这一个也不是正文请求中携带的参数,现在开始第三个。
同样如此,依旧摒弃
但是我们注意到下方有很多个sign,并且是已经赋值的,现在打开其中的第一个。这不就是请求中的参数吗,打工搞成,我们呢现在只需要把这个html页面获取之后进行解析然后就可以解决了。
现在开始解析这个位置,可以通过多种手段,这里我采用的正则
import requests
import json
from lxml import etree
import re
import execjs
headers = {
'authority': 'www.aliwx.com.cn',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
}
url = "https://www.shuqi.com/reader?bid=7969805&cid=1187207"
html = requests.get(url).text
a_str = re.findall(re.compile(r'dataChapters">(.*?)</i>', re.S), html)[0]
data_info = str(a_str).replace('"', '"').replace('true', 'True').replace('false', 'False').replace('amp;', '')
item = eval(data_info)
data_list = item['chapterList']
info = {
volumedata['volumeName']: {
chapterdata['chapterName']: chapterdata['contUrlSuffix'] if chapterdata['isFreeRead'] else None
for chapterdata in volumedata['volumeList']
}
for volumedata in data_list
}
for volumeName, item in info.items():
for chapterName, url_suffix in item.items():
if url_suffix:
print(f'当前进度: {volumeName}, {chapterName}')
url = f'https://c13.shuqireader.com/pcapi/chapter/contentfree/{url_suffix}'
results = requests.get(url, headers=headers).json()
encrypt_data = results['ChapterContent']
else:
print(f'收费章节: {volumeName}, {chapterName}')
break
获得到这个加密数据的话,我们现在需要对正文进行解密,这是代码运行之后的结果,解密的话还是比较简单的。
直接搜索这个,找到文件点击进入
这边我们发现这个加密后的参数是再这个函数中的,所以可以确定这个函数就是加密参数
开始扣这个函数
扣下来改一下格式
function dt(t) {
return t = function(t) {
return t.split("").map(function(t) {
var e, i;
return t.match(/[A-Za-z]/) ? (e = Math.floor(t.charCodeAt(0) / 97),
i = (t.toLowerCase().charCodeAt(0) - 83) % 26 || 26,
String.fromCharCode(i + (0 == e ? 64 : 96))) : t
}).join("")
}(t),
function(t) {
var e, i, a, n, r, c, o, s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", d = "", l = 0;
for (t = t.replace(/[^A-Za-z0-9\+\/\=]/g, ""); l < t.length; )
n = s.indexOf(t.charAt(l++)),
r = s.indexOf(t.charAt(l++)),
c = s.indexOf(t.charAt(l++)),
o = s.indexOf(t.charAt(l++)),
e = n << 2 | r >> 4,
i = (15 & r) << 4 | c >> 2,
a = (3 & c) << 6 | o,
d += String.fromCharCode(e),
64 != c && (d += String.fromCharCode(i)),
64 != o && (d += String.fromCharCode(a));
return function(t) {
for (var e, i = "", a = 0, n = 0, r = 0; a < t.length; )
n = t.charCodeAt(a),
n < 128 ? (i += String.fromCharCode(n),
a++) : n > 191 && n < 224 ? (r = t.charCodeAt(a + 1),
i += String.fromCharCode((31 & n) << 6 | 63 & r),
a += 2) : (r = t.charCodeAt(a + 1),
e = t.charCodeAt(a + 2),
i += String.fromCharCode((15 & n) << 12 | (63 & r) << 6 | 63 & e),
a += 3);
return i
}(d)
}(t)
}
function main(data){
return dt(data)
}
与python联立,解析并输出密文内容
import requests
import json
from lxml import etree
import re
import execjs
headers = {
'authority': 'www.aliwx.com.cn',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
}
url = "https://www.shuqi.com/reader?bid=7969805&cid=1187207"
html = requests.get(url).text
a_str = re.findall(re.compile(r'dataChapters">(.*?)</i>', re.S), html)[0]
data_info = str(a_str).replace('"', '"').replace('true', 'True').replace('false', 'False').replace('amp;', '')
item = eval(data_info)
data_list = item['chapterList']
info = {
volumedata['volumeName']: {
chapterdata['chapterName']: chapterdata['contUrlSuffix'] if chapterdata['isFreeRead'] else None
for chapterdata in volumedata['volumeList']
}
for volumedata in data_list
}
for volumeName, item in info.items():
for chapterName, url_suffix in item.items():
if url_suffix:
print(f'当前进度: {volumeName}, {chapterName}')
url = f'https://c13.shuqireader.com/pcapi/chapter/contentfree/{url_suffix}'
results = requests.get(url, headers=headers).json()
encrypt_data = results['ChapterContent']
ts = str(execjs.compile(open('D:\桌面\pythoncode\书旗小说逆向\书旗小说.js', 'r', encoding='utf-8').read()).call('main',encrypt_data))
print(ts)
else:
print(f'收费章节: {volumeName}, {chapterName}')
break
输出结果
成功解决,点赞再走吧!
标签:逆向,item,url,chapterdata,js,获取,import,replace,data From: https://blog.51cto.com/u_16426526/9143883