吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 908|回复: 5
收起左侧

[Python 原创] 某图君sign破解

[复制链接]
hk137 发表于 2026-4-15 12:23
在遨游的时候发现了几张图片很好看,准备下载下来,
然后发现不是高清图,
后续发现原图在某图君
然后开始了爬行之路

__APP__.wxapkg 解密一下

function s(e)   e这个传入的参数为
获取微信 access_token 返回的 token

COMMON_E_PARAM说明: miniwechat/v1/shentujun/getOpenid 返回的 token 替换进去

COMMON_openid说明: miniwechat/v1/shentujun/getOpenid 返回的 openid替换进去


[Python] 纯文本查看 复制代码
import os
import time
import random
import requests
import json
import traceback
from pathlib import Path

# ===================== 神图君 =====================

# 全局公用 e_param
COMMON_E_PARAM = "自行抓取"
COMMON_openid  = "自行抓取"

# === 签名逻辑 ===
def sign_system(e: str) -> str:
    """
    函数的签名生成逻辑
    """

    timestamp = str(round(time.time()))  
    e = e + "###" + timestamp

    # __APP__.wxapkg 解密 里面的 app-service.js 
    t = "PXhw7UT1B0a9kQDKZsjIASmOezxYG4CHo5Jyfg2b8FLpEvRr3WtVnlqMidu6cN"
    i = "" 

    for char in e:
        o = t.find(char)

        if o == -1:
            s_char = char
        else:
            s_char = t[(o + 3) % 62]

        n = int(62 * random.random())
        d = int(62 * random.random())

        i += t[n] + s_char + t[d]

    return i

# === headers ===
def get_common_headers(sign):
    return {
        "Host": "stapi.youpengw.com",
        "Connection": "keep-alive",
        "xweb_xhr": "1",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11)XWEB/14315",
        "sign": sign,
        "Content-Type": "application/json",
        "Accept": "*/*",
        "Sec-Fetch-Site": "cross-site",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Dest": "empty",
        "Referer": "https://servicewechat.com/wxba7de3a24a3ff4d5/105/page-frame.html",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "zh-CN,zh;q=0.9"
    }


# === 获取搜索列表 ===
def request_album_photoList(homepage_id):
    
    url = "https://stapi.youpengw.com/miniwechat/v1/shentujun/photoList"

    # token
    e_param = COMMON_E_PARAM
    
    # 初始化变量
    all_data = []
    page = 1
    limit = 30  # 这里必须和接口保持一致!!!
    max_pages = 50

    while page <= max_pages:
        try:
            # 每次重新生成时间戳 + 签名(关键!)
            import time
            timestamp = int(time.time() * 1000)
            sign = sign_system(e_param)
            
            params = {
                "homepage_id": homepage_id,
                "classify_id": 0,
                "sort_type": "default",
                "album_id": -2,
                "uid": 990439,
                "page": page,
                "limit": limit,  # 统一
                "id": 0,
                "action": "cover",
                "version": 1,
                "appid": "wxba7de3a24a3ff4d5",
                "openid": COMMON_openid,
                "timestamp": timestamp
            }

            # 请求头
            headers = get_common_headers(sign)

            response = requests.post(url, headers=headers, json=params, timeout=20)
            result = response.json()

            # 请求失败直接结束
            if result.get("code") != 1 or not result.get("data"):
                print(f"&#10060; 第{page}页请求失败或无数据,结束翻页")
                break

            current_page_data = result["data"].get("photoList", [])
            
            # 关键:当前页没有数据 → 结束翻页
            if not current_page_data:
                print(f"&#9989; 第{page}页无数据,全部爬取完毕")
                break

            all_data.extend(current_page_data)
            print(f"&#9989; 第{page}页:获取到 {len(current_page_data)} 条,累计 {len(all_data)} 条")

            page += 1
            time.sleep(0.5)

        except Exception as e:
            print(f"&#10060; 第{page}页异常:{str(e)}")
            break


    # 解析出所有的URL
    classify_id = all_data[0].get("classify_id")
    
    # print(classify_id)
    # print(all_data)
    # exit()

    # classify_id=1 视频  classify_id=5 图片 classify_id=7 链接   classify_id=10 集合

    if classify_id == 10:
        return classify_id    
        
    else:
        
        # 解析出所有视频URL
        video_urls = []
        for item in all_data:

            # 用ID作为文件名,避免重复
            video_id  = item.get("id") 
            video_url = item.get("video_url") or item.get("url")
            if video_url:
                video_urls.append({
                    "id": video_id,
                    "url": video_url
                })
        
        print(f"&#9989; 成功获取 {len(video_urls)} 个视频下载链接")
        return video_urls
    

