吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7458|回复: 21
收起左侧

[Python 原创] 【原创源码】【python】淘豆网文档下载探索

  [复制链接]
pinhai 发表于 2020-2-26 19:54
本帖最后由 pinhai 于 2020-2-26 23:13 编辑

一、引子
因发现有人悬赏下载淘豆网(taodocs.com)文档,之前看过python下载文泉的文档,就想试试看能不能用python下载淘豆网付费文档。

二、分析
以https://www.taodocs.com/p-55966379.html为例,浏览器为火狐。ctrl+shift+E打开开发工具-网络,刷新该页面,试一下“图像”选项,观察左侧请求,不难发现该页面里面加载的文档都是图片,分辨率810*1146,至此确定下载思路为下载每个页面的图片,最后合成为pdf格式。
01.jpg

三、探索
1.要想下载图片就必须知道图片地址,查看上图所点选的请求,发现消息头为https://file.taodocs.com:808/img/Hj5pnzEjlNUzKb8@8S9qCO38LfhgpL2T,非常简单,前半部分为服务器地址https://file.taodocs.com:808/img/,后面为一个字符串,查看图片地址问题简化为查找字符串生成方式。多次打开该页面,发现针对同一个页面,该字符串是固定不变的,更进一步简化了探索过程。通过调试器查找该字符串,没有结果,也正常,如果能在源码中找到该字符串,这个问题也过于简单了。
02.jpg

2.既然在源码中没有,那应该是从服务器动态获取的,重新翻看各个请求,发现这样一个请求
https://file.taodocs.com:808/?from=pc_55966379&furl=lBk9LJ9uXl6xoMR8lbVBog==&callback=jQuery112405711252286986038_1582691611656&_=158269161165,其响应结果为

[JavaScript] 纯文本查看 复制代码
jQuery112405711252286986038_1582691611656({"imgs":["i8iHNYeTqVJnoWn94KhuiUcGAbR7NkEda7Pz/A2BXR6Klbsjxc6VBFlNSo2v+E+gPbaY0kGjILRUfWGVklmq1Q==","i8iHNYeTqVJnoWn94KhuiUcGAbR7NkEda7Pz/A2BXR5qt+SMkv+qjTc0lEgGxV7hMMSI+gTcr2AiNP8TFOBijg==","i8iHNYeTqVJnoWn94KhuiUcGAbR7NkEda7Pz/A2BXR7A4Dh7vPZP21hM7cvADzC9TKG2FdbWuk9LnmXlFAkXgg=="],"next":"lBk9LJ9uXl59juySZznxSh6QvU@bBUhr","pageNum":10,"ts":28.779500000000002});
其中imgs标签很可疑,但不是地址,可能经过了加密。翻看代码,发现(其实找了好久)js代码中对imgs变量进行了一个处理,处理函数是EiePQRNA,查看定义为:

03.jpg
[JavaScript] 纯文本查看 复制代码
function EiePQRNA(_0x2abb91) { var _0x53a94f = { 'ZWphd': '**********' }; var _0x2d16f9 = _0x53a94f['ZWphd']; var _0x6048e2 = L8LXdspqSjEiePQRNA['AES']['decrypt'](_0x2abb91, L8LXdspqSjEiePQRNA['enc']['Utf8']['parse'](_0x2d16f9), { 'mode': L8LXdspqSjEiePQRNA['mode']['ECB'], 'padding': L8LXdspqSjEiePQRNA['pad']['Pkcs7'] })['toString'](L8LXdspqSjEiePQRNA['enc']['Utf8']); return _0x6048e2; }

可见加密方式为AES,加密模式为ECB,秘钥也是明文,在此隐去了,没有偏移量,拿到在线解密网站试一下,结果正是我们要找的图片地址。

04.jpg

好了,既然图片地址找到了,我们就要构造请求了,看上述请求发现,55966379容易,就是文档的编号,在网址中可以方便接取,furl是什么?我们需要看一下,重新看上述请求的响应,除了imgs保存了加密过的图片地址外,还有一个next参数,长度和我们furl长度一致,理解一下next,就是下一个的意思,再看imgs中只存了3个地址,可以猜想到网页是分段加载的,next中存储的正是下一个请求的furl参数。这样就串起来了,只要构造出第一个reuqest,后面就可以递归调用了。那么第一个request如何构造呢?

