分析蓝奏云下载直链!使用Python下载分享资源

【作者主页】:吴秋霖
【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作!
【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建与开发实战》
还有未来会持续更新的验证码突防、APP逆向、Python领域等一系列文章

1. 写在前面

  在很早之前我们做过一个针对论坛中分享安卓APK资源的采集项目。通过下面图片可以看到去广告、破解、内供、VIP…各种魔改的APP版本在论坛中层出不穷,如果说从安全的角度去思考,这些APK资源很有研究价值!

在这里插入图片描述

这些资源在论坛中主要通过第三方的存储介质(网盘、云盘)去分享与传播,并且链接地址将会以无序的方式嵌套在贴文内容当中!提取文本内容中的真实且有效的链接地址与密码,在早期使用的方式是基于规则,正则+特征的一个规则库去命中与识别!

那个时候没有GPT,现在处理这样的场景那可就简单了!!!

本期主要说说蓝奏云资源的下载链接获取(需要密码、多资源分享、单一资源分享)等多种情况的链接提取分析

后期有时间也会更新百度网盘跟天翼云盘的下载提取方式

庆幸的是我在写这篇文章的时候,所有涉及到的接口与参数跟以前相比并没有太大的变化!因为我是参考以前的代码去写的~~

在这里插入图片描述

在开始阅读这篇文章之前,请先看之前遇到过的坑,以免你恰巧也正在遇到,如下所示:

1、由于APK包寄存在云盘,直链存在是有时效性的(<10分钟)
2、网络检测那一步验证,可能会出现Sign参数校验错误,停留几秒重试几次即可通过参数验证

2. 单一文件提取

  这一类APK资源点击分享链接跳转,直接可以下载,它跟有密码提取的接口一致,参数不同区分,如下所示:

在这里插入图片描述

sign参数在响应的HTML代码中可获取到,其他参数为固定参数,所以基本上没有任何较大的难度,请求参数如下所示:

在这里插入图片描述

这里需要说一下的是,该接口请求响应的JSON数据中,需要提取dom、url两个字段拼接下一次请求的链接,响应数据如下所示:

{“zt”:1,“dom”:“https://developer-oss.lanzouc.com”,“url”:“?UjRWaF1sADEACQszUWQCbltkU2sCuAaBV/hSvFOMU+8A5gXbAfdV5wXcU4pU5wKNBtcB4lefBKZQvgOcUZ0G4VL+VqBd5gDBAOYLc1FkAnNbalNwAjsGbVc8UjFTUFM7AGQFbwFtVTIFalM8VDUCNQZrATNXLgRgUCQDOFE/BjVSY1Y3XTUAYABgC2hRIwJzW3FTawJvBjRXYVJtUyBTYwAxBX0BbVUwBXxTZ1QwAmUGZQEzVz0EMlBuA2dRaAZjUmZWN11mADcAZgs5UWMCZ1s5U24CPAYwV2dSYFNuU2oAMAViAT5VMQU2UytUYQJzBjcBIld9BHVQMgN3UWQGY1JvVjBdMABnAGMLaFEwAjdbJ1MiAjQGaVc1UjJTMlNjADcFYgFuVTIFZVM3VDICMwZqASpXJgQgUDEDaVF6BjpSY1Y2XTAAZgBlC2tRNAIyWzNTYwJ7BnFXIFIjUzJTYwA1BWUBb1U1BWtTNFQ3AjIGawEiV30Eb1AnAzhRPAY3UmRWL10zAGwAeAtsUTcCMlsvU2cCZAYw”,“inf”:0}

拼接方式需要加一个字符串file:os.path.join(dom, ‘file’, url)

拿到下一次请求的链接后,发起请求,会出现一个验证检测,这里需要点击触发才能继续后续下载操作,如下所示:

在这里插入图片描述

上图验证并下载的操作抓包分析一下,可以看到同样是一个Ajax的请求,sign参数同样在响应的HTML代码中可以拿到,file参数一样在HTML代码中可以获取,如下所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

拿到上述验证检测请求所需的参数后,接下来提交验证并下载的请求,即可通过验证,如下所示:

在这里插入图片描述

通过验证之后,接口响应的数据就包含最终APK资源的下载链接,直接提取即可,响应数据如下:

{“zt”:1,“dom”:null,“url”:“https://c1026.lanosso.com/df137b170d87e8a5968ef81693144f7c/65780215/2019/11/11/b0f97549bed46fc0dfd88a474a800b0e.apk?fn=%E5%85%A8%E8%83%BD%E6%89%AB%E6%8F%8F%E7%8E%8B%E6%97%A0%E9%99%90%E6%AC%A1%E6%95%B0.apk”}

还有另外一种页面,就是在点击云盘的分享链接后,会直接跳转到如下页面:

在这里插入图片描述

这样的情况只是页面类型不一样而已,到这一步直接拼接上面含file的链接直接请求,就会来到验证检测页面那一步

3. 多文件分享提取

  另外一种就是分享链接中含多个APK资源文件,它们都不一样,可能需要全部下载,如下所示:

在这里插入图片描述

首先它有一个更多文件加载的接口,我们抓包分析一下,如下:

在这里插入图片描述

这些参数同样在响应的HTML代码中可以获取到,如下所示:

在这里插入图片描述

截止目前,你会发现蓝奏云的参数并没有使用很难或者多复杂的加密算法,也没有相对严格的风控!唯一繁琐的就是流程较为多。多APK资源文件提取代码如下,仅供参考:

def get_first_match(self, pattern, text):
    match = findall(pattern, text)
    return match[0] if match else None

def get_more_apk(self, url, html, data: dict = {
    
    }):

    lx = self.get_first_match("'lx':(\\d{1})", html)
    fid = self.get_first_match("'fid':(\\d{7})", html)
    uid = self.get_first_match("'uid':'\\d{5}'", html)
    pgs = self.get_first_match("pgs =(\\d{1})", html)
    _k = self.get_first_match("'k':([0-9a-zA-Z]{6}),", html)
    _t = self.get_first_match("'t':([0-9a-zA-Z]{6}),", html)

    if _k and _t:
        k = self.get_first_match(
            "var {} = '(.*)';".format(_k), html)
        t = self.get_first_match(
            "var {} = '(.*)';".format(_t), html)

        data = {
    
    
            "lx": lx,
            "fid": fid,
            "uid": str(uid),
            "pg": pgs,
            "rep": '0',
            "t": t,
            "k": k,
            "up": 1,
            "vip": '0',
            "webfoldersign": ""
        }

    if data:
        moreapk_res = requests.post(
            'https://pan.lanzoub.com/filemoreajax.php',
            json=data,
            headers=self.headers
        ).json()

        _apk_json = moreapk_res.get('text', '')

        if isinstance(_apk_json, list):
            for _json in _apk_json:
                apk_info = {
    
    }
                icon = _json.get('icon', '')
                if icon == 'apk':
                    apk_info['url'] = urljoin(
                        self.host_url, _json['id'])
                    apk_info['title'] = _json['name_all']
                    apk_info['size'] = _json['size']
                    print(apk_info)

4. 密码登陆提取

  最后一种就是常见的需要提取码(密码)提取的资源,跟上面单一文件分享流程是一样的,只不过在第一步请求的时候有一个p参数,这个参数就是密码,如下所示:

在这里插入图片描述

sign参数同样能够在影响的HTML代码中拿到,如下所示:

在这里插入图片描述

提交上面携带密码参数的请求之后,就会进入到分享文件页面,然后重复上面的流程,先构造携带file的链接进行请求,之后过检测,最后接口响应的数据如下所示:

{“zt”:1,“dom”:“https://developer-oss.lanzouc.com”,“url”:“?BGJXaQ08Dz4BCFBoBzIHa1plUmpS6QC6CqBTsAfWUd4I71a/CdoHugn8UJlW6ga3Bu1UDlU/U2kHMwc3AW1bdARlV3ANOw99ATFQbwc/B2NaX1I+UmkAPwo/U2IHaVFpCDxWNAljB2QJeVBgVnEGOgZtVGBVOlNpBzgHNwFqW20EIldwDSAPZgFlUDYHYQc2Wi9SZ1I1AC0KPVNnB3RRYwhtVmUJMQc2CWZQZVZgBmQGaVQ3VW5TNQdmBzYBPFtoBGVXOQ1oDz0BZlAxB2YHN1o0UjVSPQA0Cm9TZgdsUX4IaVZxCT8HdQkqUHVWZwZ1BjVUNVU3U2AHNQc3AWpbbgQ9VzMNdg8vAT5Qawc2B2BaPVJmUjoAMgo/U2YHblFiCD9WNwliB30JcVAgVmQGawYrVGxVO1NmBzAHMAFuW2oEN1czDWEPYgFxUHMHIwdxWj1SZlI4ADsKO1NmB29RaAg8VjQJYQd1CSpQb1ZyBjoGbVRhVTxTfwczBzkBc1trBDZXMQ1+D2oBblAy”,“inf”:“\u4e2d\u534e\u7f8e\u98df\u8c31_58360.apk”}

5. 防盗链处理

  请求过程中会遇到可能会防盗链,主要就是为了保护资源跟控制流量,稍微处理一下,代码参考如下:

iframe_element = response.xpath("//div[@class='iframe']")
# 防盗链处理
if 'plugin.php' in response.url or iframe_element:
    share_link = response.xpath("//div[@class='iframe']//iframe/@src").extract_first()
    # 拿到真实链接地址重新请求
	yield scrapy.Request(
	    share_link,
	    callback=self.parse_handle,
	    meta=response.meta
	)

6. 下载分享资源

  这里对于APK资源的下载使用开源仓库YouTube-dl,代码参考如下:

def rename_hook(d):
   if d['status'] == 'finished':
        print(
            '====> APK Download Fnish. {}'.format(
                d.get(
                    'filename',
                    '')))
                    
def download(apk_link, apk_name):
    try:
        ydl_opts = {
    
    
            'outtmpl': '{}.apk'.format(apk_name),
            'progress_hooks': [rename_hook],
            'writeautomaticsub': True,
            'nocheckcertificate': True,
            'nooverwrites': True,
            'subtitleslangs': 'en',
            'logger': MyLogger(),
            'retries': 3,
            'socket_timeout': 60
        }
        with youtube_dl.YoutubeDL(ydl_opts) as ydl:
            rest = ydl.download([apk_link])
            if not rest:
                return True, ''
            else:
                return False, FileNotFoundError
    except Exception as e:
        return False, e

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

猜你喜欢

转载自blog.csdn.net/qiulin_wu/article/details/134944217