# === 获取搜索 ===
def request_album_search(keyword):
    
    url = "https://stapi.youpengw.com/miniwechat/v1/shentujun/search"

    # token
    e_param = COMMON_E_PARAM

    sign = sign_system(e_param)
    
    params = {
        "search_code":keyword,
        "version":1,
        "action":"homepageinfo",
        "appid":"wxba7de3a24a3ff4d5",
        "openid":COMMON_openid,
        "timestamp":1776152477228
    }

    # 请求头
    headers = get_common_headers(sign)
    
    response = requests.post(
        url=url,
        headers=headers,
        json=params,
        timeout=20,
    )
    result = response.json()

    # print(result)
    # exit()

    if result.get("code") == 1 and result.get("data"):
        homepage_id = result["data"].get("homepage_id", [])

        # print(result)
        # exit()

        photoList = request_album_photoList(homepage_id)
        return photoList
    else:
        msg = result.get("msg")
        print(msg)
        exit()


# === 获取集合列表 ===
def request_album_list():
    
    session = requests.Session()
    session.trust_env = False  
    # 禁用代理
    
    url = "https://stapi.youpengw.com/miniwechat/v1/brand/albumList"

    # token
    e_param = COMMON_E_PARAM
    sign = sign_system(e_param)
    
    # 接口参数
    params = {
        "brand_id":"1",
        "page":1,
        "limit":20,
        "version":1,
        "appid":"wxba7de3a24a3ff4d5",
        "openid":COMMON_openid,
        "timestamp":1776152477228
    }
    
    # 请求头
    headers = get_common_headers(sign)

    response = session.post(
        url=url,
        headers=headers,
        json=params,
        timeout=20,
    )
    result = response.json()
    return result

# === 获取详细 ===
def request_album_find(id):
    
    session = requests.Session()
    session.trust_env = False  
    # 禁用代理
    
    url = "https://stapi.youpengw.com/miniwechat/v1/brand/albumImageList"

    # token
    e_param = COMMON_E_PARAM
    sign = sign_system(e_param)
    
    # 接口参数
    params = {
        "brand_id":2,
        "homepage_id":"2550841",
        "album_id":id,
        "appid":"wxba7de3a24a3ff4d5",
        "openid":COMMON_openid,
        "page":1,
        "limit":24,
        "version":1,
        "timestamp":1776151154843,
    }
    
    # 请求头
    headers = get_common_headers(sign)
    
    try:
        response = session.post(
            url=url,
            headers=headers,
            json=params,
            timeout=20,
        )
        result = response.json()
        
        # 解析出所有视频URL
        video_urls = []
        if result.get("code") == 1 and result.get("data"):
            photo_list = result["data"].get("photoList", [])
            for item in photo_list:
                video_url = item.get("url")
                video_id = item.get("id")  # 用ID作为文件名,避免重复
                if video_url and video_url.endswith(".mp4"):
                    video_urls.append({
                        "id": video_id,
                        "url": video_url
                    })
        print(f"&#9989; 成功获取 {len(video_urls)} 个视频下载链接")
        return video_urls
    
        
    except Exception as e:
        return {
            "status": "error",
            "msg": f"请求失败:{str(e)}",
        }

