From 2114bc925edf8c050834f1ba2f3ddb4be22b6ed3 Mon Sep 17 00:00:00 2001 From: imgyh <1974355683@qq.com> Date: Sun, 21 May 2023 16:25:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(tiktok):=20=E5=88=A0=E9=99=A4=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TikTok.py | 1214 --------------------------------------------- TikTokCommand.py | 353 ------------- TikTokDataBase.py | 172 ------- TikTokResult.py | 284 ----------- TikTokTest.py | 109 ---- TikTokUrls.py | 90 ---- TikTokUtils.py | 105 ---- TikTokWeb.py | 150 ------ X-Bogus.js | 564 --------------------- 9 files changed, 3041 deletions(-) delete mode 100644 TikTok.py delete mode 100644 TikTokCommand.py delete mode 100644 TikTokDataBase.py delete mode 100644 TikTokResult.py delete mode 100644 TikTokTest.py delete mode 100644 TikTokUrls.py delete mode 100644 TikTokUtils.py delete mode 100644 TikTokWeb.py delete mode 100644 X-Bogus.js diff --git a/TikTok.py b/TikTok.py deleted file mode 100644 index 0d01a1d..0000000 --- a/TikTok.py +++ /dev/null @@ -1,1214 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/01/27 19:36:18 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : 2023/02/11 修改接口 -------------------------------------------------- -''' - -import re -import requests -import json -import time -import os -import copy -from tqdm import tqdm -from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED -# rich 进度条 -# from functools import partial -# from urllib.request import urlopen -# import signal -# from threading import Event -# from rich.progress import ( -# BarColumn, -# DownloadColumn, -# Progress, -# TaskID, -# TextColumn, -# TimeRemainingColumn, -# TransferSpeedColumn -# ) - -from TikTokUtils import Utils -from TikTokUrls import Urls -from TikTokResult import Result -from TikTokDataBase import db - - -class TikTok(object): - - def __init__(self): - self.urls = Urls() - self.utils = Utils() - self.result = Result() - self.db = db() - self.headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', - 'referer': 'https://www.douyin.com/', - 'accept-encoding': None, - 'Cookie': f"msToken={self.utils.generate_random_str(107)}; ttwid={self.utils.getttwid()}; odin_tt=324fb4ea4a89c0c05827e18a1ed9cf9bf8a17f7705fcc793fec935b637867e2a5a9b8168c885554d029919117a18ba69; passport_csrf_token=f61602fc63757ae0e4fd9d6bdcee4810;" - } - # 用于设置重复请求某个接口的最大时间 - self.timeout = 10 - - # rich 进度条 - # self.progress = Progress( - # TextColumn("[bold blue]{task.fields[filename]}", justify="left"), - # BarColumn(bar_width=20), - # "[progress.percentage]{task.percentage:>3.1f}%", - # "•", - # DownloadColumn(), - # "•", - # TransferSpeedColumn(), - # "•", - # TimeRemainingColumn(), - # ) - # self.done_event = Event() - # signal.signal(signal.SIGINT, self.handle_sigint) - - # 从分享链接中提取网址 - def getShareLink(self, string): - # findall() 查找匹配正则表达式的字符串 - return re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', string)[0] - - # 得到 作品id 或者 用户id - # 传入 url 支持 https://www.iesdouyin.com 与 https://v.douyin.com - def getKey(self, url): - key = None - key_type = None - - try: - r = requests.get(url=url, headers=self.headers) - except Exception as e: - print('[ 错误 ]:输入链接有误!\r') - return key_type, key - - # 抖音把图集更新为note - # 作品 第一步解析出来的链接是share/video/{aweme_id} - # https://www.iesdouyin.com/share/video/7037827546599263488/?region=CN&mid=6939809470193126152&u_code=j8a5173b&did=MS4wLjABAAAA1DICF9-A9M_CiGqAJZdsnig5TInVeIyPdc2QQdGrq58xUgD2w6BqCHovtqdIDs2i&iid=MS4wLjABAAAAomGWi4n2T0H9Ab9x96cUZoJXaILk4qXOJlJMZFiK6b_aJbuHkjN_f0mBzfy91DX1&with_sec_did=1&titleType=title&schema_type=37&from_ssr=1&utm_source=copy&utm_campaign=client_share&utm_medium=android&app=aweme - # 用户 第一步解析出来的链接是share/user/{sec_uid} - # https://www.iesdouyin.com/share/user/MS4wLjABAAAA06y3Ctu8QmuefqvUSU7vr0c_ZQnCqB0eaglgkelLTek?did=MS4wLjABAAAA1DICF9-A9M_CiGqAJZdsnig5TInVeIyPdc2QQdGrq58xUgD2w6BqCHovtqdIDs2i&iid=MS4wLjABAAAAomGWi4n2T0H9Ab9x96cUZoJXaILk4qXOJlJMZFiK6b_aJbuHkjN_f0mBzfy91DX1&with_sec_did=1&sec_uid=MS4wLjABAAAA06y3Ctu8QmuefqvUSU7vr0c_ZQnCqB0eaglgkelLTek&from_ssr=1&u_code=j8a5173b×tamp=1674540164&ecom_share_track_params=%7B%22is_ec_shopping%22%3A%221%22%2C%22secuid%22%3A%22MS4wLjABAAAA-jD2lukp--I21BF8VQsmYUqJDbj3FmU-kGQTHl2y1Cw%22%2C%22enter_from%22%3A%22others_homepage%22%2C%22share_previous_page%22%3A%22others_homepage%22%7D&utm_source=copy&utm_campaign=client_share&utm_medium=android&app=aweme - # 合集 - # https://www.douyin.com/collection/7093490319085307918 - urlstr = str(r.request.path_url) - - if "/user/" in urlstr: - # 获取用户 sec_uid - if '?' in r.request.path_url: - for one in re.finditer(r'user\/([\d\D]*)([?])', str(r.request.path_url)): - key = one.group(1) - else: - for one in re.finditer(r'user\/([\d\D]*)', str(r.request.path_url)): - key = one.group(1) - key_type = "user" - elif "/video/" in urlstr: - # 获取作品 aweme_id - key = re.findall('video/(\d+)?', urlstr)[0] - key_type = "aweme" - elif "/note/" in urlstr: - # 获取note aweme_id - key = re.findall('note/(\d+)?', urlstr)[0] - key_type = "aweme" - elif "/mix/detail/" in urlstr: - # 获取合集 id - key = re.findall('/mix/detail/(\d+)?', urlstr)[0] - key_type = "mix" - elif "/collection/" in urlstr: - # 获取合集 id - key = re.findall('/collection/(\d+)?', urlstr)[0] - key_type = "mix" - elif "/music/" in urlstr: - # 获取原声 id - key = re.findall('music/(\d+)?', urlstr)[0] - key_type = "music" - elif "/webcast/reflow/" in urlstr: - key1 = re.findall('reflow/(\d+)?', urlstr)[0] - url = self.urls.LIVE2 + self.utils.getXbogus( - f'live_id=1&room_id={key1}&app_id=1128') - res = requests.get(url, headers=self.headers) - resjson = json.loads(res.text) - key = resjson['data']['room']['owner']['web_rid'] - key_type = "live" - elif "live.douyin.com" in r.url: - key = r.url.replace('https://live.douyin.com/', '') - key_type = "live" - - if key is None or key_type is None: - print('[ 错误 ]:输入链接有误!无法获取 id\r') - return key_type, key - - return key_type, key - - def getAwemeInfoApi(self, aweme_id): - if aweme_id is None: - return None - start = time.time() # 开始时间 - while True: - try: - jx_url = self.urls.POST_DETAIL + self.utils.getXbogus( - url=f'aweme_id={aweme_id}&device_platform=webapp&aid=6383') - - raw = requests.get(url=jx_url, headers=self.headers).text - datadict = json.loads(raw) - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if datadict['aweme_detail']["images"] is not None: - awemeType = 1 - except Exception as e: - pass - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, datadict['aweme_detail']) - - return self.result.awemeDict, datadict - - # 传入 aweme_id - # 返回 数据 字典 - def getAwemeInfo(self, aweme_id): - print('[ 提示 ]:正在请求的作品 id = %s\r' % aweme_id) - if aweme_id is None: - return None - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - # 单作品接口返回 'aweme_detail' - # 主页作品接口返回 'aweme_list'->['aweme_detail'] - jx_url = self.urls.POST_DETAIL + self.utils.getXbogus( - url=f'aweme_id={aweme_id}&device_platform=webapp&aid=6383') - - raw = requests.get(url=jx_url, headers=self.headers).text - datadict = json.loads(raw) - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return {}, {} - # print("[ 警告 ]:接口未返回数据, 正在重新请求!\r") - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - # datadict['aweme_detail']["images"] 不为 None 说明是图集 - if datadict['aweme_detail']["images"] is not None: - awemeType = 1 - except Exception as e: - print("[ 警告 ]:接口中未找到 images\r") - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, datadict['aweme_detail']) - - return self.result.awemeDict, datadict - - def getUserInfoApi(self, sec_uid, mode="post", count=35, max_cursor=0): - if sec_uid is None: - return None - - awemeList = [] - - start = time.time() # 开始时间 - while True: - try: - if mode == "post": - url = self.urls.USER_POST + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&device_platform=webapp&aid=6383') - elif mode == "like": - url = self.urls.USER_FAVORITE_A + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&device_platform=webapp&aid=6383') - else: - return None - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - for aweme in datadict["aweme_list"]: - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - pass - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - return awemeList, datadict, datadict["max_cursor"], datadict["has_more"] - - # 传入 url 支持 https://www.iesdouyin.com 与 https://v.douyin.com - # mode : post | like 模式选择 like为用户点赞 post为用户发布 - def getUserInfo(self, sec_uid, mode="post", count=35, number=0, increase=False): - print('[ 提示 ]:正在请求的用户 id = %s\r\n' % sec_uid) - if sec_uid is None: - return None - if number <= 0: - numflag = False - else: - numflag = True - - max_cursor = 0 - awemeList = [] - increaseflag = False - numberis0 = False - - print("[ 提示 ]:正在获取所有作品数据请稍后...\r") - print("[ 提示 ]:会进行多次请求,等待时间较长...\r\n") - times = 0 - while True: - times = times + 1 - print("[ 提示 ]:正在对 [主页] 进行第 " + str(times) + " 次请求...\r") - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - if mode == "post": - url = self.urls.USER_POST + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&device_platform=webapp&aid=6383') - elif mode == "like": - url = self.urls.USER_FAVORITE_A + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&device_platform=webapp&aid=6383') - else: - print("[ 错误 ]:模式选择错误, 仅支持post、like、mix, 请检查后重新运行!\r") - return None - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - print('[ 提示 ]:本次请求返回 ' + str(len(datadict["aweme_list"])) + ' 条数据\r') - # print('[ 提示 ]:开始对 ' + str(len(datadict["aweme_list"])) + ' 条数据请求作品详情\r\n') - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return awemeList - # print("[ 警告 ]:接口未返回数据, 正在重新请求!\r") - - for aweme in datadict["aweme_list"]: - # 退出条件 - if increase is False and numflag and numberis0: - break - if increase and numflag and numberis0 and increaseflag: - break - # 增量更新, 找到非置顶的最新的作品发布时间 - if mode == "post": - if self.db.get_user_post(sec_uid=sec_uid, aweme_id=aweme['aweme_id']) is not None: - if increase and aweme['is_top'] == 0: - increaseflag = True - else: - self.db.insert_user_post(sec_uid=sec_uid, aweme_id=aweme['aweme_id'], data=aweme) - elif mode == "like": - if self.db.get_user_like(sec_uid=sec_uid, aweme_id=aweme['aweme_id']) is not None: - if increase and aweme['is_top'] == 0: - increaseflag = True - else: - self.db.insert_user_like(sec_uid=sec_uid, aweme_id=aweme['aweme_id'], data=aweme) - - # 退出条件 - if increase and numflag is False and increaseflag: - break - if increase and numflag and numberis0 and increaseflag: - break - - if numflag: - number -= 1 - if number == 0: - numberis0 = True - # 获取 aweme_id - # aweme_id = aweme["aweme_id"] - # 深拷贝 dict 不然list里面全是同样的数据 - # datanew, dataraw = self.getAwemeInfo(aweme_id) - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - print("[ 警告 ]:接口中未找到 images\r") - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - if increase and numflag is False and increaseflag: - print("\r\n[ 提示 ]: [主页] 下作品增量更新数据获取完成...\r\n") - break - elif increase is False and numflag and numberis0: - print("\r\n[ 提示 ]: [主页] 下指定数量作品数据获取完成...\r\n") - break - elif increase and numflag and numberis0 and increaseflag: - print("\r\n[ 提示 ]: [主页] 下指定数量作品数据获取完成, 增量更新数据获取完成...\r\n") - break - - # 更新 max_cursor - max_cursor = datadict["max_cursor"] - - # 退出条件 - if datadict["has_more"] == 0 or datadict["has_more"] == False: - print("\r\n[ 提示 ]: [主页] 下所有作品数据获取完成...\r\n") - break - else: - print("\r\n[ 提示 ]:[主页] 第 " + str(times) + " 次请求成功...\r\n") - - return awemeList - - def getLiveInfoApi(self, web_rid: str): - start = time.time() # 开始时间 - while True: - try: - live_api = self.urls.LIVE + self.utils.getXbogus( - url=f'aid=6383&device_platform=web&web_rid={web_rid}') - - response = requests.get(live_api, headers=self.headers) - live_json = json.loads(response.text) - if live_json != {} and live_json['status_code'] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - # 清空字典 - self.result.clearDict(self.result.liveDict) - - # 类型 - self.result.liveDict["awemeType"] = 2 - # 是否在播 - self.result.liveDict["status"] = live_json['data']['data'][0]['status'] - - if self.result.liveDict["status"] == 4: - return self.result.liveDict, live_json - - # 直播标题 - self.result.liveDict["title"] = live_json['data']['data'][0]['title'] - - # 直播cover - self.result.liveDict["cover"] = live_json['data']['data'][0]['cover']['url_list'][0] - - # 头像 - self.result.liveDict["avatar"] = live_json['data']['data'][0]['owner']['avatar_thumb']['url_list'][0].replace( - "100x100", "1080x1080") - - # 观看人数 - self.result.liveDict["user_count"] = live_json['data']['data'][0]['user_count_str'] - - # 昵称 - self.result.liveDict["nickname"] = live_json['data']['data'][0]['owner']['nickname'] - - # sec_uid - self.result.liveDict["sec_uid"] = live_json['data']['data'][0]['owner']['sec_uid'] - - # 直播间观看状态 - self.result.liveDict["display_long"] = live_json['data']['data'][0]['room_view_stats']['display_long'] - - # 推流 - self.result.liveDict["flv_pull_url"] = live_json['data']['data'][0]['stream_url']['flv_pull_url'] - - try: - # 分区 - self.result.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title'] - self.result.liveDict["sub_partition"] = \ - live_json['data']['partition_road_map']['sub_partition']['partition']['title'] - except Exception as e: - self.result.liveDict["partition"] = '无' - self.result.liveDict["sub_partition"] = '无' - - flv = [] - - for i, f in enumerate(self.result.liveDict["flv_pull_url"].keys()): - flv.append(f) - - self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[0]] - - return self.result.liveDict, live_json - - def getLiveInfo(self, web_rid: str): - print('[ 提示 ]:正在请求的直播间 id = %s\r\n' % web_rid) - - # web_rid = live_url.replace('https://live.douyin.com/', '') - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - live_api = self.urls.LIVE + self.utils.getXbogus( - url=f'aid=6383&device_platform=web&web_rid={web_rid}') - - response = requests.get(live_api, headers=self.headers) - live_json = json.loads(response.text) - if live_json != {} and live_json['status_code'] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return {} - - # 清空字典 - self.result.clearDict(self.result.liveDict) - - # 类型 - self.result.liveDict["awemeType"] = 2 - # 是否在播 - self.result.liveDict["status"] = live_json['data']['data'][0]['status'] - - if self.result.liveDict["status"] == 4: - print('[ 📺 ]:当前直播已结束,正在退出') - return self.result.liveDict - - # 直播标题 - self.result.liveDict["title"] = live_json['data']['data'][0]['title'] - - # 直播cover - self.result.liveDict["cover"] = live_json['data']['data'][0]['cover']['url_list'][0] - - # 头像 - self.result.liveDict["avatar"] = live_json['data']['data'][0]['owner']['avatar_thumb']['url_list'][0].replace( - "100x100", "1080x1080") - - # 观看人数 - self.result.liveDict["user_count"] = live_json['data']['data'][0]['user_count_str'] - - # 昵称 - self.result.liveDict["nickname"] = live_json['data']['data'][0]['owner']['nickname'] - - # sec_uid - self.result.liveDict["sec_uid"] = live_json['data']['data'][0]['owner']['sec_uid'] - - # 直播间观看状态 - self.result.liveDict["display_long"] = live_json['data']['data'][0]['room_view_stats']['display_long'] - - # 推流 - self.result.liveDict["flv_pull_url"] = live_json['data']['data'][0]['stream_url']['flv_pull_url'] - - try: - # 分区 - self.result.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title'] - self.result.liveDict["sub_partition"] = \ - live_json['data']['partition_road_map']['sub_partition']['partition']['title'] - except Exception as e: - self.result.liveDict["partition"] = '无' - self.result.liveDict["sub_partition"] = '无' - - info = '[ 💻 ]:直播间:%s 当前%s 主播:%s 分区:%s-%s\r' % ( - self.result.liveDict["title"], self.result.liveDict["display_long"], self.result.liveDict["nickname"], - self.result.liveDict["partition"], self.result.liveDict["sub_partition"]) - print(info) - - flv = [] - print('[ 🎦 ]:直播间清晰度') - for i, f in enumerate(self.result.liveDict["flv_pull_url"].keys()): - print('[ %s ]: %s' % (i, f)) - flv.append(f) - - rate = int(input('[ 🎬 ]输入数字选择推流清晰度:')) - - self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[rate]] - - # 显示清晰度列表 - print('[ %s ]:%s' % (flv[rate], self.result.liveDict["flv_pull_url"][flv[rate]])) - print('[ 📺 ]:复制链接使用下载工具下载') - return self.result.liveDict - - def getMixInfoApi(self, mix_id: str, count=35, cursor=0): - if mix_id is None: - return None - - awemeList = [] - - start = time.time() # 开始时间 - while True: - try: - url = self.urls.USER_MIX + self.utils.getXbogus( - url=f'mix_id={mix_id}&cursor={cursor}&count={count}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - if datadict is not None: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - for aweme in datadict["aweme_list"]: - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - pass - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - return awemeList, datadict, datadict["cursor"], datadict["has_more"] - - def getMixInfo(self, mix_id: str, count=35, number=0, increase=False, sec_uid=''): - print('[ 提示 ]:正在请求的合集 id = %s\r\n' % mix_id) - if mix_id is None: - return None - if number <= 0: - numflag = False - else: - numflag = True - - cursor = 0 - awemeList = [] - increaseflag = False - numberis0 = False - - print("[ 提示 ]:正在获取合集下的所有作品数据请稍后...\r") - print("[ 提示 ]:会进行多次请求,等待时间较长...\r\n") - times = 0 - while True: - times = times + 1 - print("[ 提示 ]:正在对 [合集] 进行第 " + str(times) + " 次请求...\r") - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - url = self.urls.USER_MIX + self.utils.getXbogus( - url=f'mix_id={mix_id}&cursor={cursor}&count={count}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - print('[ 提示 ]:本次请求返回 ' + str(len(datadict["aweme_list"])) + ' 条数据\r') - # print('[ 提示 ]:开始对 ' + str(len(datadict["aweme_list"])) + ' 条数据请求作品详情\r\n') - if datadict is not None: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return awemeList - # print("[ 警告 ]:接口未返回数据, 正在重新请求!\r") - - for aweme in datadict["aweme_list"]: - # 退出条件 - if increase is False and numflag and numberis0: - break - if increase and numflag and numberis0 and increaseflag: - break - # 增量更新, 找到非置顶的最新的作品发布时间 - if self.db.get_mix(sec_uid=sec_uid, mix_id=mix_id, aweme_id=aweme['aweme_id']) is not None: - if increase and aweme['is_top'] == 0: - increaseflag = True - else: - self.db.insert_mix(sec_uid=sec_uid, mix_id=mix_id, aweme_id=aweme['aweme_id'], data=aweme) - - # 退出条件 - if increase and numflag is False and increaseflag: - break - if increase and numflag and numberis0 and increaseflag: - break - - if numflag: - number -= 1 - if number == 0: - numberis0 = True - # 获取 aweme_id - # aweme_id = aweme["aweme_id"] - # 深拷贝 dict 不然list里面全是同样的数据 - # datanew, dataraw = self.getAwemeInfo(aweme_id) - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - print("[ 警告 ]:接口中未找到 images\r") - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - if increase and numflag is False and increaseflag: - print("\r\n[ 提示 ]: [合集] 下作品增量更新数据获取完成...\r\n") - break - elif increase is False and numflag and numberis0: - print("\r\n[ 提示 ]: [合集] 下指定数量作品数据获取完成...\r\n") - break - elif increase and numflag and numberis0 and increaseflag: - print("\r\n[ 提示 ]: [合集] 下指定数量作品数据获取完成, 增量更新数据获取完成...\r\n") - break - - # 更新 max_cursor - cursor = datadict["cursor"] - - # 退出条件 - if datadict["has_more"] == 0 or datadict["has_more"] == False: - print("\r\n[ 提示 ]:[合集] 下所有作品数据获取完成...\r\n") - break - else: - print("\r\n[ 提示 ]:[合集] 第 " + str(times) + " 次请求成功...\r\n") - - return awemeList - - def getUserAllMixInfoApi(self, sec_uid, count=35, cursor=0): - - if sec_uid is None: - return None - - mixIdlist = [] - - start = time.time() # 开始时间 - while True: - try: - url = self.urls.USER_MIX_LIST + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&cursor={cursor}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - for mix in datadict["mix_infos"]: - mixIdNameDict = {} - mixIdNameDict["https://www.douyin.com/collection/" + mix["mix_id"]] = mix["mix_name"] - mixIdlist.append(mixIdNameDict) - - return mixIdlist, datadict, datadict["cursor"], datadict["has_more"] - - def getUserAllMixInfo(self, sec_uid, count=35, number=0): - print('[ 提示 ]:正在请求的用户 id = %s\r\n' % sec_uid) - if sec_uid is None: - return None - if number <= 0: - numflag = False - else: - numflag = True - - cursor = 0 - mixIdNameDict = {} - - print("[ 提示 ]:正在获取主页下所有合集 id 数据请稍后...\r") - print("[ 提示 ]:会进行多次请求,等待时间较长...\r\n") - times = 0 - while True: - times = times + 1 - print("[ 提示 ]:正在对 [合集列表] 进行第 " + str(times) + " 次请求...\r") - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - url = self.urls.USER_MIX_LIST + self.utils.getXbogus( - url=f'sec_user_id={sec_uid}&count={count}&cursor={cursor}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - print('[ 提示 ]:本次请求返回 ' + str(len(datadict["mix_infos"])) + ' 条数据\r') - # print('[ 提示 ]:开始对 ' + str(len(datadict["mix_infos"])) + ' 条数据请求作品详情\r\n') - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return mixIdNameDict - # print("[ 警告 ]:接口未返回数据, 正在重新请求!\r") - - for mix in datadict["mix_infos"]: - mixIdNameDict[mix["mix_id"]] = mix["mix_name"] - if numflag: - number -= 1 - if number == 0: - break - if numflag and number == 0: - print("\r\n[ 提示 ]:[合集列表] 下指定数量合集数据获取完成...\r\n") - break - - # 更新 max_cursor - cursor = datadict["cursor"] - - # 退出条件 - if datadict["has_more"] == 0 or datadict["has_more"] == False: - print("[ 提示 ]:[合集列表] 下所有合集 id 数据获取完成...\r\n") - break - else: - print("\r\n[ 提示 ]:[合集列表] 第 " + str(times) + " 次请求成功...\r\n") - - return mixIdNameDict - - def getMusicInfoApi(self, music_id: str, count=35, cursor=0): - if music_id is None: - return None - - awemeList = [] - - start = time.time() # 开始时间 - while True: - try: - url = self.urls.MUSIC + self.utils.getXbogus( - url=f'music_id={music_id}&cursor={cursor}&count={count}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - return None - - for aweme in datadict["aweme_list"]: - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - pass - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - return awemeList, datadict, datadict["cursor"], datadict["has_more"] - - def getMusicInfo(self, music_id: str, count=35, number=0, increase=False): - print('[ 提示 ]:正在请求的音乐集合 id = %s\r\n' % music_id) - if music_id is None: - return None - if number <= 0: - numflag = False - else: - numflag = True - - cursor = 0 - awemeList = [] - increaseflag = False - numberis0 = False - - print("[ 提示 ]:正在获取音乐集合下的所有作品数据请稍后...\r") - print("[ 提示 ]:会进行多次请求,等待时间较长...\r\n") - times = 0 - while True: - times = times + 1 - print("[ 提示 ]:正在对 [音乐集合] 进行第 " + str(times) + " 次请求...\r") - - start = time.time() # 开始时间 - while True: - # 接口不稳定, 有时服务器不返回数据, 需要重新获取 - try: - url = self.urls.MUSIC + self.utils.getXbogus( - url=f'music_id={music_id}&cursor={cursor}&count={count}&device_platform=webapp&aid=6383') - - res = requests.get(url=url, headers=self.headers) - datadict = json.loads(res.text) - print('[ 提示 ]:本次请求返回 ' + str(len(datadict["aweme_list"])) + ' 条数据\r') - # print('[ 提示 ]:开始对 ' + str(len(datadict["aweme_list"])) + ' 条数据请求作品详情\r\n') - if datadict is not None and datadict["status_code"] == 0: - break - except Exception as e: - end = time.time() # 结束时间 - if end - start > self.timeout: - # raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据") - return awemeList - # print("[ 警告 ]:接口未返回数据, 正在重新请求!\r") - - for aweme in datadict["aweme_list"]: - if increase is False and numflag and numberis0: - break - if increase and numflag and numberis0 and increaseflag: - break - # 增量更新, 找到非置顶的最新的作品发布时间 - if self.db.get_music(music_id=music_id, aweme_id=aweme['aweme_id']) is not None: - if increase and aweme['is_top'] == 0: - increaseflag = True - else: - self.db.insert_music(music_id=music_id, aweme_id=aweme['aweme_id'], data=aweme) - - # 退出条件 - if increase and numflag is False and increaseflag: - break - if increase and numflag and numberis0 and increaseflag: - break - - if numflag: - number -= 1 - if number == 0: - numberis0 = True - # 获取 aweme_id - # aweme_id = aweme["aweme_id"] - # 深拷贝 dict 不然list里面全是同样的数据 - # datanew, dataraw = self.getAwemeInfo(aweme_id) - - # 清空self.awemeDict - self.result.clearDict(self.result.awemeDict) - - # 默认为视频 - awemeType = 0 - try: - if aweme["images"] is not None: - awemeType = 1 - except Exception as e: - print("[ 警告 ]:接口中未找到 images\r") - - # 转换成我们自己的格式 - self.result.dataConvert(awemeType, self.result.awemeDict, aweme) - - if self.result.awemeDict is not None and self.result.awemeDict != {}: - awemeList.append(copy.deepcopy(self.result.awemeDict)) - - if increase and numflag is False and increaseflag: - print("\r\n[ 提示 ]: [音乐集合] 下作品增量更新数据获取完成...\r\n") - break - elif increase is False and numflag and numberis0: - print("\r\n[ 提示 ]: [音乐集合] 下指定数量作品数据获取完成...\r\n") - break - elif increase and numflag and numberis0 and increaseflag: - print("\r\n[ 提示 ]: [音乐集合] 下指定数量作品数据获取完成, 增量更新数据获取完成...\r\n") - break - - # 更新 cursor - cursor = datadict["cursor"] - - # 退出条件 - if datadict["has_more"] == 0 or datadict["has_more"] == False: - print("\r\n[ 提示 ]:[音乐集合] 下所有作品数据获取完成...\r\n") - break - else: - print("\r\n[ 提示 ]:[音乐集合] 第 " + str(times) + " 次请求成功...\r\n") - - return awemeList - - # rich 进度条 - # https://github.com/textualize/rich/blob/master/examples/downloader.py - # def handle_sigint(self, signum, frame): - # self.done_event.set() - # - # def copy_url(self, task_id: TaskID, url: str, path: str) -> None: - # """Copy data from a url to a local file.""" - # # self.progress.console.log(f"Requesting {url}") - # response = urlopen(url) - # try: - # # This will break if the response doesn't contain content length - # self.progress.update(task_id, total=int(response.info()["Content-length"])) - # with open(path, "wb") as dest_file: - # self.progress.start_task(task_id) - # for data in iter(partial(response.read, 32768), b""): - # dest_file.write(data) - # self.progress.update(task_id, advance=len(data)) - # if self.done_event.is_set(): - # return - # except Exception as e: - # # 下载异常 删除原来下载的文件, 可能未下成功 - # if os.path.exists(path): - # os.remove(path) - # print("[ 错误 ]:下载出错\r") - - # 来自 https://blog.csdn.net/weixin_43347550/article/details/105248223 - def progressBarDownload(self, url, filepath, desc): - response = requests.get(url, stream=True, headers=self.headers) - chunk_size = 1024 # 每次下载的数据大小 - content_size = int(response.headers['content-length']) # 下载文件总大小 - try: - if response.status_code == 200: # 判断是否响应成功 - # print('[开始下载]:文件大小:{size:.2f} MB'.format( - # size=content_size / chunk_size / 1024)) # 开始下载,显示下载文件大小 - with open(filepath, 'wb') as file, tqdm(total=content_size, - unit="iB", - desc=desc, - unit_scale=True, - unit_divisor=1024, - - ) as bar: # 显示进度条 - for data in response.iter_content(chunk_size=chunk_size): - size = file.write(data) - bar.update(size) - except Exception as e: - # 下载异常 删除原来下载的文件, 可能未下成功 - if os.path.exists(filepath): - os.remove(filepath) - print("[ 错误 ]:下载出错\r") - - def awemeDownload(self, awemeDict: dict, music=True, cover=True, avatar=True, resjson=True, savePath=os.getcwd()): - if awemeDict is None: - return - if not os.path.exists(savePath): - os.mkdir(savePath) - - try: - # 使用作品 创建时间+描述 当文件夹 - file_name = awemeDict["create_time"] + "_" + self.utils.replaceStr(awemeDict["desc"]) - aweme_path = os.path.join(savePath, file_name) - if not os.path.exists(aweme_path): - os.mkdir(aweme_path) - - # 保存获取到的字典信息 - # print("[ 提示 ]:正在保存获取到的信息到 result.json\r\n") - if resjson: - try: - with open(os.path.join(aweme_path, "result.json"), "w", encoding='utf-8') as f: - f.write(json.dumps(awemeDict, ensure_ascii=False, indent=2)) - f.close() - except Exception as e: - print("[ 错误 ]:保存 result.json 失败... 作品名: " + file_name + "\r\n") - - desc = file_name[:30] - # 下载 视频 - if awemeDict["awemeType"] == 0: - # print("[ 提示 ]:正在下载视频...\r") - video_path = os.path.join(aweme_path, file_name + ".mp4") - - if os.path.exists(video_path): - # print("[ 提示 ]:视频已存在为您跳过...\r\n") - pass - else: - try: - url = awemeDict["video"]["play_addr"]["url_list"][0] - if url != "": - self.isdwownload = False - # task_id = self.progress.add_task("download", filename="[ 视频 ]:" + desc, start=False) - # self.alltask.append(self.pool.submit(self.copy_url, task_id, url, video_path)) - self.alltask.append( - self.pool.submit(self.progressBarDownload, url, video_path, "[ 视频 ]:" + desc)) - except Exception as e: - print("[ 警告 ]:视频下载失败,请重试... 作品名: " + file_name + "\r\n") - - # 下载 图集 - if awemeDict["awemeType"] == 1: - # print("[ 提示 ]:正在下载图集...\r") - for ind, image in enumerate(awemeDict["images"]): - image_path = os.path.join(aweme_path, "image" + str(ind) + ".jpeg") - if os.path.exists(image_path): - # print("[ 提示 ]:图片已存在为您跳过...\r\n") - pass - else: - try: - url = image["url_list"][0] - if url != "": - self.isdwownload = False - # task_id = self.progress.add_task("download", filename="[ 图集 ]:" + desc, start=False) - # self.alltask.append(self.pool.submit(self.copy_url, task_id, url, image_path)) - self.alltask.append( - self.pool.submit(self.progressBarDownload, url, image_path, "[ 图集 ]:" + desc)) - except Exception as e: - print("[ 警告 ]:图片下载失败,请重试... 作品名: " + file_name + "\r\n") - - # 下载 音乐 - if music: - # print("[ 提示 ]:正在下载音乐...\r") - music_name = self.utils.replaceStr(awemeDict["music"]["title"]) - music_path = os.path.join(aweme_path, music_name + ".mp3") - - if os.path.exists(music_path): - # print("[ 提示 ]:音乐已存在为您跳过...\r\n") - pass - else: - try: - url = awemeDict["music"]["play_url"]["url_list"][0] - if url != "": - self.isdwownload = False - # task_id = self.progress.add_task("download", filename="[ 原声 ]:" + desc, start=False) - # self.alltask.append(self.pool.submit(self.copy_url, task_id, url, music_path)) - self.alltask.append( - self.pool.submit(self.progressBarDownload, url, music_path, "[ 原声 ]:" + desc)) - except Exception as e: - print("[ 警告 ]:音乐(原声)下载失败,请重试... 作品名: " + file_name + "\r\n") - - # 下载 cover - if cover and awemeDict["awemeType"] == 0: - # print("[ 提示 ]:正在下载视频cover图...\r") - cover_path = os.path.join(aweme_path, "cover.jpeg") - - if os.path.exists(cover_path): - # print("[ 提示 ]:cover 已存在为您跳过...\r\n") - pass - else: - try: - url = awemeDict["video"]["cover"]["url_list"][0] - if url != "": - self.isdwownload = False - # task_id = self.progress.add_task("download", filename="[ 封面 ]:" + desc, start=False) - # self.alltask.append(self.pool.submit(self.copy_url, task_id, url, cover_path)) - self.alltask.append( - self.pool.submit(self.progressBarDownload, url, cover_path, "[ 封面 ]:" + desc)) - except Exception as e: - print("[ 警告 ]:cover下载失败,请重试... 作品名: " + file_name + "\r\n") - - # 下载 avatar - if avatar: - # print("[ 提示 ]:正在下载用户头像...\r") - avatar_path = os.path.join(aweme_path, "avatar.jpeg") - - if os.path.exists(avatar_path): - # print("[ 提示 ]:avatar 已存在为您跳过...\r\n") - pass - else: - try: - url = awemeDict["author"]["avatar"]["url_list"][0] - if url != "": - self.isdwownload = False - # task_id = self.progress.add_task("download", filename="[ 头像 ]:" + desc, start=False) - # self.alltask.append(self.pool.submit(self.copy_url, task_id, url, avatar_path)) - self.alltask.append( - self.pool.submit(self.progressBarDownload, url, avatar_path, "[ 头像 ]:" + desc)) - except Exception as e: - print("[ 警告 ]:avatar下载失败,请重试... 作品名: " + file_name + "\r\n") - except Exception as e: - print("[ 错误 ]:下载作品时出错\r\n") - - # def userDownload(self, awemeList: list, music=True, cover=True, avatar=True, resjson=True, savePath=os.getcwd(), thread=5): - # if awemeList is None: - # return - # if not os.path.exists(savePath): - # os.mkdir(savePath) - # - # self.alltask = [] - # - # start = time.time() # 开始时间 - # - # # 分块下载 - # for i in range(0, len(awemeList), thread): - # batchAwemeList = awemeList[i:i + thread] - # - # - # for awemeList2 in batchAwemeList: - # with self.progress: - # with ThreadPoolExecutor(max_workers=thread) as self.pool: - # # self.progress.console.log("请耐心等待下载完成(终端尺寸越长显示的进度条越多)...") - # for aweme in awemeList2: - # self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, savePath=savePath) - # # time.sleep(0.5) - # wait(self.alltask, return_when=ALL_COMPLETED) - # # self.alltask = [] - # # 清除上一步的进度条 - # # for taskid in self.progress.task_ids: - # # self.progress.remove_task(taskid) - # - # # 检查下载是否完成 - # while True: - # self.isdwownload = True - # # 下载上一步失败的 - # with self.progress: - # with ThreadPoolExecutor(max_workers=thread) as self.pool: - # self.progress.console.log("正在检查下载是否完成...") - # for aweme in awemeList: - # self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, savePath=savePath) - # # time.sleep(0.5) - # wait(self.alltask, return_when=ALL_COMPLETED) - # # self.alltask = [] - # # 清除上一步的进度条 - # # for taskid in self.progress.task_ids: - # # self.progress.remove_task(taskid) - # - # if self.isdwownload: - # break - # - # end = time.time() # 结束时间 - # print('\n' + '[下载完成]:耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间 - - def userDownload(self, awemeList: list, music=True, cover=True, avatar=True, resjson=True, savePath=os.getcwd(), - thread=5): - if awemeList is None: - return - if not os.path.exists(savePath): - os.mkdir(savePath) - - self.alltask = [] - self.pool = ThreadPoolExecutor(max_workers=thread) - - start = time.time() # 开始时间 - - for aweme in awemeList: - self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, - savePath=savePath) - # time.sleep(0.5) - wait(self.alltask, return_when=ALL_COMPLETED) - - # 检查下载是否完成 - while True: - print("[ 提示 ]:正在检查下载是否完成...") - self.isdwownload = True - # 下载上一步失败的 - for aweme in awemeList: - self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, - savePath=savePath) - # time.sleep(0.5) - wait(self.alltask, return_when=ALL_COMPLETED) - - if self.isdwownload: - break - - end = time.time() # 结束时间 - print('\n' + '[下载完成]:耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间 - - -if __name__ == "__main__": - pass diff --git a/TikTokCommand.py b/TikTokCommand.py deleted file mode 100644 index 0df42b8..0000000 --- a/TikTokCommand.py +++ /dev/null @@ -1,353 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/01/27 19:36:18 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' - -import argparse -import os -import sys -import json -import yaml -import time -from TikTok import TikTok -from TikTokUtils import Utils - -configModel = { - "link": [], - "path": os.getcwd(), - "music": True, - "cover": True, - "avatar": True, - "json": True, - "mode": ["post"], - "number": { - "post": 0, - "like": 0, - "allmix": 0, - "mix": 0, - "music": 0, - }, - "increase": { - "post": False, - "like": False, - "allmix": False, - "mix": False, - "music": False, - }, - "thread": 5, - "cookie": None - -} - - -def argument(): - parser = argparse.ArgumentParser(description='抖音批量下载工具 使用帮助') - parser.add_argument("--cmd", "-C", help="使用命令行(True)或者配置文件(False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--link", "-l", - help="作品(视频或图集)、直播、合集、音乐集合、个人主页的分享链接或者电脑浏览器网址, 可以设置多个链接(删除文案, 保证只有URL, https://v.douyin.com/kcvMpuN/ 或者 https://www.douyin.com/开头的)", - type=str, required=False, default=[], action="append") - parser.add_argument("--path", "-p", help="下载保存位置, 默认当前文件位置", - type=str, required=False, default=os.getcwd()) - parser.add_argument("--music", "-m", help="是否下载视频中的音乐(True/False), 默认为True", - type=Utils().str2bool, required=False, default=True) - parser.add_argument("--cover", "-c", help="是否下载视频的封面(True/False), 默认为True, 当下载视频时有效", - type=Utils().str2bool, required=False, default=True) - parser.add_argument("--avatar", "-a", help="是否下载作者的头像(True/False), 默认为True", - type=Utils().str2bool, required=False, default=True) - parser.add_argument("--json", "-j", help="是否保存获取到的数据(True/False), 默认为True", - type=Utils().str2bool, required=False, default=True) - parser.add_argument("--mode", "-M", help="link是个人主页时, 设置下载发布的作品(post)或喜欢的作品(like)或者用户所有合集(mix), 默认为post, 可以设置多种模式", - type=str, required=False, default=[], action="append") - parser.add_argument("--postnumber", help="主页下作品下载个数设置, 默认为0 全部下载", - type=int, required=False, default=0) - parser.add_argument("--likenumber", help="主页下喜欢下载个数设置, 默认为0 全部下载", - type=int, required=False, default=0) - parser.add_argument("--allmixnumber", help="主页下合集下载个数设置, 默认为0 全部下载", - type=int, required=False, default=0) - parser.add_argument("--mixnumber", help="单个合集下作品下载个数设置, 默认为0 全部下载", - type=int, required=False, default=0) - parser.add_argument("--musicnumber", help="音乐(原声)下作品下载个数设置, 默认为0 全部下载", - type=int, required=False, default=0) - parser.add_argument("--postincrease", help="是否开启主页作品增量下载(True/False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--likeincrease", help="是否开启主页喜欢增量下载(True/False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--allmixincrease", help="是否开启主页合集增量下载(True/False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--mixincrease", help="是否开启单个合集下作品增量下载(True/False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--musicincrease", help="是否开启音乐(原声)下作品增量下载(True/False), 默认为False", - type=Utils().str2bool, required=False, default=False) - parser.add_argument("--thread", "-t", - help="设置线程数, 默认5个线程", - type=int, required=False, default=5) - parser.add_argument("--cookie", help="设置cookie, 格式: \"name1=value1; name2=value2;\" 注意要加冒号", - type=str, required=False, default='') - args = parser.parse_args() - if args.thread <= 0: - args.thread = 5 - - return args - - -def yamlConfig(): - curPath = os.path.dirname(os.path.realpath(sys.argv[0])) - yamlPath = os.path.join(curPath, "config.yml") - f = open(yamlPath, 'r', encoding='utf-8') - cfg = f.read() - configDict = yaml.load(stream=cfg, Loader=yaml.FullLoader) - - try: - if configDict["link"] != None: - configModel["link"] = configDict["link"] - except Exception as e: - print("[ 警告 ]:link未设置, 程序退出...\r\n") - try: - if configDict["path"] != None: - configModel["path"] = configDict["path"] - except Exception as e: - print("[ 警告 ]:path未设置, 使用当前路径...\r\n") - try: - if configDict["music"] != None: - configModel["music"] = configDict["music"] - except Exception as e: - print("[ 警告 ]:music未设置, 使用默认值True...\r\n") - try: - if configDict["cover"] != None: - configModel["cover"] = configDict["cover"] - except Exception as e: - print("[ 警告 ]:cover未设置, 使用默认值True...\r\n") - try: - if configDict["avatar"] != None: - configModel["avatar"] = configDict["avatar"] - except Exception as e: - print("[ 警告 ]:avatar未设置, 使用默认值True...\r\n") - try: - if configDict["json"] != None: - configModel["json"] = configDict["json"] - except Exception as e: - print("[ 警告 ]:json未设置, 使用默认值True...\r\n") - try: - if configDict["mode"] != None: - configModel["mode"] = configDict["mode"] - except Exception as e: - print("[ 警告 ]:mode未设置, 使用默认值post...\r\n") - try: - if configDict["number"]["post"] != None: - configModel["number"]["post"] = configDict["number"]["post"] - except Exception as e: - print("[ 警告 ]:post number未设置, 使用默认值0...\r\n") - try: - if configDict["number"]["like"] != None: - configModel["number"]["like"] = configDict["number"]["like"] - except Exception as e: - print("[ 警告 ]:like number未设置, 使用默认值0...\r\n") - try: - if configDict["number"]["allmix"] != None: - configModel["number"]["allmix"] = configDict["number"]["allmix"] - except Exception as e: - print("[ 警告 ]:allmix number未设置, 使用默认值0...\r\n") - try: - if configDict["number"]["mix"] != None: - configModel["number"]["mix"] = configDict["number"]["mix"] - except Exception as e: - print("[ 警告 ]:mix number未设置, 使用默认值0...\r\n") - try: - if configDict["number"]["music"] != None: - configModel["number"]["music"] = configDict["number"]["music"] - except Exception as e: - print("[ 警告 ]:music number未设置, 使用默认值0...\r\n") - try: - if configDict["increase"]["post"] != None: - configModel["increase"]["post"] = configDict["increase"]["post"] - except Exception as e: - print("[ 警告 ]:post 增量更新未设置, 使用默认值False...\r\n") - try: - if configDict["increase"]["like"] != None: - configModel["increase"]["like"] = configDict["increase"]["like"] - except Exception as e: - print("[ 警告 ]:like 增量更新未设置, 使用默认值False...\r\n") - try: - if configDict["increase"]["allmix"] != None: - configModel["increase"]["allmix"] = configDict["increase"]["allmix"] - except Exception as e: - print("[ 警告 ]:allmix 增量更新未设置, 使用默认值False...\r\n") - try: - if configDict["increase"]["mix"] != None: - configModel["increase"]["mix"] = configDict["increase"]["mix"] - except Exception as e: - print("[ 警告 ]:mix 增量更新未设置, 使用默认值False...\r\n") - try: - if configDict["increase"]["music"] != None: - configModel["increase"]["music"] = configDict["increase"]["music"] - except Exception as e: - print("[ 警告 ]:music 增量更新未设置, 使用默认值False...\r\n") - try: - if configDict["thread"] != None: - configModel["thread"] = configDict["thread"] - except Exception as e: - print("[ 警告 ]:thread未设置, 使用默认值5...\r\n") - try: - if configDict["cookies"] != None: - cookiekey = configDict["cookies"].keys() - cookieStr = "" - for i in cookiekey: - cookieStr = cookieStr + i + "=" + configDict["cookies"][i] + "; " - configModel["cookie"] = cookieStr - except Exception as e: - pass - try: - if configDict["cookie"] != None: - configModel["cookie"] = configDict["cookie"] - except Exception as e: - pass - - -def main(): - start = time.time() # 开始时间 - - utils = Utils() - args = argument() - - if args.cmd: - configModel["link"] = args.link - configModel["path"] = args.path - configModel["music"] = args.music - configModel["cover"] = args.cover - configModel["avatar"] = args.avatar - configModel["json"] = args.json - if args.mode == None or args.mode == []: - args.mode = [] - args.mode.append("post") - configModel["mode"] = list(set(args.mode)) - configModel["number"]["post"] = args.postnumber - configModel["number"]["like"] = args.likenumber - configModel["number"]["allmix"] = args.allmixnumber - configModel["number"]["mix"] = args.mixnumber - configModel["number"]["music"] = args.musicnumber - configModel["increase"]["post"] = args.postincrease - configModel["increase"]["like"] = args.likeincrease - configModel["increase"]["allmix"] = args.allmixincrease - configModel["increase"]["mix"] = args.mixincrease - configModel["increase"]["music"] = args.musicincrease - configModel["thread"] = args.thread - configModel["cookie"] = args.cookie - else: - yamlConfig() - - if configModel["link"] == []: - return - - tk = TikTok() - - if configModel["cookie"] is not None and configModel["cookie"] != "": - tk.headers["Cookie"] = configModel["cookie"] - - configModel["path"] = os.path.abspath(configModel["path"]) - print("[ 提示 ]:数据保存路径 " + configModel["path"]) - if not os.path.exists(configModel["path"]): - os.mkdir(configModel["path"]) - - for link in configModel["link"]: - print("--------------------------------------------------------------------------------") - print("[ 提示 ]:正在请求的链接: " + link + "\r\n") - url = tk.getShareLink(link) - key_type, key = tk.getKey(url) - if key_type == "user": - print("[ 提示 ]:正在请求用户主页下作品\r\n") - userPath = os.path.join(configModel["path"], "user_" + key) - if not os.path.exists(userPath): - os.mkdir(userPath) - - for mode in configModel["mode"]: - print("--------------------------------------------------------------------------------") - print("[ 提示 ]:正在请求用户主页模式: " + mode + "\r\n") - if mode == 'post' or mode == 'like': - datalist = tk.getUserInfo(key, mode, 35, configModel["number"][mode], configModel["increase"][mode]) - if datalist is not None and datalist != []: - modePath = os.path.join(userPath, mode) - if not os.path.exists(modePath): - os.mkdir(modePath) - tk.userDownload(awemeList=datalist, music=configModel["music"], cover=configModel["cover"], - avatar=configModel["avatar"], resjson=configModel["json"], - savePath=modePath, thread=configModel["thread"]) - elif mode == 'mix': - mixIdNameDict = tk.getUserAllMixInfo(key, 35, configModel["number"]["allmix"]) - if mixIdNameDict is not None and mixIdNameDict != {}: - for mix_id in mixIdNameDict: - print(f'[ 提示 ]:正在下载合集 [{mixIdNameDict[mix_id]}] 中的作品\r\n') - mix_file_name = utils.replaceStr(mixIdNameDict[mix_id]) - datalist = tk.getMixInfo(mix_id, 35, 0, configModel["increase"]["allmix"], key) - if datalist is not None and datalist != []: - modePath = os.path.join(userPath, mode) - if not os.path.exists(modePath): - os.mkdir(modePath) - tk.userDownload(awemeList=datalist, music=configModel["music"], - cover=configModel["cover"], - avatar=configModel["avatar"], resjson=configModel["json"], - savePath=os.path.join(modePath, mix_file_name), - thread=configModel["thread"]) - print(f'[ 提示 ]:合集 [{mixIdNameDict[mix_id]}] 中的作品下载完成\r\n') - elif key_type == "mix": - print("[ 提示 ]:正在请求单个合集下作品\r\n") - datalist = tk.getMixInfo(key, 35, configModel["number"]["mix"], configModel["increase"]["mix"], "") - if datalist is not None and datalist != []: - mixPath = os.path.join(configModel["path"], "mix_" + key) - if not os.path.exists(mixPath): - os.mkdir(mixPath) - tk.userDownload(awemeList=datalist, music=configModel["music"], cover=configModel["cover"], - avatar=configModel["avatar"], resjson=configModel["json"], - savePath=mixPath, thread=configModel["thread"]) - elif key_type == "music": - print("[ 提示 ]:正在请求音乐(原声)下作品\r\n") - datalist = tk.getMusicInfo(key, 35, configModel["number"]["music"], configModel["increase"]["music"]) - if datalist is not None and datalist != []: - musicPath = os.path.join(configModel["path"], "music_" + key) - if not os.path.exists(musicPath): - os.mkdir(musicPath) - tk.userDownload(awemeList=datalist, music=configModel["music"], cover=configModel["cover"], - avatar=configModel["avatar"], resjson=configModel["json"], - savePath=musicPath, thread=configModel["thread"]) - elif key_type == "aweme": - print("[ 提示 ]:正在请求单个作品\r\n") - datanew, dataraw = tk.getAwemeInfo(key) - if datanew is not None and datanew != {}: - datalist = [] - datalist.append(datanew) - awemePath = os.path.join(configModel["path"], "aweme") - if not os.path.exists(awemePath): - os.mkdir(awemePath) - tk.userDownload(awemeList=datalist, music=configModel["music"], cover=configModel["cover"], - avatar=configModel["avatar"], resjson=configModel["json"], - savePath=awemePath, thread=configModel["thread"]) - elif key_type == "live": - print("[ 提示 ]:正在进行直播解析\r\n") - live_json = tk.getLiveInfo(key) - if configModel["json"]: - livePath = os.path.join(configModel["path"], "live") - if not os.path.exists(livePath): - os.mkdir(livePath) - live_file_name = utils.replaceStr(key + live_json["nickname"]) - # 保存获取到json - print("[ 提示 ]:正在保存获取到的信息到result.json\r\n") - with open(os.path.join(livePath, live_file_name + ".json"), "w", encoding='utf-8') as f: - f.write(json.dumps(live_json, ensure_ascii=False, indent=2)) - f.close() - - end = time.time() # 结束时间 - print('\n' + '[下载完成]:总耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间 - - -if __name__ == "__main__": - main() diff --git a/TikTokDataBase.py b/TikTokDataBase.py deleted file mode 100644 index 131293f..0000000 --- a/TikTokDataBase.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -''' -@FileName : TikTokDataBase.py -@Project : tiktok -@Description: -@Author : imgyh -@Mail : admin@imgyh.com -@Github : https://github.com/imgyh -@Site : https://www.imgyh.com -@Date : 2023/4/24 10:05 -@Version : v1.0 -@ChangeLog ------------------------------------------------- -使用数据库保存获取的状态信息 ------------------------------------------------- -''' - -import sqlite3 -import json - - -class db(object): - def __init__(self): - self.conn = sqlite3.connect('data.db') - self.cursor = self.conn.cursor() - self.create_user_post_table() - self.create_user_like_table() - self.create_mix_table() - self.create_music_table() - - def create_user_post_table(self): - sql = """CREATE TABLE if not exists t_user_post ( - id integer primary key autoincrement, - sec_uid varchar(200), - aweme_id integer unique, - rawdata json - );""" - - try: - self.cursor.execute(sql) - self.conn.commit() - except Exception as e: - pass - - def get_user_post(self, sec_uid: str, aweme_id: int): - sql = """select id, sec_uid, aweme_id, rawdata from t_user_post where sec_uid=? and aweme_id=?;""" - - try: - self.cursor.execute(sql, (sec_uid, aweme_id)) - self.conn.commit() - res = self.cursor.fetchone() - return res - except Exception as e: - pass - - def insert_user_post(self, sec_uid: str, aweme_id: int, data: dict): - insertsql = """insert into t_user_post (sec_uid, aweme_id, rawdata) values(?,?,?);""" - - try: - self.cursor.execute(insertsql, (sec_uid, aweme_id, json.dumps(data))) - self.conn.commit() - except Exception as e: - pass - - def create_user_like_table(self): - sql = """CREATE TABLE if not exists t_user_like ( - id integer primary key autoincrement, - sec_uid varchar(200), - aweme_id integer unique, - rawdata json - );""" - - try: - self.cursor.execute(sql) - self.conn.commit() - except Exception as e: - pass - - def get_user_like(self, sec_uid: str, aweme_id: int): - sql = """select id, sec_uid, aweme_id, rawdata from t_user_like where sec_uid=? and aweme_id=?;""" - - try: - self.cursor.execute(sql, (sec_uid, aweme_id)) - self.conn.commit() - res = self.cursor.fetchone() - return res - except Exception as e: - pass - - def insert_user_like(self, sec_uid: str, aweme_id: int, data: dict): - insertsql = """insert into t_user_like (sec_uid, aweme_id, rawdata) values(?,?,?);""" - - try: - self.cursor.execute(insertsql, (sec_uid, aweme_id, json.dumps(data))) - self.conn.commit() - except Exception as e: - pass - - def create_mix_table(self): - sql = """CREATE TABLE if not exists t_mix ( - id integer primary key autoincrement, - sec_uid varchar(200), - mix_id varchar(200), - aweme_id integer, - rawdata json - );""" - - try: - self.cursor.execute(sql) - self.conn.commit() - except Exception as e: - pass - - def get_mix(self, sec_uid: str, mix_id: str, aweme_id: int): - sql = """select id, sec_uid, mix_id, aweme_id, rawdata from t_mix where sec_uid=? and mix_id=? and aweme_id=?;""" - - try: - self.cursor.execute(sql, (sec_uid, mix_id, aweme_id)) - self.conn.commit() - res = self.cursor.fetchone() - return res - except Exception as e: - pass - - def insert_mix(self, sec_uid: str, mix_id: str, aweme_id: int, data: dict): - insertsql = """insert into t_mix (sec_uid, mix_id, aweme_id, rawdata) values(?,?,?,?);""" - - try: - self.cursor.execute(insertsql, (sec_uid, mix_id, aweme_id, json.dumps(data))) - self.conn.commit() - except Exception as e: - pass - - def create_music_table(self): - sql = """CREATE TABLE if not exists t_music ( - id integer primary key autoincrement, - music_id varchar(200), - aweme_id integer unique, - rawdata json - );""" - - try: - self.cursor.execute(sql) - self.conn.commit() - except Exception as e: - pass - - def get_music(self, music_id: str, aweme_id: int): - sql = """select id, music_id, aweme_id, rawdata from t_music where music_id=? and aweme_id=?;""" - - try: - self.cursor.execute(sql, (music_id, aweme_id)) - self.conn.commit() - res = self.cursor.fetchone() - return res - except Exception as e: - pass - - def insert_music(self, music_id: str, aweme_id: int, data: dict): - insertsql = """insert into t_music (music_id, aweme_id, rawdata) values(?,?,?);""" - - try: - self.cursor.execute(insertsql, (music_id, aweme_id, json.dumps(data))) - self.conn.commit() - except Exception as e: - pass - - -if __name__ == '__main__': - pass diff --git a/TikTokResult.py b/TikTokResult.py deleted file mode 100644 index 4a3b296..0000000 --- a/TikTokResult.py +++ /dev/null @@ -1,284 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/02/11 13:06:23 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' - -import time -import copy - - -class Result(object): - def __init__(self): - # 作者信息 - self.authorDict = { - "avatar_thumb": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "avatar": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "cover_url": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - # 喜欢的作品数 - "favoriting_count": "", - # 粉丝数 - "follower_count": "", - # 关注数 - "following_count": "", - # 昵称 - "nickname": "", - # 是否允许下载 - "prevent_download": "", - # 用户 url id - "sec_uid": "", - # 是否私密账号 - "secret": "", - # 短id - "short_id": "", - # 签名 - "signature": "", - # 总获赞数 - "total_favorited": "", - # 用户id - "uid": "", - # 用户自定义唯一id 抖音号 - "unique_id": "", - # 年龄 - "user_age": "", - - } - # 图片信息 - self.picDict = { - "height": "", - "mask_url_list": "", - "uri": "", - "url_list": [], - "width": "" - } - # 音乐信息 - self.musicDict = { - "cover_hd": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "cover_large": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "cover_medium": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "cover_thumb": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - # 音乐作者抖音号 - "owner_handle": "", - # 音乐作者id - "owner_id": "", - # 音乐作者昵称 - "owner_nickname": "", - "play_url": { - "height": "", - "uri": "", - "url_key": "", - "url_list": [], - "width": "" - }, - # 音乐名字 - "title": "", - } - # 视频信息 - self.videoDict = { - "play_addr": { - "uri": "", - "url_list": [], - }, - "cover_original_scale": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "dynamic_cover": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "origin_cover": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - }, - "cover": { - "height": "", - "uri": "", - "url_list": [], - "width": "" - } - } - # 作品信息 - self.awemeDict = { - # 作品创建时间 - "create_time": "", - # awemeType=0 视频, awemeType=1 图集, awemeType=2 直播 - "awemeType": "", - # 作品 id - "aweme_id": "", - # 作者信息 - "author": self.authorDict, - # 作品描述 - "desc": "", - # 图片 - "images": [], - # 音乐 - "music": self.musicDict, - # 视频 - "video": self.videoDict, - # 作品信息统计 - "statistics": { - "admire_count": "", - "collect_count": "", - "comment_count": "", - "digg_count": "", - "play_count": "", - "share_count": "" - } - } - # 用户作品信息 - self.awemeList = [] - # 直播信息 - self.liveDict = { - # awemeType=0 视频, awemeType=1 图集, awemeType=2 直播 - "awemeType": "", - # 是否在播 - "status": "", - # 直播标题 - "title": "", - # 直播cover - "cover": "", - # 头像 - "avatar": "", - # 观看人数 - "user_count": "", - # 昵称 - "nickname": "", - # sec_uid - "sec_uid": "", - # 直播间观看状态 - "display_long": "", - # 推流 - "flv_pull_url": "", - # 分区 - "partition": "", - "sub_partition": "", - # 最清晰的地址 - "flv_pull_url0": "", - } - - # 将得到的json数据(dataRaw)精简成自己定义的数据(dataNew) - # 转换得到的数据 - def dataConvert(self, awemeType, dataNew, dataRaw): - for item in dataNew: - try: - # 作品创建时间 - if item == "create_time": - dataNew['create_time'] = time.strftime( - "%Y-%m-%d %H.%M.%S", time.localtime(dataRaw['create_time'])) - continue - # 设置 awemeType - if item == "awemeType": - dataNew["awemeType"] = awemeType - continue - # 当 解析的链接 是图片时 - if item == "images": - if awemeType == 1: - for image in dataRaw[item]: - for i in image: - self.picDict[i] = image[i] - # 字典要深拷贝 - self.awemeDict["images"].append(copy.deepcopy(self.picDict)) - continue - # 当 解析的链接 是视频时 - if item == "video": - if awemeType == 0: - self.dataConvert(awemeType, dataNew[item], dataRaw[item]) - continue - # 将小头像放大 - if item == "avatar": - for i in dataNew[item]: - if i == "url_list": - for j in self.awemeDict["author"]["avatar_thumb"]["url_list"]: - dataNew[item][i].append(j.replace("100x100", "1080x1080")) - elif i == "uri": - dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i].replace("100x100", - "1080x1080") - else: - dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i] - continue - - # 原来的json是[{}] 而我们的是 {} - if item == "cover_url": - self.dataConvert(awemeType, dataNew[item], dataRaw[item][0]) - continue - - # 根据 uri 获取 1080p 视频 - if item == "play_addr": - dataNew[item]["uri"] = dataRaw["bit_rate"][0]["play_addr"]["uri"] - # 使用 这个api 可以获得1080p - # dataNew[item]["url_list"] = "https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0" \ - # % dataNew[item]["uri"] - dataNew[item]["url_list"] = copy.deepcopy(dataRaw["bit_rate"][0]["play_addr"]["url_list"]) - continue - - # 常规 递归遍历 字典 - if isinstance(dataNew[item], dict): - self.dataConvert(awemeType, dataNew[item], dataRaw[item]) - else: - # 赋值 - dataNew[item] = dataRaw[item] - except Exception as e: - # 删除这个警告, 总是让人误会出错了 - # print("[ 警告 ]:转换数据时在接口中未找到 %s\r" % (item)) - pass - - def clearDict(self, data): - for item in data: - # 常规 递归遍历 字典 - if isinstance(data[item], dict): - self.clearDict(data[item]) - elif isinstance(data[item], list): - data[item] = [] - else: - data[item] = "" diff --git a/TikTokTest.py b/TikTokTest.py deleted file mode 100644 index 57847bb..0000000 --- a/TikTokTest.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/02/11 13:06:23 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' -import TikTokUtils -from TikTok import TikTok - - -def getAwemeInfo(): - share_link_video = "3.56 uSy:/ 复制打开抖音,看看【小透明的作品】没有女朋友就用我的吧哈哈哈哈 # 表情包锁屏 https://v.douyin.com/BugmVVD/" - share_link_pic = "8.20 MJI:/ 复制打开抖音,看看【舍溪的图文作品】我又来放图集啦~还有你们要的小可爱大图也放啦~# ... https://v.douyin.com/BugrFTN/" - tk = TikTok() - - url = tk.getShareLink(share_link_pic) - key_type, key = tk.getKey(url) - datanew, dataraw = tk.getAwemeInfo(key) - print(datanew) - - -def getUserInfo(): - share_link_post = "1- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BupCppt/" - share_link_like = "2- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BusJrfr/" - tk = TikTok() - - url = tk.getShareLink(share_link_like) - key_type, key = tk.getKey(url) - awemeList = tk.getUserInfo(key, mode="like", count=35) - print(awemeList) - - -def getLiveInfo(): - live_link = "https://live.douyin.com/40768897856" - tk = TikTok() - - url = tk.getShareLink(live_link) - key_type, key = tk.getKey(url) - live_json = tk.getLiveInfo(key) - print(live_json) - - -def getMixInfo(): - mix_link = 'https://v.douyin.com/B3J63Le/' - tk = TikTok() - - url = tk.getShareLink(mix_link) - key_type, key = tk.getKey(url) - awemeList = tk.getMixInfo(key, count=35) - print(len(awemeList)) - - -def getUserAllMixInfo(): - user_all_mix_link = 'https://v.douyin.com/B38oovu/' - tk = TikTok() - - url = tk.getShareLink(user_all_mix_link) - key_type, key = tk.getKey(url) - mixIdNameDict = tk.getUserAllMixInfo(key, count=35) - print(mixIdNameDict) - - -def getMusicInfo(): - music_link = 'https://v.douyin.com/S6YMNXs/' - tk = TikTok() - - url = tk.getShareLink(music_link) - key_type, key = tk.getKey(url) - awemeList = tk.getMusicInfo(key, count=35) - print(len(awemeList)) - - -def test(): - utils = TikTokUtils.Utils() - user_all_mix_link = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?' + \ - utils.getXbogus( - url='device_platform=webapp&aid=6383&sec_user_id=MS4wLjABAAAAjQn6ONfaGgUpk0Q1ep8dPiD3W4T_lxTJmemfy3MTJ64&max_cursor=1676441180000&count=10') - headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', - 'referer': 'https://www.douyin.com/', - 'accept-encoding': None, - 'Cookie': 'ttwid=1|oLudm-Hi5ikxQQhmAnv4Km4LjwwvLa4Qk_JGrKffuYU|1681878460|b0f581d97797bb67d2260bf92d65e8808b90713afc08bf5d8100f571fd70a275; passport_csrf_token=570d671dcd8d8598fcde4c3f7c99664d; passport_csrf_token_default=570d671dcd8d8598fcde4c3f7c99664d; s_v_web_id=verify_lgn70gzw_sAVtjJdD_Clyk_43UL_8M9L_6JiTtPC2TyU0; n_mh=vrLGYVtwqutbPLOGNTDUGahwaD9AyYjn4iVvAO2Xt0s; sso_uid_tt=92e014dfb6653bdc319ecc6a6ceea870; sso_uid_tt_ss=92e014dfb6653bdc319ecc6a6ceea870; toutiao_sso_user=d0bd8d5cc0f75420799903572941ce83; toutiao_sso_user_ss=d0bd8d5cc0f75420799903572941ce83; passport_auth_status=5c576b088f4a19448eb4efd7aaeb7c5e,; passport_auth_status_ss=5c576b088f4a19448eb4efd7aaeb7c5e,; uid_tt=564215aecc985785d033c9e4c9d00fc4; uid_tt_ss=564215aecc985785d033c9e4c9d00fc4; sid_tt=f14390d924c81856fde84b1cd534bf09; sessionid=f14390d924c81856fde84b1cd534bf09; sessionid_ss=f14390d924c81856fde84b1cd534bf09; odin_tt=0aa1c100d17bf3541dce9e8dd62c6353302b8abaaa0a5998d5c437313feb245d8f7b6391a69772e4afa7d3c718878837; passport_assist_user=CjwC3fi9JyApG4DN-HiFI6n5FcGAdzNDT29nR-nSDJYAVfqh2BYI77qdTN2GRfgagkYLRi1wxNp1akHBwGcaSAo8XDkNT-UWnkFmc_0eXMYCb8OIh4G_YnH8pylwwdfS-7PCTekX3trj0JyENUVWLWFxnKuG5HhSS4FB2CtxEJ7yrg0Yia_WVCIBA9bY7IU=; sid_ucp_sso_v1=1.0.0-KDc0NmY3NzA5ZWFhNzI2YzMyOWMxMDMwNjAwMDg3YzRjYzg3ZjlhODcKHQjG-7zT9QEQ5dv9oQYY7zEgDDCL_7nMBTgGQPQHGgJscSIgZDBiZDhkNWNjMGY3NTQyMDc5OTkwMzU3Mjk0MWNlODM; ssid_ucp_sso_v1=1.0.0-KDc0NmY3NzA5ZWFhNzI2YzMyOWMxMDMwNjAwMDg3YzRjYzg3ZjlhODcKHQjG-7zT9QEQ5dv9oQYY7zEgDDCL_7nMBTgGQPQHGgJscSIgZDBiZDhkNWNjMGY3NTQyMDc5OTkwMzU3Mjk0MWNlODM; publish_badge_show_info="0,0,0,1681878505305"; LOGIN_STATUS=1; store-region=cn-sc; store-region-src=uid; sid_guard=f14390d924c81856fde84b1cd534bf09|1681878504|5183998|Sun,+18-Jun-2023+04:28:22+GMT; sid_ucp_v1=1.0.0-KGY5OGQ3OTQ4YmVkYzczODgzYzM0MmJmOWYxMzhkMDliMTc5NGI3NjMKGQjG-7zT9QEQ6Nv9oQYY7zEgDDgGQPQHSAQaAmxmIiBmMTQzOTBkOTI0YzgxODU2ZmRlODRiMWNkNTM0YmYwOQ; ssid_ucp_v1=1.0.0-KGY5OGQ3OTQ4YmVkYzczODgzYzM0MmJmOWYxMzhkMDliMTc5NGI3NjMKGQjG-7zT9QEQ6Nv9oQYY7zEgDDgGQPQHSAQaAmxmIiBmMTQzOTBkOTI0YzgxODU2ZmRlODRiMWNkNTM0YmYwOQ; download_guide="3/20230419"; pwa2="3|0"; FOLLOW_NUMBER_YELLOW_POINT_INFO="MS4wLjABAAAA-jD2lukp--I21BF8VQsmYUqJDbj3FmU-kGQTHl2y1Cw/1681920000000/0/0/1681900423333"; __ac_nonce=0644234d60042cacebbb6; __ac_signature=_02B4Z6wo00f01eZN0dAAAIDAhUcRuQz7dNHmbdVAAB3TRUC7i8VqXQejR8jv-D8UggBx1MBLH564PE.cCZf00m7Cw640CNUvcc5jJfhgn8u5FhvVndykvwbQb.HEpSfGN-8eqql7GpuGZJ8f1d; strategyABtestKey="1682060514.261"; passport_fe_beating_status=true; csrf_session_id=405b0ec4f6338a5d893a5f14f6fd1a64; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtY2xpZW50LWNlcnQiOiItLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS1cbk1JSUNGRENDQWJxZ0F3SUJBZ0lVR1ljQ3FuQUh0UUJBZm5WWkYxQW84cUtjY2Zrd0NnWUlLb1pJemowRUF3SXdcbk1URUxNQWtHQTFVRUJoTUNRMDR4SWpBZ0JnTlZCQU1NR1hScFkydGxkRjluZFdGeVpGOWpZVjlsWTJSellWOHlcbk5UWXdIaGNOTWpNd016STNNRE15T0RBeldoY05Nek13TXpJM01URXlPREF6V2pBbk1Rc3dDUVlEVlFRR0V3SkRcblRqRVlNQllHQTFVRUF3d1BZbVJmZEdsamEyVjBYMmQxWVhKa01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERcbkFRY0RRZ0FFNmZ1Z3d0MEJnZUh5akVub1FvNWtXUS9qc2daTTV1YXBiNTQ4KytTV0dRSjMwb2lSTHNtYlVFSUZcblFIYzh3UEthZzZmdXNPTm91WncxOEdNYm5vTStwNk9CdVRDQnRqQU9CZ05WSFE4QkFmOEVCQU1DQmFBd01RWURcblZSMGxCQ293S0FZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGQlFjREF3WUlLd1lCQlFVSEF3UXdcbktRWURWUjBPQkNJRUlPV3Y3d01ZUGhoeUNPL2ZwenJGNDJNeEQ4ZGIzN0YyTDgxaW8zVTVlVFpaTUNzR0ExVWRcbkl3UWtNQ0tBSURLbForcU9aRWdTamN4T1RVQjdjeFNiUjIxVGVxVFJnTmQ1bEpkN0lrZURNQmtHQTFVZEVRUVNcbk1CQ0NEbmQzZHk1a2IzVjVhVzR1WTI5dE1Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lCbm9xRDBRbVdUSlNLOVNcbkFZRjJ6YkljYzBsZjFRMDVTUGxXMURDQ0FMVUpBaUVBazJFRWpKdkdFRnl0YzBWbXRoRTA5bFpGeFFkUmlGN21cbk9pdE5IZzBOZUJrPVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLVxuIn0=; msToken=qSfWwAdwksuBS5wmQAvpzUsf2ovkFFKefOLSvZDKA1Z_FX7ith-wCknpVQB08kft4ISWp00GHeQBaPwV9tcWJq6xBC-mPnQKNjBVINeOQGvFtSdsfacWMtWpa8x1RJE=; FOLLOW_LIVE_POINT_INFO="MS4wLjABAAAA-jD2lukp--I21BF8VQsmYUqJDbj3FmU-kGQTHl2y1Cw/1682092800000/0/0/1682061497980"; msToken=jDwC5gjTRXV6hrFvGMG-AkOBXHGrt_Mp5NaltB1upOUm0aQnZ7sy7qlSEn2tQbGHShp2X7ayNMDQQlPekSTV9MkxBv56LR9zepTlYNOoqbH_RdjDvbl-MZDrmui3OEE=; tt_scid=hERl4ibL-B89BGXb9wUfsmVkQh-G2dvL2wI0QvEDYLooFsvwoz.q6J4ZA0WErn0Tb9fb; home_can_add_dy_2_desktop="1"'} - - import requests - - res = requests.get(user_all_mix_link, headers=headers).text - import json - datadict = json.loads(res) - print(datadict["aweme_list"][0]["video"]["bit_rate"]) - print(len(datadict["aweme_list"][0]["video"]["bit_rate"])) - - -if __name__ == "__main__": - # test() - # getMusicInfo() - # getUserAllMixInfo() - # getMixInfo() - # getAwemeInfo() - # getUserInfo() - # getLiveInfo() - pass diff --git a/TikTokUrls.py b/TikTokUrls.py deleted file mode 100644 index 2536171..0000000 --- a/TikTokUrls.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/02/11 13:06:23 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' - - -class Urls(object): - def __init__(self): - # https://langyue.cc/APIdocV1.0.html - ######################################### WEB ######################################### - # 首页推荐 - self.TAB_FEED = 'https://www.douyin.com/aweme/v1/web/tab/feed/?' - - # 用户短信息(给多少个用户secid就返回多少的用户信息) - self.USER_SHORT_INFO = 'https://www.douyin.com/aweme/v1/web/im/user/info/?' - - # 用户详细信息 - self.USER_DETAIL = 'https://www.douyin.com/aweme/v1/web/user/profile/other/?' - - # 用户作品 - # cookies 暂时只需要 __ac_signature, s_v_web_id两个参数, 好像会过期 - # url 暂时不需要携带 msToken, X-Bogus, _signature - # 每次返回数据很少 - # self.USER_POST = 'https://m.douyin.com/web/api/v2/aweme/post/?' - # 2023/02/19 失效 - self.USER_POST = 'https://www.douyin.com/aweme/v1/web/aweme/post/?' - - # 作品信息 - self.POST_DETAIL = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?' - - # 用户喜欢A - # 需要 odin_tt - self.USER_FAVORITE_A = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?' - - # 用户喜欢B - self.USER_FAVORITE_B = 'https://www.iesdouyin.com/web/api/v2/aweme/like/?' - - # 用户历史 - self.USER_HISTORY = 'https://www.douyin.com/aweme/v1/web/history/read/?' - - # 用户收藏 - self.USER_COLLECTION = 'https://www.douyin.com/aweme/v1/web/aweme/listcollection/?' - - # 用户评论 - self.COMMENT = 'https://www.douyin.com/aweme/v1/web/comment/list/?' - - # 首页朋友作品 - self.FRIEND_FEED = 'https://www.douyin.com/aweme/v1/web/familiar/feed/?' - - # 关注用户作品 - self.FOLLOW_FEED = 'https://www.douyin.com/aweme/v1/web/follow/feed/?' - - # 合集下所有作品 - # 只需要X-Bogus - self.USER_MIX = 'https://www.douyin.com/aweme/v1/web/mix/aweme/?' - - # 用户所有合集列表 - # 需要 ttwid - self.USER_MIX_LIST = 'https://www.douyin.com/aweme/v1/web/mix/list/?' - - # 直播 - self.LIVE = 'https://live.douyin.com/webcast/room/web/enter/?' - self.LIVE2 = 'https://webcast.amemv.com/webcast/room/reflow/info/?' - - # 音乐 - self.MUSIC = 'https://www.douyin.com/aweme/v1/web/music/aweme/?' - - # X-Bogus Path - # 60 秒内,请求同一URI累计超过 600 次,封锁IP 300 秒 - # 两个都可以用 - # 服务器在国外 - # self.GET_XB_PATH = 'https://tiktok.199933.xyz/xb' - # 服务器在国内 - self.GET_XB_PATH = 'http://47.115.208.101:9090/xb' - - ####################################################################################### - - -if __name__ == '__main__': - Urls() diff --git a/TikTokUtils.py b/TikTokUtils.py deleted file mode 100644 index dcd5b67..0000000 --- a/TikTokUtils.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/01/27 19:36:18 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' - -import random -import re -import requests -import execjs -import os -import sys -import json -from TikTokUrls import Urls - - -class Utils(object): - def __init__(self): - pass - - def generate_random_str(self, randomlength=16): - """ - 根据传入长度产生随机字符串 - """ - random_str = '' - base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789=' - length = len(base_str) - 1 - for _ in range(randomlength): - random_str += base_str[random.randint(0, length)] - return random_str - - def replaceStr(self, filenamestr: str): - """ - 替换非法字符,缩短字符长度,使其能成为文件名 - """ - # 匹配 汉字 字母 数字 空格 - match = "([0-9A-Za-z\u4e00-\u9fa5]+)" - - result = re.findall(match, filenamestr) - - result = "".join(result).strip() - if len(result) > 20: - result = result[:20] - # 去除前后空格 - return result - - def resource_path(self, relative_path): - if getattr(sys, 'frozen', False): # 是否Bundle Resource - base_path = sys._MEIPASS - else: - base_path = os.path.dirname(os.path.abspath(__file__)) - return os.path.join(base_path, relative_path) - - def getXbogus(self, url, headers=None): - # getXbogus算法开源地址https://github.com/B1gM8c/tiktok - user_agent = headers.get( - 'User-Agent') if headers else "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" - try: - xbogus = execjs.compile(open(self.resource_path(os.path.join("X-Bogus.js"))).read()).call('sign', url, - user_agent) - params = url + "&X-Bogus=" + xbogus - except Exception as e: - # print('[ 错误 ]:X-Bogus算法异常或者本地没有JS环境') - try: - # print('[ 提示 ]:尝试远程调用X-Bogus接口') - response = json.loads(requests.post( - url=Urls().GET_XB_PATH, data={"param": url}, headers=headers).text) - params = response["param"] - xbogus = response["X-Bogus"] - except Exception as e: - print('[ 错误 ]:X-Bogus获取异常') - return - return params - - def str2bool(self, v): - if isinstance(v, bool): - return v - if v.lower() in ('yes', 'true', 't', 'y', '1'): - return True - elif v.lower() in ('no', 'false', 'f', 'n', '0'): - return False - else: - return True - - # https://www.52pojie.cn/thread-1589242-1-1.html - def getttwid(self): - url = 'https://ttwid.bytedance.com/ttwid/union/register/' - data = '{"region":"cn","aid":1768,"needFid":false,"service":"www.ixigua.com","migrate_info":{"ticket":"","source":"node"},"cbUrlProtocol":"https","union":true}' - res = requests.post(url=url, data=data) - - for i, j in res.cookies.items(): - return j - - -if __name__ == "__main__": - pass diff --git a/TikTokWeb.py b/TikTokWeb.py deleted file mode 100644 index 6ccab0a..0000000 --- a/TikTokWeb.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- - -''' -@Description:TikTok.py -@Date :2023/01/27 19:36:18 -@Author :imgyh -@version :1.0 -@Github :https://github.com/imgyh -@Mail :admin@imgyh.com -------------------------------------------------- -Change Log : -------------------------------------------------- -''' - -from flask import * -from TikTok import TikTok -import argparse - - -def work(share_link, max_cursor, mode, cookie): - tk = TikTok() - - if cookie is not None and cookie != "": - tk.headers["Cookie"] = cookie - - url = tk.getShareLink(share_link) - key_type, key = tk.getKey(url) - - datalist = None - rawdatalist = None - cursor = None - has_more = None - if key_type == "user": - if mode == 'post' or mode == 'like': - datalist, rawdatalist, cursor, has_more = tk.getUserInfoApi(sec_uid=key, mode=mode, count=35, - max_cursor=max_cursor) - elif mode == 'mix': - datalist, rawdatalist, cursor, has_more = tk.getUserAllMixInfoApi(sec_uid=key, count=35, cursor=max_cursor) - elif key_type == "mix": - datalist, rawdatalist, cursor, has_more = tk.getMixInfoApi(mix_id=key, count=35, cursor=max_cursor) - elif key_type == "music": - datalist, rawdatalist, cursor, has_more = tk.getMusicInfoApi(music_id=key, count=35, cursor=max_cursor) - elif key_type == "aweme": - datalist, rawdatalist = tk.getAwemeInfoApi(aweme_id=key) - elif key_type == "live": - datalist, rawdatalist = tk.getLiveInfoApi(web_rid=key) - - datadict = {} - - if datalist is not None and datalist != []: - datadict["data"] = datalist - datadict["rawdata"] = rawdatalist - datadict["cursor"] = cursor - datadict["has_more"] = has_more - datadict["status_code"] = 200 - else: - datadict["status_code"] = 500 - return datadict - - -def deal(mode=None): - usefuldict = {} - if request.headers.get("content_type") == "application/json": - result = request.get_json(force=True) - else: - result = request.form - - share_link = None - cursor = 0 - cookie = None - - try: - share_link = result["share_link"] - cursor = result["cursor"] - cookie = result["cookie"] - except Exception as e: - usefuldict["status_code"] = 500 - - try: - if share_link is not None and share_link != "": - usefuldict = work(share_link, cursor, mode, cookie) - usefuldict["status_code"] = 200 - except Exception as e: - usefuldict["status_code"] = 500 - return jsonify(usefuldict) - - -app = Flask(__name__) -# 设置编码 -app.config['JSON_AS_ASCII'] = False - - -def argument(): - parser = argparse.ArgumentParser(description='抖音去水印工具 使用帮助') - parser.add_argument("--port", "-p", help="Web端口", - type=int, required=False, default=5000) - args = parser.parse_args() - - return args - - -@app.route("/douyin/music", methods=["POST"]) -def douyinMusic(): - return deal() - - -@app.route("/douyin/mix", methods=["POST"]) -def douyinMix(): - return deal() - - -@app.route("/douyin/user/mix", methods=["POST"]) -def douyinUserMix(): - return deal(mode="mix") - - -@app.route("/douyin/user/like", methods=["POST"]) -def douyinUserLike(): - return deal(mode="like") - - -@app.route("/douyin/user/post", methods=["POST"]) -def douyinUserPost(): - return deal(mode="post") - - -@app.route("/douyin/aweme", methods=["POST"]) -def douyinAweme(): - return deal() - - -@app.route("/douyin/live", methods=["POST"]) -def douyinLive(): - return deal() - - -@app.route("/douyin", methods=["POST"]) -def douyin(): - return deal() - - -@app.route("/", methods=["GET"]) -def index(): - return render_template("index.html") - - -if __name__ == "__main__": - args = argument() - app.run(debug=False, host="0.0.0.0", port=args.port) diff --git a/X-Bogus.js b/X-Bogus.js deleted file mode 100644 index 07b1b0e..0000000 --- a/X-Bogus.js +++ /dev/null @@ -1,564 +0,0 @@ -var window = null; - -function _0x5cd844(e) { - var b = { - exports: {} - }; - return e(b, b.exports), b.exports -} -jsvmp = function(e, b, a) { - function f(e, b, a) { - return (f = function() { - if ("undefined" == typeof Reflect || !Reflect.construct || Reflect.construct.sham) return !1; - if ("function" == typeof Proxy) return !0; - try { - return Date.prototype.toString.call(Reflect.construct(Date, [], function() {})), !0 - } catch (e) { - return !1 - } - }() ? Reflect.construct : function(e, b, a) { - var f = [null]; - f.push.apply(f, b); - var c = new(Function.bind.apply(e, f)); - return a && function(e, b) { - (Object.setPrototypeOf || function(e, b) { - return e.__proto__ = b, e - })(e, b) - }(c, a.prototype), c - }).apply(null, arguments) - } - - function c(e) { - return function(e) { - if (Array.isArray(e)) { - for (var b = 0, a = new Array(e.length); b < e.length; b++) a[b] = e[b]; - return a - } - }(e) || function(e) { - if (Symbol.iterator in Object(e) || "[object Arguments]" === Object.prototype.toString.call(e)) return Array.from(e) - }(e) || function() { - throw new TypeError("Invalid attempt to spread non-iterable instance") - }() - } - for (var r = [], t = 0, d = [], i = 0, n = function(e, b) { - var a = e[b++], - f = e[b], - c = parseInt("" + a + f, 16); - if (c >> 7 == 0) return [1, c]; - if (c >> 6 == 2) { - var r = parseInt("" + e[++b] + e[++b], 16); - return c &= 63, [2, r = (c <<= 8) + r] - } - if (c >> 6 == 3) { - var t = parseInt("" + e[++b] + e[++b], 16), - d = parseInt("" + e[++b] + e[++b], 16); - return c &= 63, [3, d = (c <<= 16) + (t <<= 8) + d] - } - }, s = function(e, b) { - var a = parseInt("" + e[b] + e[b + 1], 16); - return a > 127 ? -256 + a : a - }, o = function(e, b) { - var a = parseInt("" + e[b] + e[b + 1] + e[b + 2] + e[b + 3], 16); - return a > 32767 ? -65536 + a : a - }, l = function(e, b) { - var a = parseInt("" + e[b] + e[b + 1] + e[b + 2] + e[b + 3] + e[b + 4] + e[b + 5] + e[b + 6] + e[b + 7], 16); - return a > 2147483647 ? 0 + a : a - }, _ = function(e, b) { - return parseInt("" + e[b] + e[b + 1], 16) - }, x = function(e, b) { - return parseInt("" + e[b] + e[b + 1] + e[b + 2] + e[b + 3], 16) - }, u = u || this || window, h = (e.length, 0), p = "", y = h; y < h + 16; y++) { - var v = "" + e[y++] + e[y]; - v = parseInt(v, 16), p += String.fromCharCode(v) - } - if ("HNOJ@?RC" != p) throw new Error("error magic number " + p); - parseInt("" + e[h += 16] + e[h + 1], 16), h += 8, t = 0; - for (var g = 0; g < 4; g++) { - var w = h + 2 * g, - A = parseInt("" + e[w++] + e[w], 16); - t += (3 & A) << 2 * g - } - h += 16; - var C = parseInt("" + e[h += 8] + e[h + 1] + e[h + 2] + e[h + 3] + e[h + 4] + e[h + 5] + e[h + 6] + e[h + 7], 16), - m = C, - S = h += 8, - z = x(e, h += C); - z[1], h += 4, r = { - p: [], - q: [] - }; - for (var B = 0; B < z; B++) { - for (var R = n(e, h), q = h += 2 * R[0], I = r.p.length, k = 0; k < R[1]; k++) { - var j = n(e, q); - r.p.push(j[1]), q += 2 * j[0] - } - h = q, r.q.push([I, r.p.length]) - } - var O = { - 5: 1, - 6: 1, - 70: 1, - 22: 1, - 23: 1, - 37: 1, - 73: 1 - }, - U = { - 72: 1 - }, - D = { - 74: 1 - }, - N = { - 11: 1, - 12: 1, - 24: 1, - 26: 1, - 27: 1, - 31: 1 - }, - J = { - 10: 1 - }, - L = { - 2: 1, - 29: 1, - 30: 1, - 20: 1 - }, - T = [], - E = []; - - function M(e, b, a) { - for (var f = b; f < b + a;) { - var c = _(e, f); - T[f] = c, f += 2, U[c] ? (E[f] = s(e, f), f += 2) : O[c] ? (E[f] = o(e, f), f += 4) : D[c] ? (E[f] = l(e, f), f += 8) : N[c] ? (E[f] = _(e, f), f += 2) : J[c] ? (E[f] = x(e, f), f += 4) : L[c] && (E[f] = x(e, f), f += 4) - } - } - return F(e, S, m / 2, [], b, a); - - function P(e, b, a, n, h, p, y, v) { - null == p && (p = this); - var g, w, A, C, m = [], - S = 0; - y && (w = y); - var z, B, R = b, - q = R + 2 * a; - if (!v) - for (; R < q;) { - var I = parseInt("" + e[R] + e[R + 1], 16); - R += 2; - var j = 3 & (z = 13 * I % 241); - if (z >>= 2, j < 1) - if (j = 3 & z, z >>= 2, j < 1) { - if ((j = z) < 1) return [1, m[S--]]; - j < 5 ? (w = m[S--], m[S] = m[S] * w) : j < 7 ? (w = m[S--], m[S] = m[S] != w) : j < 14 ? (A = m[S--], C = m[S--], (j = m[S--]).x === P ? j.y >= 1 ? m[++S] = F(e, j.c, j.l, A, j.z, C, null, 1) : (m[++S] = F(e, j.c, j.l, A, j.z, C, null, 0), j.y++) : m[++S] = j.apply(C, A)) : j < 16 && (B = o(e, R), (g = function b() { - var a = arguments; - return b.y > 0 || b.y++, F(e, b.c, b.l, a, b.z, this, null, 0) - }).c = R + 4, g.l = B - 2, g.x = P, g.y = 0, g.z = h, m[S] = g, R += 2 * B - 2) - } else if (j < 2)(j = z) > 8 ? (w = m[S--], m[S] = typeof w) : j > 4 ? m[S -= 1] = m[S][m[S + 1]] : j > 2 && (A = m[S--], (j = m[S]).x === P ? j.y >= 1 ? m[S] = F(e, j.c, j.l, [A], j.z, C, null, 1) : (m[S] = F(e, j.c, j.l, [A], j.z, C, null, 0), j.y++) : m[S] = j(A)); - else if (j < 3) { - if ((j = z) < 9) { - for (w = m[S--], B = x(e, R), j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - R += 4, m[S--][j] = w - } else if (j < 13) throw m[S--] - } else(j = z) < 1 ? m[++S] = null : j < 3 ? (w = m[S--], m[S] = m[S] >= w) : j < 12 && (m[++S] = void 0); - else if (j < 2) - if (j = 3 & z, z >>= 2, j < 1) - if ((j = z) < 5) { - B = o(e, R); - try { - if (d[i][2] = 1, 1 == (w = P(e, R + 4, B - 3, [], h, p, null, 0))[0]) return w - } catch (b) { - if (d[i] && d[i][1] && 1 == (w = P(e, d[i][1][0], d[i][1][1], [], h, p, b, 0))[0]) return w - } finally { - if (d[i] && d[i][0] && 1 == (w = P(e, d[i][0][0], d[i][0][1], [], h, p, null, 0))[0]) return w; - d[i] = 0, i-- - } - R += 2 * B - 2 - } else j < 7 ? (B = _(e, R), R += 2, m[S -= B] = 0 === B ? new m[S] : f(m[S], c(m.slice(S + 1, S + B + 1)))) : j < 9 && (w = m[S--], m[S] = m[S] & w); - else if (j < 2) - if ((j = z) > 12) m[++S] = s(e, R), R += 2; - else if (j > 10) w = m[S--], m[S] = m[S] << w; - else if (j > 8) { - for (B = x(e, R), j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - R += 4, m[S] = m[S][j] - } else j > 6 && (A = m[S--], w = delete m[S--][A]); - else if (j < 3)(j = z) < 2 ? m[++S] = w : j < 11 ? (w = m[S -= 2][m[S + 1]] = m[S + 2], S--) : j < 13 && (w = m[S], m[++S] = w); - else if ((j = z) > 12) m[++S] = p; - else if (j > 5) w = m[S--], m[S] = m[S] !== w; - else if (j > 3) w = m[S--], m[S] = m[S] / w; - else if (j > 1) { - if ((B = o(e, R)) < 0) { - v = 1, M(e, b, 2 * a), R += 2 * B - 2; - break - } - R += 2 * B - 2 - } else j > -1 && (m[S] = !m[S]); - else if (j < 3) - if (j = 3 & z, z >>= 2, j < 1)(j = z) > 13 ? (m[++S] = o(e, R), R += 4) : j > 11 ? (w = m[S--], m[S] = m[S] >> w) : j > 9 ? (B = _(e, R), R += 2, w = m[S--], h[B] = w) : j > 7 ? (B = x(e, R), R += 4, A = S + 1, m[S -= B - 1] = B ? m.slice(S, A) : []) : j > 0 && (w = m[S--], m[S] = m[S] > w); - else if (j < 2)(j = z) > 12 ? (w = m[S - 1], A = m[S], m[++S] = w, m[++S] = A) : j > 3 ? (w = m[S--], m[S] = m[S] == w) : j > 1 ? (w = m[S--], m[S] = m[S] + w) : j > -1 && (m[++S] = u); - else if (j < 3) { - if ((j = z) > 13) m[++S] = !1; - else if (j > 6) w = m[S--], m[S] = m[S] instanceof w; - else if (j > 4) w = m[S--], m[S] = m[S] % w; - else if (j > 2) - if (m[S--]) R += 4; - else { - if ((B = o(e, R)) < 0) { - v = 1, M(e, b, 2 * a), R += 2 * B - 2; - break - } - R += 2 * B - 2 - } - else if (j > 0) { - for (B = x(e, R), w = "", k = r.q[B][0]; k < r.q[B][1]; k++) w += String.fromCharCode(t ^ r.p[k]); - m[++S] = w, R += 4 - } - } else(j = z) > 7 ? (w = m[S--], m[S] = m[S] | w) : j > 5 ? (B = _(e, R), R += 2, m[++S] = h["$" + B]) : j > 3 && (B = o(e, R), d[i][0] && !d[i][2] ? d[i][1] = [R + 4, B - 3] : d[i++] = [0, [R + 4, B - 3], 0], R += 2 * B - 2); - else if (j = 3 & z, z >>= 2, j > 2)(j = z) > 13 ? (m[++S] = l(e, R), R += 8) : j > 11 ? (w = m[S--], m[S] = m[S] >>> w) : j > 9 ? m[++S] = !0 : j > 7 ? (B = _(e, R), R += 2, m[S] = m[S][B]) : j > 0 && (w = m[S--], m[S] = m[S] < w); - else if (j > 1)(j = z) > 10 ? (B = o(e, R), d[++i] = [ - [R + 4, B - 3], 0, 0 - ], R += 2 * B - 2) : j > 8 ? (w = m[S--], m[S] = m[S] ^ w) : j > 6 && (w = m[S--]); - else if (j > 0) { - if ((j = z) > 7) w = m[S--], m[S] = m[S] in w; - else if (j > 5) m[S] = ++m[S]; - else if (j > 3) B = _(e, R), R += 2, w = h[B], m[++S] = w; - else if (j > 1) { - var O = 0, - U = m[S].length, - D = m[S]; - m[++S] = function() { - var e = O < U; - if (e) { - var b = D[O++]; - m[++S] = b - } - m[++S] = e - } - } - } else if ((j = z) > 13) w = m[S], m[S] = m[S - 1], m[S - 1] = w; - else if (j > 4) w = m[S--], m[S] = m[S] === w; - else if (j > 2) w = m[S--], m[S] = m[S] - w; - else if (j > 0) { - for (B = x(e, R), j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - j = +j, R += 4, m[++S] = j - } - } - if (v) - for (; R < q;) - if (I = T[R], R += 2, j = 3 & (z = 13 * I % 241), z >>= 2, j > 2) - if (j = 3 & z, z >>= 2, j > 2)(j = z) < 2 ? (w = m[S--], m[S] = m[S] < w) : j < 9 ? (B = E[R], R += 2, m[S] = m[S][B]) : j < 11 ? m[++S] = !0 : j < 13 ? (w = m[S--], m[S] = m[S] >>> w) : j < 15 && (m[++S] = E[R], R += 8); - else if (j > 1)(j = z) < 6 || (j < 8 ? w = m[S--] : j < 10 ? (w = m[S--], m[S] = m[S] ^ w) : j < 12 && (B = E[R], d[++i] = [ - [R + 4, B - 3], 0, 0 - ], R += 2 * B - 2)); - else if (j > 0)(j = z) > 7 ? (w = m[S--], m[S] = m[S] in w) : j > 5 ? m[S] = ++m[S] : j > 3 ? (B = E[R], R += 2, w = h[B], m[++S] = w) : j > 1 && (O = 0, U = m[S].length, D = m[S], m[++S] = function() { - var e = O < U; - if (e) { - var b = D[O++]; - m[++S] = b - } - m[++S] = e - }); - else if ((j = z) < 2) { - for (B = E[R], j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - j = +j, R += 4, m[++S] = j - } else j < 4 ? (w = m[S--], m[S] = m[S] - w) : j < 6 ? (w = m[S--], m[S] = m[S] === w) : j < 15 && (w = m[S], m[S] = m[S - 1], m[S - 1] = w); - else if (j > 1) - if (j = 3 & z, z >>= 2, j < 1)(j = z) > 13 ? (m[++S] = E[R], R += 4) : j > 11 ? (w = m[S--], m[S] = m[S] >> w) : j > 9 ? (B = E[R], R += 2, w = m[S--], h[B] = w) : j > 7 ? (B = E[R], R += 4, A = S + 1, m[S -= B - 1] = B ? m.slice(S, A) : []) : j > 0 && (w = m[S--], m[S] = m[S] > w); - else if (j < 2)(j = z) < 1 ? m[++S] = u : j < 3 ? (w = m[S--], m[S] = m[S] + w) : j < 5 ? (w = m[S--], m[S] = m[S] == w) : j < 14 && (w = m[S - 1], A = m[S], m[++S] = w, m[++S] = A); - else if (j < 3) { - if ((j = z) > 13) m[++S] = !1; - else if (j > 6) w = m[S--], m[S] = m[S] instanceof w; - else if (j > 4) w = m[S--], m[S] = m[S] % w; - else if (j > 2) m[S--] ? R += 4 : R += 2 * (B = E[R]) - 2; - else if (j > 0) { - for (B = E[R], w = "", k = r.q[B][0]; k < r.q[B][1]; k++) w += String.fromCharCode(t ^ r.p[k]); - m[++S] = w, R += 4 - } - } else(j = z) > 7 ? (w = m[S--], m[S] = m[S] | w) : j > 5 ? (B = E[R], R += 2, m[++S] = h["$" + B]) : j > 3 && (B = E[R], d[i][0] && !d[i][2] ? d[i][1] = [R + 4, B - 3] : d[i++] = [0, [R + 4, B - 3], 0], R += 2 * B - 2); - else if (j > 0) - if (j = 3 & z, z >>= 2, j < 1) { - if ((j = z) > 9); - else if (j > 7) w = m[S--], m[S] = m[S] & w; - else if (j > 5) B = E[R], R += 2, m[S -= B] = 0 === B ? new m[S] : f(m[S], c(m.slice(S + 1, S + B + 1))); - else if (j > 3) { - B = E[R]; - try { - if (d[i][2] = 1, 1 == (w = P(e, R + 4, B - 3, [], h, p, null, 0))[0]) return w - } catch (b) { - if (d[i] && d[i][1] && 1 == (w = P(e, d[i][1][0], d[i][1][1], [], h, p, b, 0))[0]) return w - } finally { - if (d[i] && d[i][0] && 1 == (w = P(e, d[i][0][0], d[i][0][1], [], h, p, null, 0))[0]) return w; - d[i] = 0, i-- - } - R += 2 * B - 2 - } - } else if (j < 2) - if ((j = z) < 8) A = m[S--], w = delete m[S--][A]; - else if (j < 10) { - for (B = E[R], j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - R += 4, m[S] = m[S][j] - } else j < 12 ? (w = m[S--], m[S] = m[S] << w) : j < 14 && (m[++S] = E[R], R += 2); - else j < 3 ? (j = z) < 2 ? m[++S] = w : j < 11 ? (w = m[S -= 2][m[S + 1]] = m[S + 2], S--) : j < 13 && (w = m[S], m[++S] = w) : (j = z) > 12 ? m[++S] = p : j > 5 ? (w = m[S--], m[S] = m[S] !== w) : j > 3 ? (w = m[S--], m[S] = m[S] / w) : j > 1 ? R += 2 * (B = E[R]) - 2 : j > -1 && (m[S] = !m[S]); - else if (j = 3 & z, z >>= 2, j < 1) { - if ((j = z) < 1) return [1, m[S--]]; - j < 5 ? (w = m[S--], m[S] = m[S] * w) : j < 7 ? (w = m[S--], m[S] = m[S] != w) : j < 14 ? (A = m[S--], C = m[S--], (j = m[S--]).x === P ? j.y >= 1 ? m[++S] = F(e, j.c, j.l, A, j.z, C, null, 1) : (m[++S] = F(e, j.c, j.l, A, j.z, C, null, 0), j.y++) : m[++S] = j.apply(C, A)) : j < 16 && (B = E[R], (g = function b() { - var a = arguments; - return b.y > 0 || b.y++, F(e, b.c, b.l, a, b.z, this, null, 0) - }).c = R + 4, g.l = B - 2, g.x = P, g.y = 0, g.z = h, m[S] = g, R += 2 * B - 2) - } else if (j < 2)(j = z) > 8 ? (w = m[S--], m[S] = typeof w) : j > 4 ? m[S -= 1] = m[S][m[S + 1]] : j > 2 && (A = m[S--], (j = m[S]).x === P ? j.y >= 1 ? m[S] = F(e, j.c, j.l, [A], j.z, C, null, 1) : (m[S] = F(e, j.c, j.l, [A], j.z, C, null, 0), j.y++) : m[S] = j(A)); - else if (j < 3) { - if ((j = z) < 9) { - for (w = m[S--], B = E[R], j = "", k = r.q[B][0]; k < r.q[B][1]; k++) j += String.fromCharCode(t ^ r.p[k]); - R += 4, m[S--][j] = w - } else if (j < 13) throw m[S--] - } else(j = z) < 1 ? m[++S] = null : j < 3 ? (w = m[S--], m[S] = m[S] >= w) : j < 12 && (m[++S] = void 0); - return [0, null] - } - - function F(e, b, a, f, c, r, t, d) { - null == r && (r = this), c && !c.d && (c.d = 0, c.$0 = c, c[1] = {}); - var i, n, s = {}, - o = s.d = c ? c.d + 1 : 0; - for (s["$" + o] = s, n = 0; n < o; n++) s[i = "$" + n] = c[i]; - for (n = 0, o = s.length = f.length; n < o; n++) s[n] = f[n]; - return d && !T[b] && M(e, b, 2 * a), T[b] ? P(e, b, a, 0, s, r, null, 1)[1] : P(e, b, a, 0, s, r, null, 0)[1] - } -}; -var _0x397dc7 = "undefined" != typeof globalThis ? globalThis : void 0 !== window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}, - _0x124d1a = _0x5cd844(function(_0x770f81) { - ! function() { - var _0x250d36 = "input is invalid type", - _0x4cfaee = !1, - _0x1702f9 = {}, - _0x5ccbb3 = !_0x4cfaee && "object" == typeof self, - _0x54d876 = !_0x1702f9.JS_MD5_NO_NODE_JS && "object" == typeof process && process.versions && process.versions.node, - _0x185caf; - _0x54d876 ? _0x1702f9 = _0x397dc7 : _0x5ccbb3 && (_0x1702f9 = self); - var _0x17dcbf = !_0x1702f9.JS_MD5_NO_COMMON_JS && _0x770f81.exports, - _0x554fed = !1, - _0x2de28f = !_0x1702f9.JS_MD5_NO_ARRAY_BUFFER && "undefined" != typeof ArrayBuffer, - _0x3a9a1b = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"], - _0x465562 = [128, 32768, 8388608, -2147483648], - _0x20b37e = [0, 8, 16, 24], - _0x323604 = ["hex", "array", "digest", "buffer", "arrayBuffer", "base64"], - _0x2c185e = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"], - _0x4b59e0 = []; - if (_0x2de28f) { - var _0x395837 = new ArrayBuffer(68); - _0x185caf = new Uint8Array(_0x395837), _0x4b59e0 = new Uint32Array(_0x395837) - }!_0x1702f9.JS_MD5_NO_NODE_JS && Array.isArray || (Array.isArray = function(e) { - return "[object Array]" === Object.prototype.toString.call(e) - }), _0x2de28f && (_0x1702f9.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView) && (ArrayBuffer.isView = function(e) { - return "object" == typeof e && e.buffer && e.buffer.constructor === ArrayBuffer - }); - var _0x4e9930 = function(e) { - return function(b) { - return new _0x5887c8(!0).update(b)[e]() - } - }, - _0x38ba77 = function() { - var e = _0x4e9930("hex"); - _0x54d876 && (e = _0x474989(e)), e.create = function() { - return new _0x5887c8 - }, e.update = function(b) { - return e.create().update(b) - }; - for (var b = 0; b < _0x323604.length; ++b) { - var a = _0x323604[b]; - e[a] = _0x4e9930(a) - } - return e - }, - _0x474989 = function(_0x57eeaa) { - var _0x114910, _0x226465 = eval("require('crypto');"), - _0x1f6ae0 = eval("require('buffer')['Buffer'];"); - return function(e) { - if ("string" == typeof e) return _0x226465.createHash("md5").update(e, "utf8").digest("hex"); - if (null == e) throw _0x250d36; - return e.constructor === ArrayBuffer && (e = new Uint8Array(e)), Array.isArray(e) || ArrayBuffer.isView(e) || e.constructor === _0x1f6ae0 ? _0x226465.createHash("md5").update(new _0x1f6ae0.from(e)).digest("hex") : _0x57eeaa(e) - } - }; - - function _0x5887c8(e) { - if (e) _0x4b59e0[0] = _0x4b59e0[16] = _0x4b59e0[1] = _0x4b59e0[2] = _0x4b59e0[3] = _0x4b59e0[4] = _0x4b59e0[5] = _0x4b59e0[6] = _0x4b59e0[7] = _0x4b59e0[8] = _0x4b59e0[9] = _0x4b59e0[10] = _0x4b59e0[11] = _0x4b59e0[12] = _0x4b59e0[13] = _0x4b59e0[14] = _0x4b59e0[15] = 0, this.blocks = _0x4b59e0, this.buffer8 = _0x185caf; - else if (_0x2de28f) { - var b = new ArrayBuffer(68); - this.buffer8 = new Uint8Array(b), this.blocks = new Uint32Array(b) - } else this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0, this.finalized = this.hashed = !1, this.first = !0 - } - _0x5887c8.prototype.update = function(e) { - if (!this.finalized) { - var b, a = typeof e; - if ("string" !== a) { - if ("object" !== a || null === e) throw _0x250d36; - if (_0x2de28f && e.constructor === ArrayBuffer) e = new Uint8Array(e); - else if (!(Array.isArray(e) || _0x2de28f && ArrayBuffer.isView(e))) throw _0x250d36; - b = !0 - } - for (var f, c, r = 0, t = e.length, d = this.blocks, i = this.buffer8; r < t;) { - if (this.hashed && (this.hashed = !1, d[0] = d[16], d[16] = d[1] = d[2] = d[3] = d[4] = d[5] = d[6] = d[7] = d[8] = d[9] = d[10] = d[11] = d[12] = d[13] = d[14] = d[15] = 0), b) - if (_0x2de28f) - for (c = this.start; r < t && c < 64; ++r) i[c++] = e[r]; - else - for (c = this.start; r < t && c < 64; ++r) d[c >> 2] |= e[r] << _0x20b37e[3 & c++]; - else if (_0x2de28f) - for (c = this.start; r < t && c < 64; ++r)(f = e.charCodeAt(r)) < 128 ? i[c++] = f : f < 2048 ? (i[c++] = 192 | f >> 6, i[c++] = 128 | 63 & f) : f < 55296 || f >= 57344 ? (i[c++] = 224 | f >> 12, i[c++] = 128 | f >> 6 & 63, i[c++] = 128 | 63 & f) : (f = 65536 + ((1023 & f) << 10 | 1023 & e.charCodeAt(++r)), i[c++] = 240 | f >> 18, i[c++] = 128 | f >> 12 & 63, i[c++] = 128 | f >> 6 & 63, i[c++] = 128 | 63 & f); - else - for (c = this.start; r < t && c < 64; ++r)(f = e.charCodeAt(r)) < 128 ? d[c >> 2] |= f << _0x20b37e[3 & c++] : f < 2048 ? (d[c >> 2] |= (192 | f >> 6) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | 63 & f) << _0x20b37e[3 & c++]) : f < 55296 || f >= 57344 ? (d[c >> 2] |= (224 | f >> 12) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | f >> 6 & 63) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | 63 & f) << _0x20b37e[3 & c++]) : (f = 65536 + ((1023 & f) << 10 | 1023 & e.charCodeAt(++r)), d[c >> 2] |= (240 | f >> 18) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | f >> 12 & 63) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | f >> 6 & 63) << _0x20b37e[3 & c++], d[c >> 2] |= (128 | 63 & f) << _0x20b37e[3 & c++]); - this.lastByteIndex = c, this.bytes += c - this.start, c >= 64 ? (this.start = c - 64, this.hash(), this.hashed = !0) : this.start = c - } - return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0, this.bytes = this.bytes % 4294967296), this - } - }, _0x5887c8.prototype.finalize = function() { - if (!this.finalized) { - this.finalized = !0; - var e = this.blocks, - b = this.lastByteIndex; - e[b >> 2] |= _0x465562[3 & b], b >= 56 && (this.hashed || this.hash(), e[0] = e[16], e[16] = e[1] = e[2] = e[3] = e[4] = e[5] = e[6] = e[7] = e[8] = e[9] = e[10] = e[11] = e[12] = e[13] = e[14] = e[15] = 0), e[14] = this.bytes << 3, e[15] = this.hBytes << 3 | this.bytes >>> 29, this.hash() - } - }, _0x5887c8.prototype.hash = function() { - var e, b, a, f, c, r, t = this.blocks; - this.first ? b = ((b = ((e = ((e = t[0] - 680876937) << 7 | e >>> 25) - 271733879 << 0) ^ (a = ((a = (-271733879 ^ (f = ((f = (-1732584194 ^ 2004318071 & e) + t[1] - 117830708) << 12 | f >>> 20) + e << 0) & (-271733879 ^ e)) + t[2] - 1126478375) << 17 | a >>> 15) + f << 0) & (f ^ e)) + t[3] - 1316259209) << 22 | b >>> 10) + a << 0 : (e = this.h0, b = this.h1, a = this.h2, b = ((b += ((e = ((e += ((f = this.h3) ^ b & (a ^ f)) + t[0] - 680876936) << 7 | e >>> 25) + b << 0) ^ (a = ((a += (b ^ (f = ((f += (a ^ e & (b ^ a)) + t[1] - 389564586) << 12 | f >>> 20) + e << 0) & (e ^ b)) + t[2] + 606105819) << 17 | a >>> 15) + f << 0) & (f ^ e)) + t[3] - 1044525330) << 22 | b >>> 10) + a << 0), b = ((b += ((e = ((e += (f ^ b & (a ^ f)) + t[4] - 176418897) << 7 | e >>> 25) + b << 0) ^ (a = ((a += (b ^ (f = ((f += (a ^ e & (b ^ a)) + t[5] + 1200080426) << 12 | f >>> 20) + e << 0) & (e ^ b)) + t[6] - 1473231341) << 17 | a >>> 15) + f << 0) & (f ^ e)) + t[7] - 45705983) << 22 | b >>> 10) + a << 0, b = ((b += ((e = ((e += (f ^ b & (a ^ f)) + t[8] + 1770035416) << 7 | e >>> 25) + b << 0) ^ (a = ((a += (b ^ (f = ((f += (a ^ e & (b ^ a)) + t[9] - 1958414417) << 12 | f >>> 20) + e << 0) & (e ^ b)) + t[10] - 42063) << 17 | a >>> 15) + f << 0) & (f ^ e)) + t[11] - 1990404162) << 22 | b >>> 10) + a << 0, b = ((b += ((e = ((e += (f ^ b & (a ^ f)) + t[12] + 1804603682) << 7 | e >>> 25) + b << 0) ^ (a = ((a += (b ^ (f = ((f += (a ^ e & (b ^ a)) + t[13] - 40341101) << 12 | f >>> 20) + e << 0) & (e ^ b)) + t[14] - 1502002290) << 17 | a >>> 15) + f << 0) & (f ^ e)) + t[15] + 1236535329) << 22 | b >>> 10) + a << 0, b = ((b += ((f = ((f += (b ^ a & ((e = ((e += (a ^ f & (b ^ a)) + t[1] - 165796510) << 5 | e >>> 27) + b << 0) ^ b)) + t[6] - 1069501632) << 9 | f >>> 23) + e << 0) ^ e & ((a = ((a += (e ^ b & (f ^ e)) + t[11] + 643717713) << 14 | a >>> 18) + f << 0) ^ f)) + t[0] - 373897302) << 20 | b >>> 12) + a << 0, b = ((b += ((f = ((f += (b ^ a & ((e = ((e += (a ^ f & (b ^ a)) + t[5] - 701558691) << 5 | e >>> 27) + b << 0) ^ b)) + t[10] + 38016083) << 9 | f >>> 23) + e << 0) ^ e & ((a = ((a += (e ^ b & (f ^ e)) + t[15] - 660478335) << 14 | a >>> 18) + f << 0) ^ f)) + t[4] - 405537848) << 20 | b >>> 12) + a << 0, b = ((b += ((f = ((f += (b ^ a & ((e = ((e += (a ^ f & (b ^ a)) + t[9] + 568446438) << 5 | e >>> 27) + b << 0) ^ b)) + t[14] - 1019803690) << 9 | f >>> 23) + e << 0) ^ e & ((a = ((a += (e ^ b & (f ^ e)) + t[3] - 187363961) << 14 | a >>> 18) + f << 0) ^ f)) + t[8] + 1163531501) << 20 | b >>> 12) + a << 0, b = ((b += ((f = ((f += (b ^ a & ((e = ((e += (a ^ f & (b ^ a)) + t[13] - 1444681467) << 5 | e >>> 27) + b << 0) ^ b)) + t[2] - 51403784) << 9 | f >>> 23) + e << 0) ^ e & ((a = ((a += (e ^ b & (f ^ e)) + t[7] + 1735328473) << 14 | a >>> 18) + f << 0) ^ f)) + t[12] - 1926607734) << 20 | b >>> 12) + a << 0, b = ((b += ((r = (f = ((f += ((c = b ^ a) ^ (e = ((e += (c ^ f) + t[5] - 378558) << 4 | e >>> 28) + b << 0)) + t[8] - 2022574463) << 11 | f >>> 21) + e << 0) ^ e) ^ (a = ((a += (r ^ b) + t[11] + 1839030562) << 16 | a >>> 16) + f << 0)) + t[14] - 35309556) << 23 | b >>> 9) + a << 0, b = ((b += ((r = (f = ((f += ((c = b ^ a) ^ (e = ((e += (c ^ f) + t[1] - 1530992060) << 4 | e >>> 28) + b << 0)) + t[4] + 1272893353) << 11 | f >>> 21) + e << 0) ^ e) ^ (a = ((a += (r ^ b) + t[7] - 155497632) << 16 | a >>> 16) + f << 0)) + t[10] - 1094730640) << 23 | b >>> 9) + a << 0, b = ((b += ((r = (f = ((f += ((c = b ^ a) ^ (e = ((e += (c ^ f) + t[13] + 681279174) << 4 | e >>> 28) + b << 0)) + t[0] - 358537222) << 11 | f >>> 21) + e << 0) ^ e) ^ (a = ((a += (r ^ b) + t[3] - 722521979) << 16 | a >>> 16) + f << 0)) + t[6] + 76029189) << 23 | b >>> 9) + a << 0, b = ((b += ((r = (f = ((f += ((c = b ^ a) ^ (e = ((e += (c ^ f) + t[9] - 640364487) << 4 | e >>> 28) + b << 0)) + t[12] - 421815835) << 11 | f >>> 21) + e << 0) ^ e) ^ (a = ((a += (r ^ b) + t[15] + 530742520) << 16 | a >>> 16) + f << 0)) + t[2] - 995338651) << 23 | b >>> 9) + a << 0, b = ((b += ((f = ((f += (b ^ ((e = ((e += (a ^ (b | ~f)) + t[0] - 198630844) << 6 | e >>> 26) + b << 0) | ~a)) + t[7] + 1126891415) << 10 | f >>> 22) + e << 0) ^ ((a = ((a += (e ^ (f | ~b)) + t[14] - 1416354905) << 15 | a >>> 17) + f << 0) | ~e)) + t[5] - 57434055) << 21 | b >>> 11) + a << 0, b = ((b += ((f = ((f += (b ^ ((e = ((e += (a ^ (b | ~f)) + t[12] + 1700485571) << 6 | e >>> 26) + b << 0) | ~a)) + t[3] - 1894986606) << 10 | f >>> 22) + e << 0) ^ ((a = ((a += (e ^ (f | ~b)) + t[10] - 1051523) << 15 | a >>> 17) + f << 0) | ~e)) + t[1] - 2054922799) << 21 | b >>> 11) + a << 0, b = ((b += ((f = ((f += (b ^ ((e = ((e += (a ^ (b | ~f)) + t[8] + 1873313359) << 6 | e >>> 26) + b << 0) | ~a)) + t[15] - 30611744) << 10 | f >>> 22) + e << 0) ^ ((a = ((a += (e ^ (f | ~b)) + t[6] - 1560198380) << 15 | a >>> 17) + f << 0) | ~e)) + t[13] + 1309151649) << 21 | b >>> 11) + a << 0, b = ((b += ((f = ((f += (b ^ ((e = ((e += (a ^ (b | ~f)) + t[4] - 145523070) << 6 | e >>> 26) + b << 0) | ~a)) + t[11] - 1120210379) << 10 | f >>> 22) + e << 0) ^ ((a = ((a += (e ^ (f | ~b)) + t[2] + 718787259) << 15 | a >>> 17) + f << 0) | ~e)) + t[9] - 343485551) << 21 | b >>> 11) + a << 0, this.first ? (this.h0 = e + 1732584193 << 0, this.h1 = b - 271733879 << 0, this.h2 = a - 1732584194 << 0, this.h3 = f + 271733878 << 0, this.first = !1) : (this.h0 = this.h0 + e << 0, this.h1 = this.h1 + b << 0, this.h2 = this.h2 + a << 0, this.h3 = this.h3 + f << 0) - }, _0x5887c8.prototype.hex = function() { - this.finalize(); - var e = this.h0, - b = this.h1, - a = this.h2, - f = this.h3; - return _0x3a9a1b[e >> 4 & 15] + _0x3a9a1b[15 & e] + _0x3a9a1b[e >> 12 & 15] + _0x3a9a1b[e >> 8 & 15] + _0x3a9a1b[e >> 20 & 15] + _0x3a9a1b[e >> 16 & 15] + _0x3a9a1b[e >> 28 & 15] + _0x3a9a1b[e >> 24 & 15] + _0x3a9a1b[b >> 4 & 15] + _0x3a9a1b[15 & b] + _0x3a9a1b[b >> 12 & 15] + _0x3a9a1b[b >> 8 & 15] + _0x3a9a1b[b >> 20 & 15] + _0x3a9a1b[b >> 16 & 15] + _0x3a9a1b[b >> 28 & 15] + _0x3a9a1b[b >> 24 & 15] + _0x3a9a1b[a >> 4 & 15] + _0x3a9a1b[15 & a] + _0x3a9a1b[a >> 12 & 15] + _0x3a9a1b[a >> 8 & 15] + _0x3a9a1b[a >> 20 & 15] + _0x3a9a1b[a >> 16 & 15] + _0x3a9a1b[a >> 28 & 15] + _0x3a9a1b[a >> 24 & 15] + _0x3a9a1b[f >> 4 & 15] + _0x3a9a1b[15 & f] + _0x3a9a1b[f >> 12 & 15] + _0x3a9a1b[f >> 8 & 15] + _0x3a9a1b[f >> 20 & 15] + _0x3a9a1b[f >> 16 & 15] + _0x3a9a1b[f >> 28 & 15] + _0x3a9a1b[f >> 24 & 15] - }, _0x5887c8.prototype.toString = _0x5887c8.prototype.hex, _0x5887c8.prototype.digest = function() { - this.finalize(); - var e = this.h0, - b = this.h1, - a = this.h2, - f = this.h3; - return [255 & e, e >> 8 & 255, e >> 16 & 255, e >> 24 & 255, 255 & b, b >> 8 & 255, b >> 16 & 255, b >> 24 & 255, 255 & a, a >> 8 & 255, a >> 16 & 255, a >> 24 & 255, 255 & f, f >> 8 & 255, f >> 16 & 255, f >> 24 & 255] - }, _0x5887c8.prototype.array = _0x5887c8.prototype.digest, _0x5887c8.prototype.arrayBuffer = function() { - this.finalize(); - var e = new ArrayBuffer(16), - b = new Uint32Array(e); - return b[0] = this.h0, b[1] = this.h1, b[2] = this.h2, b[3] = this.h3, e - }, _0x5887c8.prototype.buffer = _0x5887c8.prototype.arrayBuffer, _0x5887c8.prototype.base64 = function() { - for (var e, b, a, f = "", c = this.array(), r = 0; r < 15;) e = c[r++], b = c[r++], a = c[r++], f += _0x2c185e[e >>> 2] + _0x2c185e[63 & (e << 4 | b >>> 4)] + _0x2c185e[63 & (b << 2 | a >>> 6)] + _0x2c185e[63 & a]; - return f + (_0x2c185e[(e = c[r]) >>> 2] + _0x2c185e[e << 4 & 63] + "==") - }; - var _0x4dd781 = _0x38ba77(); - _0x17dcbf ? _0x770f81.exports = _0x4dd781 : (_0x1702f9.md5 = _0x4dd781, _0x554fed && (void 0)(function() { - return _0x4dd781 - })) - }() - }); - -function _0x178cef(e) { - return jsvmp("484e4f4a403f52430038001eab0015840e8ee21a00000000000000621b000200001d000146000306000e271f001b000200021d00010500121b001b000b021b000b04041d0001071b000b0500000003000126207575757575757575757575757575757575757575757575757575757575757575", [, , void 0 !== _0x124d1a ? _0x124d1a : void 0, _0x178cef, e]) -} -for (var _0xb55f3e = { - boe: !1, - aid: 0, - dfp: !1, - sdi: !1, - enablePathList: [], - _enablePathListRegex: [], - urlRewriteRules: [], - _urlRewriteRules: [], - initialized: !1, - enableTrack: !1, - track: { - unitTime: 0, - unitAmount: 0, - fre: 0 - }, - triggerUnload: !1, - region: "", - regionConf: {}, - umode: 0, - v: !1, - perf: !1, - xxbg: !0 - }, _0x3eaf64 = { - debug: function(e, b) { - let a = !1; - a = !1 - } - }, _0x233455 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"], _0x2e9f6d = [], _0x511f86 = [], _0x3d35de = 0; _0x3d35de < 256; _0x3d35de++) _0x2e9f6d[_0x3d35de] = _0x233455[_0x3d35de >> 4 & 15] + _0x233455[15 & _0x3d35de], _0x3d35de < 16 && (_0x3d35de < 10 ? _0x511f86[48 + _0x3d35de] = _0x3d35de : _0x511f86[87 + _0x3d35de] = _0x3d35de); -var _0x2ce54d = function(e) { - for (var b = e.length, a = "", f = 0; f < b;) a += _0x2e9f6d[e[f++]]; - return a - }, - _0x5960a2 = function(e) { - for (var b = e.length >> 1, a = b << 1, f = new Uint8Array(b), c = 0, r = 0; r < a;) f[c++] = _0x511f86[e.charCodeAt(r++)] << 4 | _0x511f86[e.charCodeAt(r++)]; - return f - }, - _0x4e46b6 = { - encode: _0x2ce54d, - decode: _0x5960a2 - }; - -function sign(e, b) { - return jsvmp("484e4f4a403f5243001f240fbf2031ccf317480300000000000007181b0002012e1d00921b000b171b000b02402217000a1c1b000b1726402217000c1c1b000b170200004017002646000306000e271f001b000200021d00920500121b001b000b031b000b17041d0092071b000b041e012f17000d1b000b05260a0000101c1b000b06260a0000101c1b001b000b071e01301d00931b001b000b081e00081d00941b0048021d00951b001b000b1b1d00961b0048401d009e1b001b000b031b000b16041d009f1b001b000b09221e0131241b000b031b000b09221e0131241b000b1e0a000110040a0001101d00d51b001b000b09221e0131241b000b031b000b09221e0131241b000b180a000110040a0001101d00d71b001b000b0a1e00101d00d91b001b000b0b261b000b1a1b000b190a0002101d00db1b001b000b0c261b000b221b000b210a0002101d00dc1b001b000b0d261b000b230200200a0002101d00dd1b001b000b09221e0131241b000b031b000b24040a0001101d00df1b001b000b0e1a00221e00de240a0000104903e82b1d00e31b001b000b0f260a0000101d00e41b001b000b1d1d00e71b001b000b1a4901002b1d00e81b001b000b1a4901002c1d00ea1b001b000b191d00f21b001b000b1f480e191d00f81b001b000b1f480f191d00f91b001b000b20480e191d00fb1b001b000b20480f191d00fe1b001b000b25480e191d01001b001b000b25480f191d01011b001b000b264818344900ff2f1d01031b001b000b264810344900ff2f1d01321b001b000b264808344900ff2f1d01331b001b000b264800344900ff2f1d01341b001b000b274818344900ff2f1d01351b001b000b274810344900ff2f1d01361b001b000b274808344900ff2f1d01371b001b000b274800344900ff2f1d01381b001b000b281b000b29311b000b2a311b000b2b311b000b2c311b000b2d311b000b2e311b000b2f311b000b30311b000b31311b000b32311b000b33311b000b34311b000b35311b000b36311b000b37311b000b38311b000b39311d01391b004900ff1d013a1b001b000b10261b000b281b000b2a1b000b2c1b000b2e1b000b301b000b321b000b341b000b361b000b381b000b3a1b000b291b000b2b1b000b2d1b000b2f1b000b311b000b331b000b351b000b371b000b390a0013101d013b1b001b000b0c261b000b111b000b3b041b000b3c0a0002101d013c1b001b000b12261b000b1c1b000b3b1b000b3d0a0003101d013d1b001b000b13261b000b3e0200240a0002101d013e1b000b3f0000013f000126207575757575757575757575757575757575757575757575757575757575757575012b0e7776757a7d7643617c637661676a027a77065c717976706708777671667474766107767d65707c77760374766707707c7d607c7f7607757a61767166740a7c66677661447a77677b0a7a7d7d7661447a77677b0b7c666776615b767a747b670b7a7d7d76615b767a747b6709666076615274767d670b677c5f7c64766150726076077a7d77766b5c7508767f767067617c7d09667d7776757a7d76770963617c677c676a637608677c4067617a7d740470727f7f0763617c7076606010487c71797670673363617c707660604e067c717976706705677a677f76047d7c7776012e0125012402602341525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a383c2e0260224157787763747b2749586042512b233c5e75656420254b5a22412126384446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e0260214157787763747b2749586042512b233c5e75656420254b5a224121263e4446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e02602041525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a3e4c2e012a022222067f767d74677b0a707b7261507c7776526702222306707b726152670f487c717976706733447a7d777c644e08577c70667e767d6712487c7179767067335d72657a7472677c614e057960777c7e10487c7179767067335b7a60677c616a4e07637f66747a7d60084c637b727d677c7e0b70727f7f437b727d677c7e0b4c4c7d7a747b677e726176055266777a7c1850727d65726041767d7776617a7d74507c7d67766b6721570964767177617a657661137476675c647d43617c637661676a5d727e7660097f727d74667274766006707b617c7e760761667d677a7e7607707c7d7d767067144c4c64767177617a6576614c7665727f66726776134c4c60767f767d7a667e4c7665727f667267761b4c4c64767177617a6576614c6070617a63674c75667d70677a7c7d174c4c64767177617a6576614c6070617a63674c75667d70154c4c64767177617a6576614c6070617a63674c757d134c4c756b77617a6576614c7665727f66726776124c4c77617a6576614c667d64617263637677154c4c64767177617a6576614c667d64617263637677114c4c77617a6576614c7665727f66726776144c4c60767f767d7a667e4c667d64617263637677144c4c756b77617a6576614c667d64617263637677094c60767f767d7a667e0c70727f7f40767f767d7a667e164c40767f767d7a667e4c5a57564c4176707c6177766108777c70667e767d670478766a60057e7267707b06417674566b630a4f3748723e694e77704c067072707b764c04607c7e7608707675407b72616308507675407b72616305767c72637a16767c44767151617c64607661577a60637267707b76610f717a7d775c717976706752606a7d700e7a60565c44767151617c646076610120047c63767d0467766067097a7d707c747d7a677c077c7d7661617c6104707c77761242465c47524c564b5056565756574c5641410e607660607a7c7d40677c61727476076076675a67767e10607c7e7658766a5b766176516a6776770a61767e7c65765a67767e097a7d77766b767757510c437c7a7d6776615665767d670e5e40437c7a7d6776615665767d670d706176726776567f767e767d670670727d65726009677c5772677246415f076176637f727076034f603901740a7d72677a6576707c777614487c717976706733437f66747a7d526161726a4e4a4d7b676763602c294f3c4f3c3b48233e2a4e68223f206e3b4f3d48233e2a4e68223f206e3a68206e6f48723e75233e2a4e68223f276e3b2948723e75233e2a4e68223f276e3a68246e3a0127087f7c7072677a7c7d047b61767504757a7f76107b676763293c3c7f7c70727f7b7c606708637f7267757c617e02222102222007647a7d777c646002222703647a7d02222607727d77617c7a77022225057f7a7d666b022224067a637b7c7d7602222b047a63727702222a047a637c77022123037e7270022122097e72707a7d677c607b0c7e72704c637c64766163703a0470617c60036b22220570617a7c6005756b7a7c6004637a787602212102212002212702212602212502212402212b08757a6176757c6b3c067c637661723c05337c63613c05337c63673c07707b617c7e763c0867617a77767d673c047e607a7602212a0220230665767d777c6106547c7c747f760e4c637261727e40647a67707b5c7d0a777a61767067407a747d0a707c7d607a6067767d670660647a67707b03777c7e07637b727d677c7e047b7c7c7840525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a3e3d03727a77017d01750161096067726167477a7e7601670972717a7f7a677a76600a677a7e766067727e6322137b72617764726176507c7d70666161767d706a0c7776657a70765e767e7c616a087f727d74667274760a6176607c7f66677a7c7d0f7265727a7f4176607c7f66677a7c7d0960706176767d477c630a60706176767d5f767567107776657a7076437a6b767f4172677a7c0a63617c77667067406671077172676776616a016309677c66707b5a7d757c08677a7e76697c7d760a677a7e766067727e6321077463665a7d757c0b7960557c7d67605f7a60670b637f66747a7d605f7a60670a677a7e766067727e63200a76657661507c7c787a760767674c60707a77017e0b606a7d67726b5661617c610c7d72677a65765f767d74677b056167705a43097563457661607a7c7d0b4c4c657661607a7c7d4c4c08707f7a767d675a770a677a7e766067727e63270b766b67767d77557a767f77046366607b03727f7f04677b767d097172607625274c707b0c75617c7e507b7261507c7776067125274c2023022022087172607625274c23022021087172607625274c22022020087172607625274c2102202702202602202507747667477a7e760220240b777c7e5d7c6745727f7a77096066716067617a7d740863617c677c707c7f02202b02202a01230e222323232323232322222323232302272302272207757c616176727f02272104717c776a096067617a7d747a756a02686e0b717c776a45727f216067610a717c776a4c7b72607b2e01350366617f02272005626676616a0a72607c7f774c607a747d096372677b7d727e762e0967674c6476717a772e063566667a772e0227270227260e4c716a6776774c6076704c777a770227250a27212a272a2524212a25097576457661607a7c7d0227240e4c232151274925647c232323232202272b02272a05607f7a7076022623074056505a5d555c037d7c6409677a7e766067727e6305757f7c7c610661727d777c7e0f7476674747447671507c7c787a7660056767647a770867674c6476717a770767674476715a770b67674c6476717a774c65210967674476717a7745210761667d7d7a7d7405757f66607b087e7c65765f7a60670660637f7a70760671765e7c657609707f7a70785f7a6067077176507f7a70780c78766a717c7261775f7a60670a717658766a717c7261770b7270677a657640677267760b647a7d777c6440677267760360477e05676172707808667d7a67477a7e76037270700a667d7a67527e7c667d670871767b72657a7c61077e6074476a637603645a5707727a775f7a60670b63617a6572706a5e7c777606706660677c7e067260607a747d0f4456514c5756455a50564c5a5d555c0479607c7d0a6176747a7c7d507c7d75096176637c616746617f04766b7a67094b3e5e403e404746510c4b3e5e403e43524a5f5c525720232323232323232323232323232323232323232323232323232323232323232320772722772b70772a2b75232371212327762a2b23232a2a2b7670752b272124760165066671707c7776067776707c777602262202262102262002262702262602262502262402262b02262a022523022522022521022520", [, , void 0, void 0 !== _0x178cef ? _0x178cef : void 0, { - boe: !1, - aid: 0, - dfp: !1, - sdi: !1, - enablePathList: [], - _enablePathListRegex: [/\/web\/report/], - urlRewriteRules: [], - _urlRewriteRules: [], - initialized: !1, - enableTrack: !1, - track: { - unitTime: 0, - unitAmount: 0, - fre: 0 - }, - triggerUnload: !1, - region: "", - regionConf: {}, - umode: 0, - v: !1, - perf: !1, - xxbg: !0 - }, () => 0, () => "03v", { - ubcode: 0 - }, { - bogusIndex: 0, - msNewTokenList: [], - moveList: [], - clickList: [], - keyboardList: [], - activeState: [], - aidList: [], - envcode: 0, - msToken: "", - msStatus: 0, - __ac_testid: "", - ttwid: "", - tt_webid: "", - tt_webid_v2: "" - }, void 0 !== _0x4e46b6 ? _0x4e46b6 : void 0, { - userAgent: b - }, (e, b) => { - let a = new Uint8Array(3); - return a[0] = e / 256, a[1] = e % 256, a[2] = b % 256, String.fromCharCode.apply(null, a) - }, (e, b) => { - let a, f = [], - c = 0, - r = ""; - for (let e = 0; e < 256; e++) f[e] = e; - for (let b = 0; b < 256; b++) c = (c + f[b] + e.charCodeAt(b % e.length)) % 256, a = f[b], f[b] = f[c], f[c] = a; - let t = 0; - c = 0; - for (let e = 0; e < b.length; e++) c = (c + f[t = (t + 1) % 256]) % 256, a = f[t], f[t] = f[c], f[c] = a, r += String.fromCharCode(b.charCodeAt(e) ^ f[(f[t] + f[c]) % 256]); - return r - }, (e, b) => jsvmp("484e4f4a403f524300281018f7b851f02d296e5b00000000000004a21b0002001d1d001e1b00131e00061a001d001f1b000b070200200200210d1b000b070200220200230d1b000b070200240200250d1b000b070200260200270d1b001b000b071b000b05191d00031b000200001d00281b0048001d00291b000b041e002a1b000b0b4803283b1700f11b001b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f4810331b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f480833301b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f301d002c1b00220b091b000b08221e002d241b000b0a4a00fc00002f4812340a000110281d00281b00220b091b000b08221e002d241b000b0a4a0003f0002f480c340a000110281d00281b00220b091b000b08221e002d241b000b0a490fc02f4806340a000110281d00281b00220b091b000b08221e002d241b000b0a483f2f0a000110281d002816ff031b000b041e002a1b000b0b294800391700e01b001b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f4810331b000b041e002a1b000b0b3917001e1b000b04221e002b241b000b0b0a0001104900ff2f4808331600054800301d002c1b00220b091b000b08221e002d241b000b0a4a00fc00002f4812340a000110281d00281b00220b091b000b08221e002d241b000b0a4a0003f0002f480c340a000110281d00281b00220b091b000b041e002a1b000b0b3917001e1b000b08221e002d241b000b0a490fc02f4806340a0001101600071b000b06281d00281b00220b091b000b06281d00281b000b090000002e000126207575757575757575757575757575757575757575757575757575757575757575012b0e7776757a7d7643617c637661676a027a77065c717976706708777671667474766107767d65707c77760374766707707c7d607c7f7607757a61767166740a7c66677661447a77677b0a7a7d7d7661447a77677b0b7c666776615b767a747b670b7a7d7d76615b767a747b6709666076615274767d670b677c5f7c64766150726076077a7d77766b5c7508767f767067617c7d09667d7776757a7d76770963617c677c676a637608677c4067617a7d740470727f7f0763617c7076606010487c71797670673363617c707660604e067c717976706705677a677f76047d7c7776012e0125012402602341525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a383c2e0260224157787763747b2749586042512b233c5e75656420254b5a22412126384446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e0260214157787763747b2749586042512b233c5e75656420254b5a224121263e4446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e02602041525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a3e4c2e012a022222067f767d74677b0a707b7261507c7776526702222306707b72615267", [, , , , e, b]), "undefined" != typeof Date ? Date : void 0, () => 0, (e, b, a, f, c, r, t, d, i, n, s, o, l, _, x, u, h, p, y) => { - let v = new Uint8Array(19); - return v[0] = e, v[1] = s, v[2] = b, v[3] = o, v[4] = a, v[5] = l, v[6] = f, v[7] = _, v[8] = c, v[9] = x, v[10] = r, v[11] = u, v[12] = t, v[13] = h, v[14] = d, v[15] = p, v[16] = i, v[17] = y, v[18] = n, String.fromCharCode.apply(null, v) - }, e => String.fromCharCode(e), (e, b, a) => String.fromCharCode(e) + String.fromCharCode(b) + a, (e, b) => jsvmp("484e4f4a403f524300281018f7b851f02d296e5b00000000000004a21b0002001d1d001e1b00131e00061a001d001f1b000b070200200200210d1b000b070200220200230d1b000b070200240200250d1b000b070200260200270d1b001b000b071b000b05191d00031b000200001d00281b0048001d00291b000b041e002a1b000b0b4803283b1700f11b001b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f4810331b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f480833301b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f301d002c1b00220b091b000b08221e002d241b000b0a4a00fc00002f4812340a000110281d00281b00220b091b000b08221e002d241b000b0a4a0003f0002f480c340a000110281d00281b00220b091b000b08221e002d241b000b0a490fc02f4806340a000110281d00281b00220b091b000b08221e002d241b000b0a483f2f0a000110281d002816ff031b000b041e002a1b000b0b294800391700e01b001b000b04221e002b241b001e0029222d1b00241d00290a0001104900ff2f4810331b000b041e002a1b000b0b3917001e1b000b04221e002b241b000b0b0a0001104900ff2f4808331600054800301d002c1b00220b091b000b08221e002d241b000b0a4a00fc00002f4812340a000110281d00281b00220b091b000b08221e002d241b000b0a4a0003f0002f480c340a000110281d00281b00220b091b000b041e002a1b000b0b3917001e1b000b08221e002d241b000b0a490fc02f4806340a0001101600071b000b06281d00281b00220b091b000b06281d00281b000b090000002e000126207575757575757575757575757575757575757575757575757575757575757575012b0e7776757a7d7643617c637661676a027a77065c717976706708777671667474766107767d65707c77760374766707707c7d607c7f7607757a61767166740a7c66677661447a77677b0a7a7d7d7661447a77677b0b7c666776615b767a747b670b7a7d7d76615b767a747b6709666076615274767d670b677c5f7c64766150726076077a7d77766b5c7508767f767067617c7d09667d7776757a7d76770963617c677c676a637608677c4067617a7d740470727f7f0763617c7076606010487c71797670673363617c707660604e067c717976706705677a677f76047d7c7776012e0125012402602341525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a383c2e0260224157787763747b2749586042512b233c5e75656420254b5a22412126384446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e0260214157787763747b2749586042512b233c5e75656420254b5a224121263e4446527f567a245d5f717c624a475c4366697e5579597d616a6b2a5b45547072406750762e02602041525150575655545b5a59585f5e5d5c43424140474645444b4a49727170777675747b7a79787f7e7d7c63626160676665646b6a6923222120272625242b2a3e4c2e012a022222067f767d74677b0a707b7261507c7776526702222306707b72615267", [, , , , e, b]), , sign, e, void 0]) -} - -module.exports = { - sign - };