3.继续翻看网络请求,发现第一个涉及获取图片地址的请求和后面的请求别无二致,也有furl参数,那么他的furl从哪里来呢?看到https://www.taodocs.com/showProduct.aspx?fn=docinfo&id=55966379请求比较可疑,他返回了一个参数,叫nextPageStr,将他带入获取图片地址请求中(callback和_参数不管),利用重发功能重新发起请求,发现可得正常响应。

05.jpg

4.至此,我们理顺了网站加载所有文档页面的过程:

①使用https://www.taodocs.com/showProduct.aspx?fn=docinfo&id=55966379获取nextPageStr。

②使用nextpagestr作为furl构造https://file.taodocs.com:808/?from=pc_55966379&furl=lBk9LJ9uXl6xoMR8lbVBog==&callback=jQuery112405711252286986038_1582691611656&_=158269161165获取图片地址imgs和next参数,imgs通过json解包并通过EiePQRNA函数解密后获取图片实际地址下载显示。

③使用next参数作为下一个请求的furl,直到next为空,结束请求。

5.题外话,第一次分析时,该网站的请求图片请求并不是发送到https://file.taodocs.com:808,而是https://view.taodocs.com:808,并且返回的imgs也是明码,没有加密,要更加容易一些,试验代码也是基于https://view.taodocs.com:808的,等我要来写这篇帖子时发现不一样了,黑人问号脸 ??,害我又找了半天。ps,view.taodocs.com:808依然可用,且无需解密。

四,实践

啥也别说了,撸代码(header直接从firefox中复制)
[Python] 纯文本查看 复制代码
import requests
import time
import base64
from Crypto.Cipher import AES
headers1 = {
'Host': 'file.taodocs.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Referer': 'https://www.taodocs.com/p-107648150.html',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
}
headers2={'Host': 'www.taodocs.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Referer':'https://www.taodocs.com/p-107648150.html',
'Cache-Control': 'max-age=0',
'TE': 'Trailers',}
def getimgs(url):
    pid = url.split('-')[1][:-5]#截取pid
    print(pid)
    response=requests.get('https://www.taodocs.com/showProduct.aspx?fn=docinfo&id=' + pid, headers=headers2)
    nextstr = response.json()['nextPageStr']#获取第一个nextstr
    title = response.json()['data'][0]['Title']#获取文档标题
    print(title)
    imglist=[]
    i=1
    while(nextstr):#循环获取nextstr,直到nextstr为空
        url2='https://file.taodocs.com:808/?from=pc_'+pid+'&furl='+nextstr#构造请求        
        response1 = requests.get(url2, headers=headers1).json()        
        try:
            imglist=response1['imgs']#获取imgs            
        except:
            print("=================================wait===================================")
            time.sleep(30)#遇错后延迟,主要是服务器有时间间隔限制
            response1 = requests.get(url2, headers=headers1).json()
            imglist=response1['imgs']       
        for img in imglist:
            imgjiemi=aes_decode(img, '*********')#解密,这里我把秘钥隐去了
            url = 'https:' + imgjiemi
            print(url)
            response = requests.get(url)
            imgbody = response.content
            with open('e:/1/' + title+str(i+imglist.index(img) )+ '.jpg', 'wb') as f:
                f.write(imgbody)#下载保存,没有合成pdf,主要是累了
        i=i+len(imglist)
        nextstr=response1['next']        
        
def aes_decode(data, key):#解密函数
    try:
        aes = AES.new(str.encode(key), AES.MODE_ECB)  # 初始化加密器
        decrypted_text = aes.decrypt(base64.decodebytes(bytes(data, encoding='utf8'))).decode("utf8")  # 解密
        decrypted_text = decrypted_text[:-ord(decrypted_text[-1])]  # 去除多余补位
    except Exception as e:
        print(e)
    return decrypted_text
urltoStart='https://www.taodocs.com/p-55966379.html'
getimgs(urltoStart)

06.jpg

六、总结

