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 - };