# === 下载文件 ===
def download_video(video_info,title):
    """
    下载单个视频
    :param video_info: 包含id和url的字典
    :param save_dir: 保存目录(自动创建)
    """
    session = requests.Session()
    session.trust_env = False  
    # 禁用代理

    video_id  = video_info["id"]
    video_url = video_info["url"]

    file_ext = os.path.splitext(video_url)[1]

    # 创建保存目录
    save_dir = f"download_videos/{title}"

    # Path(save_dir).mkdir(exist_ok=True)
    Path(save_dir).mkdir(parents=True, exist_ok=True)

    # 文件名:用ID命名,避免乱码
    filename  = f"video_{video_id}{file_ext}"
    save_path = os.path.join(save_dir, filename)
    
    # 如果文件已存在,跳过
    if os.path.exists(save_path):
        print(f"&#8505;&#65039;  文件已存在,跳过:{filename}")
        return True
    
    try:
        # 流式下载(支持大文件)
        response = requests.get(
            video_url,
            stream=True,
            timeout=60,
            headers={
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36"
            }
        )
        response.raise_for_status()  # 检查HTTP错误
        
        # 获取文件大小(显示进度)
        total_size = int(response.headers.get("Content-Length", 0))
        downloaded_size = 0
        
        # 写入文件
        with open(save_path, "wb") as f:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
                    downloaded_size += len(chunk)
                    # 显示下载进度
                    if total_size > 0:
                        progress = (downloaded_size / total_size) * 100
                        print(f"\r&#128229; 下载中 {filename}:{progress:.1f}% ({downloaded_size/1024/1024:.2f}MB/{total_size/1024/1024:.2f}MB)", end="")
        print(f"\n&#9989; 下载完成:{filename} → 保存路径:{save_path}")
        return True
    except Exception as e:
        print(f"\n&#10060; 下载失败 {filename}:{str(e)}")
        # 删除不完整的文件
        if os.path.exists(save_path):
            os.remove(save_path)
        return False
    

# ===================== 运行 =====================
if __name__ == "__main__":

    keyword = '雪见0308'
    # keyword = 'xx1212'
    # keyword = '588688'
    # keyword = '8023'
    # keyword = '4039'
    # keyword = '668866'
    
    print("开始调用接口...\n")

    success_countsearch = request_album_search(keyword)

    # print(success_countsearch)
    # exit()
    
    if success_countsearch == 10:

        result1 = request_album_list()
        if result1.get("code") == 1 and result1.get("data"):
            photo_list = result1["data"].get("albumList", [])
            for item in photo_list:
                id = item.get("id")
                title = item.get("title")
            
                result2 = request_album_find(id)

                success_count = 0
                fail_count = 0
                print("\n============ 开始批量下载 ============")
                for idx, video_info in enumerate(result2, 1):
                    if download_video(video_info,title):
                        success_count += 1
                    else:
                        fail_count += 1
                
                print("\n============ 下载完成 ============")
                print(f"&#9989; 成功:{success_count} 个")
                print(f"&#10060; 失败:{fail_count} 个")
                print(f"&#128194; 所有文件保存在:{os.path.abspath('download_videos')}")

    else:
        
        success_count = 0
        fail_count = 0
        print("\n============ 开始批量下载 ============")
        for idx, video_info in enumerate(success_countsearch, 1):
            if download_video(video_info,keyword):
                success_count += 1
            else:
                fail_count += 1
        
        print("\n============ 下载完成 ============")
        print(f"&#9989; 成功:{success_count} 个")
        print(f"&#10060; 失败:{fail_count} 个")
        print(f"&#128194; 所有文件保存在:{os.path.abspath('download_videos')}")

    



sign

sign

接口

接口

e_param = token

e_param = token

效果

效果

免费评分

参与人数 1吾爱币 +7 热心值 +1 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

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

amwquhwqas128 发表于 2026-4-15 17:53
有一小部分代码没有搞懂
 楼主| hk137 发表于 2026-4-16 09:25
amwquhwqas128 发表于 2026-4-16 15:11
        homepage_id = result["data"].get("homepage_id", [])     为什么可以使用["data"]?
 楼主| hk137 发表于 2026-4-16 17:08
amwquhwqas128 发表于 2026-4-16 15:11
homepage_id = result["data"].get("homepage_id", [])     为什么可以使用["data"]?

result = response.json()
Python转为字典

转为字典之后 可以使用  result["data"]
amwquhwqas128 发表于 2026-4-17 17:49
多谢解惑
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-7-14 22:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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