这个帖子是我来到吾爱的第一个帖子,费了不少劲,python也是纯自学,请各位前辈多多鼓励!
写这个帖子一是分享,二是记录学习过程,希望不足之处,各位帮助提高!

免费评分

参与人数 6吾爱币 +8 热心值 +6 收起 理由
0衰衰0 + 2 + 1 用心讨论,共获提升!
QQQRRR + 1 + 1 用心讨论,共获提升!
cooldgf + 1 + 1 用心讨论,共获提升!
suoliweng + 1 + 1 谢谢@Thanks!
知意执意 + 1 热心回复!
wushaominkk + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

风在此停止 发表于 2020-3-19 00:47
本帖最后由 风在此停止 于 2020-3-19 01:12 编辑

楼主你好我找到了我的EiePQRNA定义:

function EiePQRNA(_0x2abb91) {
var _0x53a94f = { 'ZWphd': '1234567812345678' };
var _0x2d16f9 = _0x53a94f['ZWphd'];
var _0x6048e2 = L8LXdspqSjEiePQRNA['AES']['decrypt'](_0x2abb91, L8LXdspqSjEiePQRNA['enc']['Utf8']['parse'](_0x2d16f9), { 'mode': L8LXdspqSjEiePQRNA['mode']['ECB'], 'padding': L8LXdspqSjEiePQRNA['pad']['Pkcs7'] })['toString'](L8LXdspqSjEiePQRNA['enc']['Utf8']);
return _0x6048e2; }
请问密码就是1234567812345678吗?
还有你的在线解密网站是什么?我百度的好像不好使。
我的第一页密文是:
jQuery1124011299194684837466_1584549001674({"imgs":["n865nL8mjQYiYc0y3+sfNps0MJaelT/I/y/dtjX5/t99d4gF1A4UE+b0znDl9TWdrx4/L9iiHpHoBKV1E0ytNA==","n865nL8mjQYiYc0y3+sfNps0MJaelT/I/y/dtjX5/t9RP4BrwAXdRjVGuxTCw/wQfHkiAAkSWMKP8fhdNDogpg==","n865nL8mjQYiYc0y3+sfNps0MJaelT/I/y/dtjX5/t9uRrX8frb8Qf0CCim2iUYxoskg6a784enn+hN1wg1t0A=="],"next":"@HSlfKLl6OOPEq9pzTs9GmW5foLT01Bx","pageNum":101,"ts":29.686700000000002});

但我不知道它怎么解密出:sSBsJQxhv6_H0BtpFfEin_Knuq6cm1Nk



已解决:http://tool.chacuo.net/cryptaes
chensure 发表于 2020-2-26 22:26
 楼主| pinhai 发表于 2020-2-27 08:06
godmodel 发表于 2020-2-27 10:56
感谢分享
vagrantear 发表于 2020-2-27 12:23
学习了 谢谢
知意执意 发表于 2020-2-27 12:57
感谢分享
虎虎生威 发表于 2020-2-27 15:38
小白怎样才能用上?请教
 楼主| pinhai 发表于 2020-2-27 16:09
虎虎生威 发表于 2020-2-27 15:38
小白怎样才能用上?请教

如果是页数少的,可以直接在浏览器网络调试里面找到对应的图片下载即可。页数多的话,1要安装python,2要安装pip包,3要安装requests和cypto包,4要找到密钥(在网页的源码中)替换源码中的密钥,5将源码中的urltostart换成你需要下载的网址,再运行就可以了。看起来很麻烦,但都可以百度出来,再有不懂还可以一起讨论。
其实分享这个主要是为了分享分析网站的过程,就像解开一个网站开发者打包好的神秘礼物一样,不是为了最后的文档。
如果只是为了1份文档,不需要以上这么麻烦,直接在悬赏区悬赏就可以了,自有人为你下载好。多谢回复。
虎虎生威 发表于 2020-2-27 16:26
pinhai 发表于 2020-2-27 16:09
如果是页数少的,可以直接在浏览器网络调试里面找到对应的图片下载即可。页数多的话,1要安装python,2要 ...

谢谢大哥,我要晕倒
zero66 发表于 2020-2-28 13:33
不错,学习下。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 01:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表