mirror of
https://github.com/Evil0ctal/Douyin_TikTok_Download_API.git
synced 2025-04-19 03:29:42 +08:00
248 lines
9.3 KiB
Python
248 lines
9.3 KiB
Python
# ==============================================================================
|
||
# Copyright (C) 2021 Evil0ctal
|
||
#
|
||
# This file is part of the Douyin_TikTok_Download_API project.
|
||
#
|
||
# This project is licensed under the Apache License 2.0 (the "License");
|
||
# you may not use this file except in compliance with the License.
|
||
# You may obtain a copy of the License at:
|
||
# http://www.apache.org/licenses/LICENSE-2.0
|
||
#
|
||
# Unless required by applicable law or agreed to in writing, software
|
||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
# See the License for the specific language governing permissions and
|
||
# limitations under the License.
|
||
# ==============================================================================
|
||
# __
|
||
# /> フ
|
||
# | _ _ l
|
||
# /` ミ_xノ
|
||
# / | Feed me Stars ⭐ ️
|
||
# / ヽ ノ
|
||
# │ | | |
|
||
# / ̄| | | |
|
||
# | ( ̄ヽ__ヽ_)__)
|
||
# \二つ
|
||
# ==============================================================================
|
||
#
|
||
# Contributor Link:
|
||
# - https://github.com/Evil0ctal
|
||
# - https://github.com/Johnserf-Seed
|
||
#
|
||
# ==============================================================================
|
||
|
||
|
||
import time
|
||
import base64
|
||
import hashlib
|
||
|
||
|
||
class XBogus:
|
||
def __init__(self, user_agent: str = None) -> None:
|
||
# fmt: off
|
||
self.Array = [
|
||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, None, None, None, None, None, None, None, None, None, None, None,
|
||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||
None, None, None, None, None, None, None, None, None, None, None, None, 10, 11, 12, 13, 14, 15
|
||
]
|
||
self.character = "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe="
|
||
# fmt: on
|
||
self.ua_key = b"\x00\x01\x0c"
|
||
self.user_agent = (
|
||
user_agent
|
||
if user_agent is not None and user_agent != ""
|
||
else "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0"
|
||
)
|
||
|
||
def md5_str_to_array(self, md5_str):
|
||
"""
|
||
将字符串使用md5哈希算法转换为整数数组。
|
||
Convert a string to an array of integers using the md5 hashing algorithm.
|
||
"""
|
||
if isinstance(md5_str, str) and len(md5_str) > 32:
|
||
return [ord(char) for char in md5_str]
|
||
else:
|
||
array = []
|
||
idx = 0
|
||
while idx < len(md5_str):
|
||
array.append(
|
||
(self.Array[ord(md5_str[idx])] << 4)
|
||
| self.Array[ord(md5_str[idx + 1])]
|
||
)
|
||
idx += 2
|
||
return array
|
||
|
||
def md5_encrypt(self, url_path):
|
||
"""
|
||
使用多轮md5哈希算法对URL路径进行加密。
|
||
Encrypt the URL path using multiple rounds of md5 hashing.
|
||
"""
|
||
hashed_url_path = self.md5_str_to_array(
|
||
self.md5(self.md5_str_to_array(self.md5(url_path)))
|
||
)
|
||
return hashed_url_path
|
||
|
||
def md5(self, input_data):
|
||
"""
|
||
计算输入数据的md5哈希值。
|
||
Calculate the md5 hash value of the input data.
|
||
"""
|
||
if isinstance(input_data, str):
|
||
array = self.md5_str_to_array(input_data)
|
||
elif isinstance(input_data, list):
|
||
array = input_data
|
||
else:
|
||
raise ValueError("Invalid input type. Expected str or list.")
|
||
|
||
md5_hash = hashlib.md5()
|
||
md5_hash.update(bytes(array))
|
||
return md5_hash.hexdigest()
|
||
|
||
def encoding_conversion(
|
||
self, a, b, c, e, d, t, f, r, n, o, i, _, x, u, s, l, v, h, p
|
||
):
|
||
"""
|
||
第一次编码转换。
|
||
Perform encoding conversion.
|
||
"""
|
||
y = [a]
|
||
y.append(int(i))
|
||
y.extend([b, _, c, x, e, u, d, s, t, l, f, v, r, h, n, p, o])
|
||
re = bytes(y).decode("ISO-8859-1")
|
||
return re
|
||
|
||
def encoding_conversion2(self, a, b, c):
|
||
"""
|
||
第二次编码转换。
|
||
Perform an encoding conversion on the given input values and return the result.
|
||
"""
|
||
return chr(a) + chr(b) + c
|
||
|
||
def rc4_encrypt(self, key, data):
|
||
"""
|
||
使用RC4算法对数据进行加密。
|
||
Encrypt data using the RC4 algorithm.
|
||
"""
|
||
S = list(range(256))
|
||
j = 0
|
||
encrypted_data = bytearray()
|
||
|
||
# 初始化 S 盒
|
||
# Initialize the S box
|
||
for i in range(256):
|
||
j = (j + S[i] + key[i % len(key)]) % 256
|
||
S[i], S[j] = S[j], S[i]
|
||
|
||
# 生成密文
|
||
# Generate the ciphertext
|
||
i = j = 0
|
||
for byte in data:
|
||
i = (i + 1) % 256
|
||
j = (j + S[i]) % 256
|
||
S[i], S[j] = S[j], S[i]
|
||
encrypted_byte = byte ^ S[(S[i] + S[j]) % 256]
|
||
encrypted_data.append(encrypted_byte)
|
||
|
||
return encrypted_data
|
||
|
||
def calculation(self, a1, a2, a3):
|
||
"""
|
||
对给定的输入值执行位运算计算,并返回结果。
|
||
Perform a calculation using bitwise operations on the given input values and return the result.
|
||
"""
|
||
x1 = (a1 & 255) << 16
|
||
x2 = (a2 & 255) << 8
|
||
x3 = x1 | x2 | a3
|
||
return (
|
||
self.character[(x3 & 16515072) >> 18]
|
||
+ self.character[(x3 & 258048) >> 12]
|
||
+ self.character[(x3 & 4032) >> 6]
|
||
+ self.character[x3 & 63]
|
||
)
|
||
|
||
def getXBogus(self, url_path):
|
||
"""
|
||
获取 X-Bogus 值。
|
||
Get the X-Bogus value.
|
||
"""
|
||
|
||
array1 = self.md5_str_to_array(
|
||
self.md5(
|
||
base64.b64encode(
|
||
self.rc4_encrypt(self.ua_key, self.user_agent.encode("ISO-8859-1"))
|
||
).decode("ISO-8859-1")
|
||
)
|
||
)
|
||
|
||
array2 = self.md5_str_to_array(
|
||
self.md5(self.md5_str_to_array("d41d8cd98f00b204e9800998ecf8427e"))
|
||
)
|
||
url_path_array = self.md5_encrypt(url_path)
|
||
|
||
timer = int(time.time())
|
||
ct = 536919696
|
||
array3 = []
|
||
array4 = []
|
||
xb_ = ""
|
||
# fmt: off
|
||
new_array = [
|
||
64, 0.00390625, 1, 12,
|
||
url_path_array[14], url_path_array[15], array2[14], array2[15], array1[14], array1[15],
|
||
timer >> 24 & 255, timer >> 16 & 255, timer >> 8 & 255, timer & 255,
|
||
ct >> 24 & 255, ct >> 16 & 255, ct >> 8 & 255, ct & 255
|
||
]
|
||
# fmt: on
|
||
xor_result = new_array[0]
|
||
for i in range(1, len(new_array)):
|
||
b = new_array[i]
|
||
if isinstance(b, float):
|
||
b = int(b)
|
||
xor_result ^= b
|
||
|
||
new_array.append(xor_result)
|
||
|
||
idx = 0
|
||
while idx < len(new_array):
|
||
array3.append(new_array[idx])
|
||
try:
|
||
array4.append(new_array[idx + 1])
|
||
except IndexError:
|
||
pass
|
||
idx += 2
|
||
|
||
merge_array = array3 + array4
|
||
|
||
garbled_code = self.encoding_conversion2(
|
||
2,
|
||
255,
|
||
self.rc4_encrypt(
|
||
"ÿ".encode("ISO-8859-1"),
|
||
self.encoding_conversion(*merge_array).encode("ISO-8859-1"),
|
||
).decode("ISO-8859-1"),
|
||
)
|
||
|
||
idx = 0
|
||
while idx < len(garbled_code):
|
||
xb_ += self.calculation(
|
||
ord(garbled_code[idx]),
|
||
ord(garbled_code[idx + 1]),
|
||
ord(garbled_code[idx + 2]),
|
||
)
|
||
idx += 3
|
||
self.params = "%s&X-Bogus=%s" % (url_path, xb_)
|
||
self.xb = xb_
|
||
return (self.params, self.xb, self.user_agent)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
url_path = "https://www.douyin.com/aweme/v1/web/aweme/post/?device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Edge&browser_version=122.0.0.0&browser_online=true&engine_name=Blink&engine_version=122.0.0.0&os_name=Windows&os_version=10&cpu_core_num=12&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7335414539335222835&msToken=p9Y7fUBuq9DKvAuN27Peml6JbaMqG2ZcXfFiyDv1jcHrCN00uidYqUgSuLsKl1onC-E_n82m-aKKYE0QGEmxIWZx9iueQ6WLbvzPfqnMk4GBAlQIHcDzxb38FLXXQxAm"
|
||
# ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0"
|
||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
|
||
|
||
XB = XBogus(user_agent=ua)
|
||
xbogus = XB.getXBogus(url_path)
|
||
print(f"url: {xbogus[0]}, xbogus:{xbogus[1]}, ua: {xbogus[2]}") |