123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import json
- import time
- from base64 import b64encode
- from functools import reduce
- from hashlib import md5
- from random import choice, randint
- from typing import Any, Dict, List, Optional
- from urllib.parse import urlencode
- class DouYinHelper(object):
- ttwid_list = [
- '1|G3wy_-RdLJnfG5P9zAcP54OM8_nTLZVrJxNi1lPzdmg|1693558867|5e43c47a424e939aaf7193b096e3c6f2274982ee64e9608c99c54d2a43982aca'
- ]
- @classmethod
- def _0x30492c(cls, x: bytes, y: bytes, f: Optional[List[int]] = None) -> bytes:
- """RC4加密, 可以用Crypto.Cipher.ARC4替代"""
- c = 0
- d = [i for i in range(256)]
- for b in range(256):
- c = (c + d[b] + x[b % len(x)]) % 256
- e = d[b]
- d[b] = d[c]
- d[c] = e
- t, c = 0, 0
- if not f:
- f = []
- for i in range(len(y)):
- t = (t + 1) % 256
- c = (c + d[t]) % 256
- e = d[t]
- d[t] = d[c]
- d[c] = e
- f.append(y[i] ^ d[(d[t] + d[c]) % 256])
- return bytes(f)
- @classmethod
- def _0x485470(cls, a: str) -> List[int]:
- _0x583e81 = [0] * 103
- for i in range(10):
- _0x583e81[i + 48] = i
- for j in range(10, 16):
- _0x583e81[j + 87] = j
- b = len(a) >> 1
- e = b << 1
- d = [0] * b
- c = 0
- for f in range(0, e, 2):
- d[c] = _0x583e81[ord(a[f])] << 4 | _0x583e81[ord(a[f + 1])]
- c += 1
- return d
- @classmethod
- def calc_x_bogus(cls, ua: str, query: str, data: Optional[Dict[str, Any]] = None) -> str:
- """计算X_Bogus参数"""
- query = query.encode()
- for _ in range(2):
- query = md5(query).hexdigest()
- query = bytes([int(query[i:i + 2], 16) for i in range(0, len(query), 2)])
- data = json.dumps(data, separators=(',', ':'), ensure_ascii=False).encode() if data else b''
- for _ in range(2):
- data = md5(data).hexdigest()
- data = bytes([int(data[i:i + 2], 16) for i in range(0, len(data), 2)])
- a = b'\x00\x01\x0e'
- ua = b64encode(cls._0x30492c(a, ua.encode())).decode()
- ua = md5(ua.encode()).hexdigest()
- ua = cls._0x485470(ua)
- t = int(time.time())
- fp = 2421646185 # 真实的canvas指纹
- arr1 = [
- 64,
- 1 / 256,
- 1 % 256,
- 14,
- query[14],
- query[15],
- data[14],
- data[15],
- ua[14],
- ua[15],
- t >> 24 & 255,
- t >> 16 & 255,
- t >> 8 & 255,
- t >> 0 & 255,
- fp >> 24 & 255,
- fp >> 16 & 255,
- fp >> 8 & 255,
- fp >> 0 & 255,
- ]
- reduce_num = reduce(lambda x, y: int(x) ^ int(y), arr1)
- arr1.append(reduce_num)
- arr2 = [int(arr1[i]) for i in range(len(arr1))]
- garble = cls._0x30492c(b'\xff', bytes(arr2), [2, 255])
- m = 'Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe='
- xb = ''
- for i in range(0, len(garble), 3):
- a, b, c = garble[i], garble[i + 1], garble[i + 2]
- base_num = c | b << 8 | a << 16
- c1 = m[(base_num & 16515072) >> 18]
- c2 = m[(base_num & 258048) >> 12]
- c3 = m[(base_num & 4032) >> 6]
- c4 = m[(base_num & 63)]
- xb += ''.join([c1, c2, c3, c4])
- return xb
- @classmethod
- def get_full_query(cls, ua: str, extra_data: Dict[str, Any]) -> Dict[str, Any]:
- ms_token = b64encode(bytes([randint(0, 255) for _ in range(94)])).decode()
- ms_token = ms_token.replace('+', '-').replace('/', '_').rstrip('=')
- data = {
- 'device_platform': 'webapp',
- 'aid': '6383',
- 'channel': 'channel_pc_web',
- 'pc_client_type': '1',
- 'version_code': '190500',
- 'version_name': '19.5.0',
- 'cookie_enabled': 'true',
- 'platform': 'PC',
- 'msToken': ms_token,
- }
- data.update(extra_data)
- query = urlencode(data, safe='=')
- x_bogus = cls.calc_x_bogus(ua=ua, query=query, data=None)
- data.update({'X-Bogus': x_bogus})
- return data
- @classmethod
- def get_cookie(cls):
- ttwid = choice(cls.ttwid_list)
- return f'ttwid={ttwid}'
|