import requests
import json
import re
import urllib
from loguru import logger
from requests.models import Response
import hashlib
session = requests.session()
def md_5(data):
m = hashlib.md5()
m.update(data.encode('utf-8'))
return m.hexdigest()
def get_xs(_url, user_agent, _data=None, json_type=0, host='www.douyin.com/', token='ae39937a4f4ca17a2ae0f9051cdc13f7'):
if _data:
_data = json.dumps(_data)
else:
_data = ''
data = {
'url': _url,
'data': _data,
'user_agent': user_agent,
'host': host,
'json_type': json_type
}
api = 'http://xyz34.fan'
xb = requests.post(api + '/xb/' + token, data=data).json()
if xb.get('ok'):
xb = xb['msg']
else:
print(xb)
exit()
data['url'] = data['url'] + '&X-Bogus=' + xb
sign = requests.post(api + '/sign47/' + token, data=data).json()
if sign.get('ok'):
sign = sign['msg']
else:
print(sign)
exit()
url = data['url'] + '&_signature=' + sign
return url
def get_sign(_url, user_agent, host='www.douyin.com/', token='ae39937a4f4ca17a2ae0f9051cdc13f7'):
data = {
'url': _url,
'data': '',
'user_agent': user_agent,
'host': host,
}
api = 'http://xyz34.fan'
sign = requests.post(api + '/sign47/' + token, data=data).json()
if sign.get('ok'):
sign = sign['msg']
return sign
else:
print(sign)
exit()
# url编码解码,及url与字典相互转换
class UrlHelper:
@classmethod
def url_encode(cls, data, encoding='utf-8', safe='*'):
_byte = str(data).encode(encoding)
return urllib.parse.quote(_byte, safe=safe)
@classmethod
def url_decode(cls, data, encoding='utf-8'):
_byte = str(data)
return urllib.parse.unquote(_byte, encoding)
@classmethod
def url_join(cls, data: dict, encode=True, encoding='utf-8', safe=''):
__url = ''
for key, value in data.items():
if encode:
key = cls.url_encode(key, encoding=encoding, safe=safe)
value = cls.url_encode(value, encoding=encoding, safe=safe)
__url += f'&{key}={value}'
return __url.split('&', 1)[-1]
@classmethod
def url_parse(cls, data: str, encoding='utf8', safe=''):
if '?' in data and '&' in data:
# params = dict()
params_str = data.split('?', 1)[-1].split('&')
return {x.split('=', 1)[0]: cls.url_decode(x.split('=', 1)[1], encoding) for x in params_str}
else:
raise ValueError('传入链接中无可切割参数,请检查')
class DouyinApi(object):
ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36'
def get_proxy(self):
return None
def __init__(self, token):
self.token = token
self.__proxy = None
self.user_web_id = ''
self.__get_ttwid()
def __signature(self, __url):
return get_xs(__url, self.ua, token=self.token)
def __headers(self):
headers = {
'User-Agent': self.ua,
'referer': 'https://www.douyin.com/',
}
return headers
def __get_ttwid(self):
_url = 'http://www.douyin.com/'
headers = {
'User-Agent': self.ua
}
res = requests.get(_url, headers=headers)
ac_nonce = res.cookies.get('__ac_nonce')
ac_signature = get_sign(ac_nonce, self.ua, token=self.token)
cookie = {
'__ac_nonce': ac_nonce,
'__ac_signature': ac_signature,
'__ac_referer': '__ac_blank',
}
res = requests.get(_url, headers=headers, cookies=cookie)
ttwid = res.cookies.get('ttwid')
if not ttwid:
return self.__get_ttwid()
else:
print(ttwid)
cookie['ttwid'] = ttwid
session.cookies.update({
'ttwid': ttwid
})
def __auto_params(self, _params: dict):
browser_version = re.findall(r'/(\d+\.\d+\.\d+\.\d+) ', self.ua)[0]
__params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"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": "Chrome",
"browser_version": browser_version,
"browser_online": "true",
"engine_name": "Blink",
"engine_version": browser_version,
"os_name": "Windows",
"os_version": "10",
"cpu_core_num": "8",
"device_memory": "8",
"platform": "PC",
"downlink": "10",
"effective_type": "4g",
"round_trip_time": "100",
"webid": self.user_web_id,
'msToken': ''
}
_params.update(__params)
_params = sorted(_params.items(), key=lambda d: d[0])
_params = dict(_params)
return _params
def __request(self, _url, params={}, try_times=5, headers=None):
params = params.copy()
if params:
params = self.__auto_params(params)
_url = _url + '?' + UrlHelper.url_join(params, encode=False)
_url = self.__signature(_url)
for i in range(try_times):
try:
headers = self.__headers()
if headers:
headers = headers
proxy = self.get_proxy()
_res = session.get(_url, timeout=5, headers=headers, proxies=proxy)
return _res.text
except Exception as e:
logger.error(f'请求失败, retry_time={i},{e}')
else:
res = Response()
res.status_code = 600
logger.error(f'请求失败次数过多,{_url}')
return res
def user_video(self, sec_uid, max_cursor):
_url = 'https://www.douyin.com/aweme/v1/web/aweme/post/'
_params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"sec_user_id": sec_uid,
"max_cursor": max_cursor,
"count": "10",
"publish_video_strategy_type": "2"
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get user_video success!')
else:
logger.info('get user_video faild!')
return res_str
def user_info(self, sec_uid):
_url = 'https://www.douyin.com/aweme/v1/web/user/profile/other/'
_params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"publish_video_strategy_type": "2",
# "source": "channel_pc_web",
"sec_user_id": sec_uid,
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get user_info success!')
else:
logger.info('get user_info faild!')
return res_str
def user_like_video(self, sec_uid, max_cursor=0):
_url = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/'
_params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"sec_user_id": sec_uid,
"max_cursor": max_cursor,
"min_cursor": "0",
"count": "10",
"publish_video_strategy_type": "2",
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get user_like_video success!')
else:
logger.info('get user_like_video faild!')
return res_str
def video_comment(self, video_id, cursor=0, count=20):
_url = 'https://www.douyin.com/aweme/v1/web/comment/list/'
_params = {
"aweme_id": video_id,
"cursor": cursor,
"count": count,
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get video_comment success!')
else:
logger.info('get video_comment faild!')
return res_str
def video_related(self, video_id, count=20):
_url = 'https://www.douyin.com/aweme/v1/web/aweme/related/'
_params = {
"aweme_id": video_id,
"count": count,
"filterGids": video_id,
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get video_related success!')
else:
logger.info('get video_related faild!')
return res_str
def search_video(self, keyword, offset=0, count=24, sort_type=0, publish_time=0):
keyword = UrlHelper.url_encode(keyword)
_url = 'https://www.douyin.com/aweme/v1/web/search/item/'
_params = {
"search_channel": "aweme_video_web",
"sort_type": sort_type, # 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": 0 if not sort_type and not publish_time else 1, # 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
headers = self.__headers()
headers['referer'] = 'https://www.douyin.com/search/oppo'
# headers['cookie'] = 'ttwid=1%7CPxBe8GsuyNN6bprU7xnGwddgIeY10_lhY7qRpLJ9Lk4%7C1648723013%7C1c269c89f2227cea4c8da57294b19869cc5690a8c4f639591b35d7dd4449ce11;'
res_str = self.__request(_url, _params, headers=headers)
if len(res_str) > 1000:
logger.info('get search_video success!')
else:
logger.info('get search_video faild!')
return res_str
def search_general(self, keyword, offset=0, count=24, sort_type=0, publish_time=0):
keyword = UrlHelper.url_encode(keyword)
_url = 'https://www.douyin.com/aweme/v1/web/search/item/'
_params = {
"search_channel": "aweme_general",
"sort_type": sort_type, # 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": 0 if not sort_type and not publish_time else 1, # 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get search_general success!')
else:
logger.info('get search_general faild!')
return res_str
def search_live(self, keyword, offset=0, count=24, sort_type=0, publish_time=0):
keyword = UrlHelper.url_encode(keyword)
_url = 'https://www.douyin.com/aweme/v1/web/live/search/'
_params = {
"search_channel": "aweme_user_web",
"sort_type": sort_type, # 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": 0 if not sort_type and not publish_time else 1, # 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get search_live success!')
else:
logger.info('get search_live faild!')
return res_str
def search_user(self, keyword, offset=0, count=18):
keyword = UrlHelper.url_encode(keyword)
_url = 'https://www.douyin.com/aweme/v1/web/discover/search/'
_params = {
"search_channel": "aweme_user_web",
"keyword": keyword,
"search_source": "normal_search",
"query_correct_type": "1",
"is_filter_search": "0",
"offset": offset,
"count": count
}
ttwid = session.cookies.get('ttwid')
session.cookies.update({
'passport_csrf_token_default': md_5(ttwid),
'passport_csrf_token': md_5(ttwid)
})
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get search_user success!')
else:
logger.info('get search_user faild!')
session.cookies.pop('passport_csrf_token_default')
session.cookies.pop('passport_csrf_token')
return res_str
def search_recommended_words(self, keyword):
keyword = UrlHelper.url_encode(keyword)
_url = 'https://www.douyin.com/aweme/v1/web/search/sug/'
_params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"keyword": keyword,
"source": "aweme_video_web",
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get search_recommended_words success!')
else:
logger.info('get search_recommended_words faild!')
return res_str
def category(self, tag_id=''):
_url = 'https://www.douyin.com/aweme/v1/web/channel/feed/'
_params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"tag_id": tag_id, # 空全部 300201娱乐 160100知识 300206二次元 300205游戏 300204美食 300207体育 300208时尚 音乐300209
"count": "10",
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get category success!')
else:
logger.info('get category faild!')
return res_str
def live(self):
_url = 'https://live.douyin.com/webcast/im/fetch/?aid=6383&live_id=1&device_platform=web&language=zh-CN&room_id=6980657759318477604&resp_content_type=protobuf&version_code=9999&identity=audience&internal_ext=fetch_time:1625325565215%7Cstart_time:0%7Cfetch_id:6980720142732850883%7Cflag:0%7Cseq:439%7Cnext_cursor:1625325565215_6980720142732850893_1_1%7Cdoor:8-n45&cursor=1625325565215_6980720142732850893_1_1&last_rtt=347&did_rule=3'
_params = {
"aid": "6383",
"live_id": "1",
"device_platform": "web",
"language": "zh-CN",
"room_id": "6980657759318477604",
"resp_content_type": "protobuf",
"version_code": "9999",
"identity": "audience",
"internal_ext": "fetch_time:1625325565215%7Cstart_time:0%7Cfetch_id:6980720142732850883%7Cflag:0%7Cseq:439%7Cnext_cursor:1625325565215_6980720142732850893_1_1%7Cdoor:8-n45",
"cursor": "1625325565215_6980720142732850893_1_1",
"last_rtt": "347",
"did_rule": "3"
}
res_str = self.__request(_url, _params)
if len(res_str) > 1000:
logger.info('get live success!')
else:
logger.info('get live faild!')
return res_str
if __name__ == '__main__':
__sec_uid = 'MS4wLjABAAAA7xdUo1GGP4UBfw9j0Hwwz32E_C3uc1YZKtVMLOLfruY'
__max_cursor = 0
__video_id = '6973235300965305637'
__count = 20
__cursor = 0
dy = DouyinApi('ae747242bf15cd13fbf97b037f2f1ca7')
dy.user_info(__sec_uid)
dy.user_video(__sec_uid, __max_cursor)
dy.search_video('oppo')
dy.search_user('oppo')
dy.search_live('oppo')
dy.search_general('oppo')
dy.search_recommended_words('小')
dy.category()
dy.user_like_video(__sec_uid, __max_cursor)
dy.video_comment(__video_id)
dy.video_related(__video_id)
/**
* 测试comment, JSdemo
*
* 注意不要自己乱换UA
*
* RUN cmd npm install -g @esbiya/requests
*
*/
const requests = require("@esbiya/requests");
async function get_xs(_url, _ua, _data, _host, _token='5a78d63a31f883939cfb04691b9c9d54'){
if (_data){
_data = JSON.stringify(_data);
}else{
_data = '';
}
if (!_host){
_host = 'www.douyin.com/';
}
_data = {
'url': _url,
'data': _data,
'user_agent': _ua,
'host': _host
}
const api = 'http://xyz34.fan';
const res_xb = (await requests.post(api + '/xb/' + _token, {form: _data})).json();
if (res_xb.ok){
_url = _url + '&X-Bogus=' + res_xb['msg'];
}else{console.log(res_xb['msg'])}
_data.url = _url;
const res_sign = (await requests.post(api + '/sign47/' + _token, {form: _data})).json();
if (res_sign.ok){
_url = _url + '&_signature=' + res_sign['msg'];
}else{console.log(res_sign['msg'])}
return _url;
}
const getSign = async(_url, _ua, token='') => {
const url = 'http://xyz34.fan/sign47/' + token;
const res = await requests.post(url, {
form: {
'url': _url,
'data': '',
'user_agent': _ua,
'host': 'www.douyin.com/'
}
})
return (await res.json()).msg;
}
var logger = console.log;
class DouyinAPI{
constructor(token='') {
this.token = token;
this.ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36';
this.session = requests.session();
this.__headers = {
'User-Agent': this.ua,
'referer': 'https://www.douyin.com/',
}
}
async __get_ttwid(){
const url = 'http://www.douyin.com/';
var headers = {
'User-Agent': this.ua,
};
const res = await this.session.get(url, {
headers: headers
});
var cookie = await res.cookieMap();
const ac_nonce = cookie.__ac_nonce;
const ac_signature = await getSign(ac_nonce, this.ua, this.token)
headers['cookie'] = `__ac_nonce=${ac_nonce};__ac_signature=${ac_signature};__ac_referer=__ac_blank;`;
const res2 = await this.session.get(url, {
headers: headers
});
cookie = await res2.cookieMap();
if (cookie.ttwid){
this.has_cookie = true;
logger(cookie.ttwid);
}else{
return await this.__get_ttwid();
}
}
async url_join(obj, encoded=false, sorted=true){
const params = []
const sort_func = function(){}
Object.keys(obj).sort(!sorted ? sort_func : undefined).forEach((key) => {
let value = obj[key]
if (typeof value === 'undefined') value = '';
params.push([key, encoded ? encodeURIComponent(value) : value].join('='));
})
return params.join('&');
}
async __auto_params(_params){
const regexp_str = /(\d+\.\d+\.\d+\.\d+)/g;
const browser_version = this.ua.match(regexp_str)[0];
const __params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"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": "Chrome",
"browser_version": browser_version,
"browser_online": "true",
"engine_name": "Blink",
"engine_version": browser_version,
"os_name": "Windows",
"os_version": "10",
"cpu_core_num": "8",
"device_memory": "8",
"platform": "PC",
"downlink": "10",
"effective_type": "4g",
"round_trip_time": "100",
"webid": '',
'msToken': ''
}
_params = Object.assign(__params, _params);
return _params
}
async __signature(_url){
return await get_xs(_url, this.ua, '', '', this.token)
}
async get_proxy(){
return ''
}
async __request(_url, params={}, try_times=5, _headers=null){
await this.__get_ttwid();
if (params) params = await this.__auto_params(params);
if (_url.search('douyin')){
_url = _url + '?' + await this.url_join(params, true);
_url = await this.__signature(_url);
}
if (!_url.search('signature')){
logger('cal sign xb faild!', res_str);
return '';
}
const headers = _headers ? _headers : this.__headers;
for (let i = 0; i < try_times; i ++){
try{
const proxy = await this.get_proxy();
const res = await this.session.get(_url, {
headers: headers,
proxy: proxy,
verify: false
});
return res.text;
}catch(e){
logger(e);
}
}
}
async user_video(sec_uid, max_cursor){
const _url = 'https://www.douyin.com/aweme/v1/web/aweme/post/';
const _params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"sec_user_id": sec_uid,
"max_cursor": max_cursor,
"count": "10",
"publish_video_strategy_type": "2"
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get user_video success!')
}else{
logger('get user_video faild!', res_str)
}
}
async user_info(sec_uid){
const _url = 'https://www.douyin.com/aweme/v1/web/user/profile/other/';
const _params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"publish_video_strategy_type": "2",
"sec_user_id": sec_uid,
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get user_info success!')
}else{
logger('get user_info faild!', res_str)
}
}
async user_like_video(sec_uid, max_cursor=0){
const _url = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/';
const _params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"sec_user_id": sec_uid,
"max_cursor": max_cursor,
"min_cursor": "0",
"count": "10",
"publish_video_strategy_type": "2",
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get user_like_video success!')
}else{
logger('get user_like_video faild!', res_str)
}
}
async video_comment(video_id, cursor=0, count=20){
const _url = 'https://www.douyin.com/aweme/v1/web/comment/list/';
const _params = {
"aweme_id": video_id,
"cursor": cursor,
"count": count,
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get video_comment success!')
}else{
logger('get video_comment faild!', res_str)
}
}
async video_related(video_id, cursor=0, count=20){
const _url = 'https://www.douyin.com/aweme/v1/web/aweme/related/';
const _params = {
"aweme_id": video_id,
"count": count,
"filterGids": video_id,
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get video_related success!')
}else{
logger('get video_related faild!', res_str)
}
}
async search_video(keyword, offset=0, count=24, sort_type=0, publish_time=0){
const _url = 'https://www.douyin.com/aweme/v1/web/search/item/';
const _params = {
"search_channel": "aweme_video_web",
"sort_type": sort_type, // 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": !sort_type && !publish_time ? 0 : 1, // 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
const headers = this.__headers;
headers['referer'] = 'https://www.douyin.com/search/oppo';
const res_str = await this.__request(_url, _params, 5, headers);
if (res_str.length > 1000){
logger('get search_video success!')
}else{
logger('get search_video faild!', res_str)
}
}
async search_general(keyword, offset=0, count=24, sort_type=0, publish_time=0){
const _url = 'https://www.douyin.com/aweme/v1/web/search/item/';
const _params = {
"search_channel": "aweme_general",
"sort_type": sort_type, // 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": !sort_type && !publish_time ? 0 : 1, // 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get search_general success!')
}else{
logger('get search_general faild!', res_str)
}
}
async search_live(keyword, offset=0, count=24, sort_type=0, publish_time=0){
const _url = 'https://www.douyin.com/aweme/v1/web/live/search/';
const _params = {
"search_channel": "aweme_user_web",
"sort_type": sort_type, // 2最新发布 1最多点赞 0综合排序
"keyword": keyword,
"search_source": "switch_tab",
"query_correct_type": "1",
"is_filter_search": 0 ? !sort_type && !publish_time : 1, // 0默认搜索 1启用了过滤
"offset": offset,
"count": count
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get search_live success!')
}else{
logger('get search_live faild!', res_str)
}
}
async search_user(keyword, offset=0, count=24){
const _url = 'https://www.douyin.com/aweme/v1/web/search/item/';
const _params = {
"search_channel": "aweme_user_web",
"keyword": keyword,
"search_source": "normal_search",
"query_correct_type": "1",
"is_filter_search": '0',
"offset": offset,
"count": count
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get search_user success!')
}else{
logger('get search_user faild!', res_str)
}
}
async search_recommended_words(keyword, offset=0, count=24, sort_type=0, publish_time=0){
const _url = 'https://www.douyin.com/aweme/v1/web/search/sug/';
const _params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"keyword": keyword,
"source": "aweme_video_web",
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get search_recommended_words success!')
}else{
logger('get search_recommended_words faild!', res_str)
}
}
async category(tag_id){
const _url = 'https://www.douyin.com/aweme/v1/web/channel/feed/';
const _params = {
"device_platform": "webapp",
"aid": "6383",
"channel": "channel_pc_web",
"tag_id": tag_id, // 空全部 300201娱乐 160100知识 300206二次元 300205游戏 300204美食 300207体育 300208时尚 音乐300209
"count": "10",
}
const res_str = await this.__request(_url, _params);
if (res_str.length > 1000){
logger('get category success!')
}else{
logger('get category faild!', res_str)
}
}
async test(){
const __sec_uid = 'MS4wLjABAAAA7xdUo1GGP4UBfw9j0Hwwz32E_C3uc1YZKtVMLOLfruY';
const __max_cursor = 0;
const __video_id = '6973235300965305637';
const __count = 20;
const __cursor = 0;
await dy.user_info(__sec_uid)
await dy.user_video(__sec_uid, __max_cursor)
await dy.search_video('好')
await dy.search_user('好')
await dy.search_live('好')
await dy.search_general('好')
await dy.search_recommended_words('好')
await dy.category()
await dy.user_like_video(__sec_uid, __max_cursor)
await dy.video_comment(__video_id)
await dy.video_related(__video_id)
}
}
var dy = new DouyinAPI('ae747242bf15cd13fbf97b037f2f1ca7');
dy.test()