mirror of
https://github.com/imgyh/tiktok.git
synced 2025-06-01 15:59:18 +08:00
style(tiktok): 整理代码格式
This commit is contained in:
parent
48fcf902be
commit
064ae7dc63
318
.gitignore
vendored
318
.gitignore
vendored
@ -1,160 +1,160 @@
|
|||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
|
||||||
# Distribution / packaging
|
# Distribution / packaging
|
||||||
.Python
|
.Python
|
||||||
build/
|
build/
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
lib/
|
lib/
|
||||||
lib64/
|
lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
var/
|
var/
|
||||||
wheels/
|
wheels/
|
||||||
share/python-wheels/
|
share/python-wheels/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
MANIFEST
|
MANIFEST
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
*.manifest
|
*.manifest
|
||||||
*.spec
|
*.spec
|
||||||
|
|
||||||
# Installer logs
|
# Installer logs
|
||||||
pip-log.txt
|
pip-log.txt
|
||||||
pip-delete-this-directory.txt
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
# Unit test / coverage reports
|
# Unit test / coverage reports
|
||||||
htmlcov/
|
htmlcov/
|
||||||
.tox/
|
.tox/
|
||||||
.nox/
|
.nox/
|
||||||
.coverage
|
.coverage
|
||||||
.coverage.*
|
.coverage.*
|
||||||
.cache
|
.cache
|
||||||
nosetests.xml
|
nosetests.xml
|
||||||
coverage.xml
|
coverage.xml
|
||||||
*.cover
|
*.cover
|
||||||
*.py,cover
|
*.py,cover
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
cover/
|
cover/
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
*.pot
|
*.pot
|
||||||
|
|
||||||
# Django stuff:
|
# Django stuff:
|
||||||
*.log
|
*.log
|
||||||
local_settings.py
|
local_settings.py
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
db.sqlite3-journal
|
db.sqlite3-journal
|
||||||
|
|
||||||
# Flask stuff:
|
# Flask stuff:
|
||||||
instance/
|
instance/
|
||||||
.webassets-cache
|
.webassets-cache
|
||||||
|
|
||||||
# Scrapy stuff:
|
# Scrapy stuff:
|
||||||
.scrapy
|
.scrapy
|
||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
.pybuilder/
|
.pybuilder/
|
||||||
target/
|
target/
|
||||||
|
|
||||||
# Jupyter Notebook
|
# Jupyter Notebook
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
|
|
||||||
# IPython
|
# IPython
|
||||||
profile_default/
|
profile_default/
|
||||||
ipython_config.py
|
ipython_config.py
|
||||||
|
|
||||||
# pyenv
|
# pyenv
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
# .python-version
|
# .python-version
|
||||||
|
|
||||||
# pipenv
|
# pipenv
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
# install all needed dependencies.
|
# install all needed dependencies.
|
||||||
#Pipfile.lock
|
#Pipfile.lock
|
||||||
|
|
||||||
# poetry
|
# poetry
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
# commonly ignored for libraries.
|
# commonly ignored for libraries.
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
#poetry.lock
|
#poetry.lock
|
||||||
|
|
||||||
# pdm
|
# pdm
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
#pdm.lock
|
#pdm.lock
|
||||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
# in version control.
|
# in version control.
|
||||||
# https://pdm.fming.dev/#use-with-ide
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
.pdm.toml
|
.pdm.toml
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
__pypackages__/
|
__pypackages__/
|
||||||
|
|
||||||
# Celery stuff
|
# Celery stuff
|
||||||
celerybeat-schedule
|
celerybeat-schedule
|
||||||
celerybeat.pid
|
celerybeat.pid
|
||||||
|
|
||||||
# SageMath parsed files
|
# SageMath parsed files
|
||||||
*.sage.py
|
*.sage.py
|
||||||
|
|
||||||
# Environments
|
# Environments
|
||||||
.env
|
.env
|
||||||
.venv
|
.venv
|
||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
ENV/
|
ENV/
|
||||||
env.bak/
|
env.bak/
|
||||||
venv.bak/
|
venv.bak/
|
||||||
|
|
||||||
# Spyder project settings
|
# Spyder project settings
|
||||||
.spyderproject
|
.spyderproject
|
||||||
.spyproject
|
.spyproject
|
||||||
|
|
||||||
# Rope project settings
|
# Rope project settings
|
||||||
.ropeproject
|
.ropeproject
|
||||||
|
|
||||||
# mkdocs documentation
|
# mkdocs documentation
|
||||||
/site
|
/site
|
||||||
|
|
||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
.dmypy.json
|
.dmypy.json
|
||||||
dmypy.json
|
dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
# pytype static type analyzer
|
# pytype static type analyzer
|
||||||
.pytype/
|
.pytype/
|
||||||
|
|
||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
|
|
||||||
# PyCharm
|
# PyCharm
|
||||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
.idea/
|
.idea/
|
38
Dockerfile
38
Dockerfile
@ -1,19 +1,19 @@
|
|||||||
# This Dockerfile is used to build an Python environment
|
# This Dockerfile is used to build an Python environment
|
||||||
FROM node:18-bullseye-slim
|
FROM node:18-bullseye-slim
|
||||||
|
|
||||||
LABEL maintainer="imgyh<admin@imgyh.com>"
|
LABEL maintainer="imgyh<admin@imgyh.com>"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ADD . $WORKDIR
|
ADD . $WORKDIR
|
||||||
|
|
||||||
RUN sed -i s/deb.debian.org/mirrors.aliyun.com/g /etc/apt/sources.list
|
RUN sed -i s/deb.debian.org/mirrors.aliyun.com/g /etc/apt/sources.list
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y python3.9 python3-pip
|
RUN apt-get update && apt-get install -y python3.9 python3-pip
|
||||||
|
|
||||||
RUN pip3 install -r requirements.txt
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
ENV TZ=Asia/Shanghai
|
ENV TZ=Asia/Shanghai
|
||||||
|
|
||||||
CMD ["python3", "TikTokWeb.py"]
|
CMD ["python3", "TikTokWeb.py"]
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ class TikTok(object):
|
|||||||
userVideoUrls.append(videoRealUrl)
|
userVideoUrls.append(videoRealUrl)
|
||||||
return userVideoUrls
|
return userVideoUrls
|
||||||
|
|
||||||
|
|
||||||
tk = TikTok()
|
tk = TikTok()
|
||||||
# tk.oneVideoInfo()
|
# tk.oneVideoInfo()
|
||||||
tk.userVideoInfo()
|
tk.userVideoInfo()
|
||||||
|
68
TikTok.py
68
TikTok.py
@ -48,10 +48,10 @@ class TikTok(object):
|
|||||||
self.utils = Utils()
|
self.utils = Utils()
|
||||||
self.result = Result()
|
self.result = Result()
|
||||||
self.headers = {
|
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',
|
'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/',
|
'referer': 'https://www.douyin.com/',
|
||||||
'accept-encoding': None,
|
'accept-encoding': None,
|
||||||
'Cookie': f"msToken={self.utils.generate_random_str(107)}; ttwid={self.utils.getttwid()}; odin_tt=324fb4ea4a89c0c05827e18a1ed9cf9bf8a17f7705fcc793fec935b637867e2a5a9b8168c885554d029919117a18ba69; passport_csrf_token=f61602fc63757ae0e4fd9d6bdcee4810;"
|
'Cookie': f"msToken={self.utils.generate_random_str(107)}; ttwid={self.utils.getttwid()}; odin_tt=324fb4ea4a89c0c05827e18a1ed9cf9bf8a17f7705fcc793fec935b637867e2a5a9b8168c885554d029919117a18ba69; passport_csrf_token=f61602fc63757ae0e4fd9d6bdcee4810;"
|
||||||
}
|
}
|
||||||
# 用于设置重复请求某个接口的最大时间
|
# 用于设置重复请求某个接口的最大时间
|
||||||
self.timeout = 10
|
self.timeout = 10
|
||||||
@ -71,7 +71,6 @@ class TikTok(object):
|
|||||||
# self.done_event = Event()
|
# self.done_event = Event()
|
||||||
# signal.signal(signal.SIGINT, self.handle_sigint)
|
# signal.signal(signal.SIGINT, self.handle_sigint)
|
||||||
|
|
||||||
|
|
||||||
# 从分享链接中提取网址
|
# 从分享链接中提取网址
|
||||||
def getShareLink(self, string):
|
def getShareLink(self, string):
|
||||||
# findall() 查找匹配正则表达式的字符串
|
# findall() 查找匹配正则表达式的字符串
|
||||||
@ -145,7 +144,6 @@ class TikTok(object):
|
|||||||
|
|
||||||
return key_type, key
|
return key_type, key
|
||||||
|
|
||||||
|
|
||||||
def getAwemeInfoApi(self, aweme_id):
|
def getAwemeInfoApi(self, aweme_id):
|
||||||
if aweme_id is None:
|
if aweme_id is None:
|
||||||
return None
|
return None
|
||||||
@ -205,7 +203,7 @@ class TikTok(object):
|
|||||||
if end - start > self.timeout:
|
if end - start > self.timeout:
|
||||||
# raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据")
|
# raise RuntimeError("重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据")
|
||||||
print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据")
|
print("[ 提示 ]:重复请求该接口" + str(self.timeout) + "s, 仍然未获取到数据")
|
||||||
return {},{}
|
return {}, {}
|
||||||
# print("[ 警告 ]:接口未返回数据, 正在重新请求!\r")
|
# print("[ 警告 ]:接口未返回数据, 正在重新请求!\r")
|
||||||
|
|
||||||
# 清空self.awemeDict
|
# 清空self.awemeDict
|
||||||
@ -225,7 +223,6 @@ class TikTok(object):
|
|||||||
|
|
||||||
return self.result.awemeDict, datadict
|
return self.result.awemeDict, datadict
|
||||||
|
|
||||||
|
|
||||||
def getUserInfoApi(self, sec_uid, mode="post", count=35, max_cursor=0):
|
def getUserInfoApi(self, sec_uid, mode="post", count=35, max_cursor=0):
|
||||||
if sec_uid is None:
|
if sec_uid is None:
|
||||||
return None
|
return None
|
||||||
@ -346,10 +343,10 @@ class TikTok(object):
|
|||||||
awemeList.append(copy.deepcopy(self.result.awemeDict))
|
awemeList.append(copy.deepcopy(self.result.awemeDict))
|
||||||
|
|
||||||
if numflag:
|
if numflag:
|
||||||
number-=1
|
number -= 1
|
||||||
if number==0:
|
if number == 0:
|
||||||
break
|
break
|
||||||
if numflag and number==0:
|
if numflag and number == 0:
|
||||||
print("\r\n[ 提示 ]: [主页] 下指定数量作品数据获取完成...\r\n")
|
print("\r\n[ 提示 ]: [主页] 下指定数量作品数据获取完成...\r\n")
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -399,7 +396,8 @@ class TikTok(object):
|
|||||||
self.result.liveDict["cover"] = live_json['data']['data'][0]['cover']['url_list'][0]
|
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["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["user_count"] = live_json['data']['data'][0]['user_count_str']
|
||||||
@ -419,19 +417,20 @@ class TikTok(object):
|
|||||||
try:
|
try:
|
||||||
# 分区
|
# 分区
|
||||||
self.result.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title']
|
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'][
|
self.result.liveDict["sub_partition"] = \
|
||||||
|
live_json['data']['partition_road_map']['sub_partition']['partition'][
|
||||||
'title']
|
'title']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.result.liveDict["partition"] = '无'
|
self.result.liveDict["partition"] = '无'
|
||||||
self.result.liveDict["sub_partition"] = '无'
|
self.result.liveDict["sub_partition"] = '无'
|
||||||
|
|
||||||
|
|
||||||
flv = []
|
flv = []
|
||||||
|
|
||||||
for i, f in enumerate(self.result.liveDict["flv_pull_url"].keys()):
|
for i, f in enumerate(self.result.liveDict["flv_pull_url"].keys()):
|
||||||
flv.append(f)
|
flv.append(f)
|
||||||
|
|
||||||
self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[0]].replace("http://", "https://")
|
self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[0]].replace("http://",
|
||||||
|
"https://")
|
||||||
|
|
||||||
return self.result.liveDict, live_json
|
return self.result.liveDict, live_json
|
||||||
|
|
||||||
@ -477,7 +476,8 @@ class TikTok(object):
|
|||||||
self.result.liveDict["cover"] = live_json['data']['data'][0]['cover']['url_list'][0]
|
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["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["user_count"] = live_json['data']['data'][0]['user_count_str']
|
||||||
@ -497,7 +497,8 @@ class TikTok(object):
|
|||||||
try:
|
try:
|
||||||
# 分区
|
# 分区
|
||||||
self.result.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title']
|
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'][
|
self.result.liveDict["sub_partition"] = \
|
||||||
|
live_json['data']['partition_road_map']['sub_partition']['partition'][
|
||||||
'title']
|
'title']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.result.liveDict["partition"] = '无'
|
self.result.liveDict["partition"] = '无'
|
||||||
@ -516,7 +517,8 @@ class TikTok(object):
|
|||||||
|
|
||||||
rate = int(input('[ 🎬 ]输入数字选择推流清晰度:'))
|
rate = int(input('[ 🎬 ]输入数字选择推流清晰度:'))
|
||||||
|
|
||||||
self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[rate]].replace("http://", "https://")
|
self.result.liveDict["flv_pull_url0"] = self.result.liveDict["flv_pull_url"][flv[rate]].replace("http://",
|
||||||
|
"https://")
|
||||||
|
|
||||||
# 显示清晰度列表
|
# 显示清晰度列表
|
||||||
print('[ %s ]:%s' % (flv[rate], self.result.liveDict["flv_pull_url"][flv[rate]]))
|
print('[ %s ]:%s' % (flv[rate], self.result.liveDict["flv_pull_url"][flv[rate]]))
|
||||||
@ -544,7 +546,6 @@ class TikTok(object):
|
|||||||
if end - start > self.timeout:
|
if end - start > self.timeout:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
for aweme in datadict["aweme_list"]:
|
for aweme in datadict["aweme_list"]:
|
||||||
|
|
||||||
# 清空self.awemeDict
|
# 清空self.awemeDict
|
||||||
@ -672,13 +673,12 @@ class TikTok(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
for mix in datadict["mix_infos"]:
|
for mix in datadict["mix_infos"]:
|
||||||
mixIdNameDict={}
|
mixIdNameDict = {}
|
||||||
mixIdNameDict["https://www.douyin.com/collection/" + mix["mix_id"]] = mix["mix_name"]
|
mixIdNameDict["https://www.douyin.com/collection/" + mix["mix_id"]] = mix["mix_name"]
|
||||||
mixIdlist.append(mixIdNameDict)
|
mixIdlist.append(mixIdNameDict)
|
||||||
|
|
||||||
return mixIdlist, datadict, datadict["cursor"], datadict["has_more"]
|
return mixIdlist, datadict, datadict["cursor"], datadict["has_more"]
|
||||||
|
|
||||||
|
|
||||||
def getUserAllMixInfo(self, sec_uid, count=35, number=0):
|
def getUserAllMixInfo(self, sec_uid, count=35, number=0):
|
||||||
print('[ 提示 ]:正在请求的用户 id = %s\r\n' % sec_uid)
|
print('[ 提示 ]:正在请求的用户 id = %s\r\n' % sec_uid)
|
||||||
if sec_uid is None:
|
if sec_uid is None:
|
||||||
@ -762,7 +762,6 @@ class TikTok(object):
|
|||||||
if end - start > self.timeout:
|
if end - start > self.timeout:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
for aweme in datadict["aweme_list"]:
|
for aweme in datadict["aweme_list"]:
|
||||||
# 清空self.awemeDict
|
# 清空self.awemeDict
|
||||||
self.result.clearDict(self.result.awemeDict)
|
self.result.clearDict(self.result.awemeDict)
|
||||||
@ -924,7 +923,7 @@ class TikTok(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 使用作品 创建时间+描述 当文件夹
|
# 使用作品 创建时间+描述 当文件夹
|
||||||
file_name = awemeDict["create_time"] + "_" + self.utils.replaceStr(awemeDict["desc"])
|
file_name = awemeDict["create_time"] + "_" + self.utils.replaceStr(awemeDict["desc"])
|
||||||
aweme_path = os.path.join(savePath, file_name)
|
aweme_path = os.path.join(savePath, file_name)
|
||||||
if not os.path.exists(aweme_path):
|
if not os.path.exists(aweme_path):
|
||||||
os.mkdir(aweme_path)
|
os.mkdir(aweme_path)
|
||||||
@ -937,7 +936,7 @@ class TikTok(object):
|
|||||||
f.write(json.dumps(awemeDict, ensure_ascii=False, indent=2))
|
f.write(json.dumps(awemeDict, ensure_ascii=False, indent=2))
|
||||||
f.close()
|
f.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 错误 ]:保存 result.json 失败... 作品名: " + file_name +"\r\n")
|
print("[ 错误 ]:保存 result.json 失败... 作品名: " + file_name + "\r\n")
|
||||||
|
|
||||||
desc = file_name[:30]
|
desc = file_name[:30]
|
||||||
# 下载 视频
|
# 下载 视频
|
||||||
@ -958,7 +957,7 @@ class TikTok(object):
|
|||||||
self.alltask.append(
|
self.alltask.append(
|
||||||
self.pool.submit(self.progressBarDownload, url, video_path, "[ 视频 ]:" + desc))
|
self.pool.submit(self.progressBarDownload, url, video_path, "[ 视频 ]:" + desc))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 警告 ]:视频下载失败,请重试... 作品名: " + file_name +"\r\n")
|
print("[ 警告 ]:视频下载失败,请重试... 作品名: " + file_name + "\r\n")
|
||||||
|
|
||||||
# 下载 图集
|
# 下载 图集
|
||||||
if awemeDict["awemeType"] == 1:
|
if awemeDict["awemeType"] == 1:
|
||||||
@ -978,7 +977,7 @@ class TikTok(object):
|
|||||||
self.alltask.append(
|
self.alltask.append(
|
||||||
self.pool.submit(self.progressBarDownload, url, image_path, "[ 图集 ]:" + desc))
|
self.pool.submit(self.progressBarDownload, url, image_path, "[ 图集 ]:" + desc))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 警告 ]:图片下载失败,请重试... 作品名: " + file_name +"\r\n")
|
print("[ 警告 ]:图片下载失败,请重试... 作品名: " + file_name + "\r\n")
|
||||||
|
|
||||||
# 下载 音乐
|
# 下载 音乐
|
||||||
if music:
|
if music:
|
||||||
@ -999,7 +998,7 @@ class TikTok(object):
|
|||||||
self.alltask.append(
|
self.alltask.append(
|
||||||
self.pool.submit(self.progressBarDownload, url, music_path, "[ 原声 ]:" + desc))
|
self.pool.submit(self.progressBarDownload, url, music_path, "[ 原声 ]:" + desc))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 警告 ]:音乐(原声)下载失败,请重试... 作品名: " + file_name +"\r\n")
|
print("[ 警告 ]:音乐(原声)下载失败,请重试... 作品名: " + file_name + "\r\n")
|
||||||
|
|
||||||
# 下载 cover
|
# 下载 cover
|
||||||
if cover and awemeDict["awemeType"] == 0:
|
if cover and awemeDict["awemeType"] == 0:
|
||||||
@ -1019,7 +1018,7 @@ class TikTok(object):
|
|||||||
self.alltask.append(
|
self.alltask.append(
|
||||||
self.pool.submit(self.progressBarDownload, url, cover_path, "[ 封面 ]:" + desc))
|
self.pool.submit(self.progressBarDownload, url, cover_path, "[ 封面 ]:" + desc))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 警告 ]:cover下载失败,请重试... 作品名: " + file_name +"\r\n")
|
print("[ 警告 ]:cover下载失败,请重试... 作品名: " + file_name + "\r\n")
|
||||||
|
|
||||||
# 下载 avatar
|
# 下载 avatar
|
||||||
if avatar:
|
if avatar:
|
||||||
@ -1039,7 +1038,7 @@ class TikTok(object):
|
|||||||
self.alltask.append(
|
self.alltask.append(
|
||||||
self.pool.submit(self.progressBarDownload, url, avatar_path, "[ 头像 ]:" + desc))
|
self.pool.submit(self.progressBarDownload, url, avatar_path, "[ 头像 ]:" + desc))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 警告 ]:avatar下载失败,请重试... 作品名: " + file_name +"\r\n")
|
print("[ 警告 ]:avatar下载失败,请重试... 作品名: " + file_name + "\r\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("[ 错误 ]:下载作品时出错\r\n")
|
print("[ 错误 ]:下载作品时出错\r\n")
|
||||||
|
|
||||||
@ -1093,8 +1092,8 @@ class TikTok(object):
|
|||||||
# end = time.time() # 结束时间
|
# end = time.time() # 结束时间
|
||||||
# print('\n' + '[下载完成]:耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间
|
# 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(),
|
||||||
def userDownload(self, awemeList: list, music=True, cover=True, avatar=True, resjson=True, savePath=os.getcwd(), thread=5):
|
thread=5):
|
||||||
if awemeList is None:
|
if awemeList is None:
|
||||||
return
|
return
|
||||||
if not os.path.exists(savePath):
|
if not os.path.exists(savePath):
|
||||||
@ -1106,7 +1105,8 @@ class TikTok(object):
|
|||||||
start = time.time() # 开始时间
|
start = time.time() # 开始时间
|
||||||
|
|
||||||
for aweme in awemeList:
|
for aweme in awemeList:
|
||||||
self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, savePath=savePath)
|
self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson,
|
||||||
|
savePath=savePath)
|
||||||
# time.sleep(0.5)
|
# time.sleep(0.5)
|
||||||
wait(self.alltask, return_when=ALL_COMPLETED)
|
wait(self.alltask, return_when=ALL_COMPLETED)
|
||||||
|
|
||||||
@ -1116,7 +1116,8 @@ class TikTok(object):
|
|||||||
self.isdwownload = True
|
self.isdwownload = True
|
||||||
# 下载上一步失败的
|
# 下载上一步失败的
|
||||||
for aweme in awemeList:
|
for aweme in awemeList:
|
||||||
self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson, savePath=savePath)
|
self.awemeDownload(awemeDict=aweme, music=music, cover=cover, avatar=avatar, resjson=resjson,
|
||||||
|
savePath=savePath)
|
||||||
# time.sleep(0.5)
|
# time.sleep(0.5)
|
||||||
wait(self.alltask, return_when=ALL_COMPLETED)
|
wait(self.alltask, return_when=ALL_COMPLETED)
|
||||||
|
|
||||||
@ -1126,5 +1127,6 @@ class TikTok(object):
|
|||||||
end = time.time() # 结束时间
|
end = time.time() # 结束时间
|
||||||
print('\n' + '[下载完成]:耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间
|
print('\n' + '[下载完成]:耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
|
@ -42,6 +42,7 @@ configModel = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def argument():
|
def argument():
|
||||||
parser = argparse.ArgumentParser(description='抖音批量下载工具 使用帮助')
|
parser = argparse.ArgumentParser(description='抖音批量下载工具 使用帮助')
|
||||||
parser.add_argument("--cmd", "-C", help="使用命令行(True)或者配置文件(False), 默认为False",
|
parser.add_argument("--cmd", "-C", help="使用命令行(True)或者配置文件(False), 默认为False",
|
||||||
@ -50,7 +51,7 @@ def argument():
|
|||||||
help="作品(视频或图集)、直播、合集、音乐集合、个人主页的分享链接或者电脑浏览器网址, 可以设置多个链接(删除文案, 保证只有URL, https://v.douyin.com/kcvMpuN/ 或者 https://www.douyin.com/开头的)",
|
help="作品(视频或图集)、直播、合集、音乐集合、个人主页的分享链接或者电脑浏览器网址, 可以设置多个链接(删除文案, 保证只有URL, https://v.douyin.com/kcvMpuN/ 或者 https://www.douyin.com/开头的)",
|
||||||
type=str, required=False, default=[], action="append")
|
type=str, required=False, default=[], action="append")
|
||||||
parser.add_argument("--path", "-p", help="下载保存位置, 默认当前文件位置",
|
parser.add_argument("--path", "-p", help="下载保存位置, 默认当前文件位置",
|
||||||
type=str, required=False,default=os.getcwd())
|
type=str, required=False, default=os.getcwd())
|
||||||
parser.add_argument("--music", "-m", help="是否下载视频中的音乐(True/False), 默认为True",
|
parser.add_argument("--music", "-m", help="是否下载视频中的音乐(True/False), 默认为True",
|
||||||
type=Utils().str2bool, required=False, default=True)
|
type=Utils().str2bool, required=False, default=True)
|
||||||
parser.add_argument("--cover", "-c", help="是否下载视频的封面(True/False), 默认为True, 当下载视频时有效",
|
parser.add_argument("--cover", "-c", help="是否下载视频的封面(True/False), 默认为True, 当下载视频时有效",
|
||||||
@ -82,12 +83,13 @@ def argument():
|
|||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
def yamlConfig():
|
def yamlConfig():
|
||||||
curPath = os.path.dirname(os.path.realpath(sys.argv[0]))
|
curPath = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||||
yamlPath = os.path.join(curPath, "config.yml")
|
yamlPath = os.path.join(curPath, "config.yml")
|
||||||
f = open(yamlPath, 'r', encoding='utf-8')
|
f = open(yamlPath, 'r', encoding='utf-8')
|
||||||
cfg = f.read()
|
cfg = f.read()
|
||||||
configDict = yaml.load(stream=cfg,Loader=yaml.FullLoader)
|
configDict = yaml.load(stream=cfg, Loader=yaml.FullLoader)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if configDict["link"] != None:
|
if configDict["link"] != None:
|
||||||
@ -159,7 +161,7 @@ def yamlConfig():
|
|||||||
cookiekey = configDict["cookies"].keys()
|
cookiekey = configDict["cookies"].keys()
|
||||||
cookieStr = ""
|
cookieStr = ""
|
||||||
for i in cookiekey:
|
for i in cookiekey:
|
||||||
cookieStr = cookieStr + i + "=" + configDict["cookies"][i] + "; "
|
cookieStr = cookieStr + i + "=" + configDict["cookies"][i] + "; "
|
||||||
configModel["cookie"] = cookieStr
|
configModel["cookie"] = cookieStr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
@ -184,7 +186,7 @@ def main():
|
|||||||
configModel["avatar"] = args.avatar
|
configModel["avatar"] = args.avatar
|
||||||
configModel["json"] = args.json
|
configModel["json"] = args.json
|
||||||
if args.mode == None or args.mode == []:
|
if args.mode == None or args.mode == []:
|
||||||
args.mode=[]
|
args.mode = []
|
||||||
args.mode.append("post")
|
args.mode.append("post")
|
||||||
configModel["mode"] = list(set(args.mode))
|
configModel["mode"] = list(set(args.mode))
|
||||||
configModel["number"]["post"] = args.postnumber
|
configModel["number"]["post"] = args.postnumber
|
||||||
@ -215,7 +217,7 @@ def main():
|
|||||||
key_type, key = tk.getKey(url)
|
key_type, key = tk.getKey(url)
|
||||||
if key_type == "user":
|
if key_type == "user":
|
||||||
print("[ 提示 ]:正在请求用户主页下作品\r\n")
|
print("[ 提示 ]:正在请求用户主页下作品\r\n")
|
||||||
userPath = os.path.join(configModel["path"], "user_"+key)
|
userPath = os.path.join(configModel["path"], "user_" + key)
|
||||||
if not os.path.exists(userPath):
|
if not os.path.exists(userPath):
|
||||||
os.mkdir(userPath)
|
os.mkdir(userPath)
|
||||||
|
|
||||||
@ -242,13 +244,15 @@ def main():
|
|||||||
modePath = os.path.join(userPath, mode)
|
modePath = os.path.join(userPath, mode)
|
||||||
if not os.path.exists(modePath):
|
if not os.path.exists(modePath):
|
||||||
os.mkdir(modePath)
|
os.mkdir(modePath)
|
||||||
tk.userDownload(awemeList=datalist, music=configModel["music"], cover=configModel["cover"],
|
tk.userDownload(awemeList=datalist, music=configModel["music"],
|
||||||
|
cover=configModel["cover"],
|
||||||
avatar=configModel["avatar"], resjson=configModel["json"],
|
avatar=configModel["avatar"], resjson=configModel["json"],
|
||||||
savePath=os.path.join(modePath, mix_file_name), thread=configModel["thread"])
|
savePath=os.path.join(modePath, mix_file_name),
|
||||||
|
thread=configModel["thread"])
|
||||||
print(f'[ 提示 ]:合集 [{mixIdNameDict[mix_id]}] 中的作品下载完成\r\n')
|
print(f'[ 提示 ]:合集 [{mixIdNameDict[mix_id]}] 中的作品下载完成\r\n')
|
||||||
elif key_type == "mix":
|
elif key_type == "mix":
|
||||||
print("[ 提示 ]:正在请求单个合集下作品\r\n")
|
print("[ 提示 ]:正在请求单个合集下作品\r\n")
|
||||||
datalist = tk.getMixInfo(key,35, configModel["number"]["mix"])
|
datalist = tk.getMixInfo(key, 35, configModel["number"]["mix"])
|
||||||
if datalist is not None and datalist != []:
|
if datalist is not None and datalist != []:
|
||||||
mixPath = os.path.join(configModel["path"], "mix_" + key)
|
mixPath = os.path.join(configModel["path"], "mix_" + key)
|
||||||
if not os.path.exists(mixPath):
|
if not os.path.exists(mixPath):
|
||||||
@ -258,7 +262,7 @@ def main():
|
|||||||
savePath=mixPath, thread=configModel["thread"])
|
savePath=mixPath, thread=configModel["thread"])
|
||||||
elif key_type == "music":
|
elif key_type == "music":
|
||||||
print("[ 提示 ]:正在请求音乐(原声)下作品\r\n")
|
print("[ 提示 ]:正在请求音乐(原声)下作品\r\n")
|
||||||
datalist = tk.getMusicInfo(key,35, configModel["number"]["music"])
|
datalist = tk.getMusicInfo(key, 35, configModel["number"]["music"])
|
||||||
if datalist is not None and datalist != []:
|
if datalist is not None and datalist != []:
|
||||||
musicPath = os.path.join(configModel["path"], "music_" + key)
|
musicPath = os.path.join(configModel["path"], "music_" + key)
|
||||||
if not os.path.exists(musicPath):
|
if not os.path.exists(musicPath):
|
||||||
@ -281,19 +285,20 @@ def main():
|
|||||||
elif key_type == "live":
|
elif key_type == "live":
|
||||||
print("[ 提示 ]:正在进行直播解析\r\n")
|
print("[ 提示 ]:正在进行直播解析\r\n")
|
||||||
live_json = tk.getLiveInfo(key)
|
live_json = tk.getLiveInfo(key)
|
||||||
if configModel["json"]:
|
if configModel["json"]:
|
||||||
livePath = os.path.join(configModel["path"], "live")
|
livePath = os.path.join(configModel["path"], "live")
|
||||||
if not os.path.exists(livePath):
|
if not os.path.exists(livePath):
|
||||||
os.mkdir(livePath)
|
os.mkdir(livePath)
|
||||||
live_file_name = utils.replaceStr(key + live_json["nickname"])
|
live_file_name = utils.replaceStr(key + live_json["nickname"])
|
||||||
# 保存获取到json
|
# 保存获取到json
|
||||||
print("[ 提示 ]:正在保存获取到的信息到result.json\r\n")
|
print("[ 提示 ]:正在保存获取到的信息到result.json\r\n")
|
||||||
with open(os.path.join(livePath, live_file_name + ".json"), "w", encoding='utf-8') as f:
|
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.write(json.dumps(live_json, ensure_ascii=False, indent=2))
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
end = time.time() # 结束时间
|
end = time.time() # 结束时间
|
||||||
print('\n' + '[下载完成]:总耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间
|
print('\n' + '[下载完成]:总耗时: %d分钟%d秒\n' % (int((end - start) / 60), ((end - start) % 60))) # 输出下载用时时间
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
567
TikTokResult.py
567
TikTokResult.py
@ -1,283 +1,284 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@Description:TikTok.py
|
@Description:TikTok.py
|
||||||
@Date :2023/02/11 13:06:23
|
@Date :2023/02/11 13:06:23
|
||||||
@Author :imgyh
|
@Author :imgyh
|
||||||
@version :1.0
|
@version :1.0
|
||||||
@Github :https://github.com/imgyh
|
@Github :https://github.com/imgyh
|
||||||
@Mail :admin@imgyh.com
|
@Mail :admin@imgyh.com
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
Change Log :
|
Change Log :
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
class Result(object):
|
|
||||||
def __init__(self):
|
class Result(object):
|
||||||
# 作者信息
|
def __init__(self):
|
||||||
self.authorDict = {
|
# 作者信息
|
||||||
"avatar_thumb": {
|
self.authorDict = {
|
||||||
"height": "",
|
"avatar_thumb": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"avatar": {
|
},
|
||||||
"height": "",
|
"avatar": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"cover_url": {
|
},
|
||||||
"height": "",
|
"cover_url": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
# 喜欢的作品数
|
},
|
||||||
"favoriting_count": "",
|
# 喜欢的作品数
|
||||||
# 粉丝数
|
"favoriting_count": "",
|
||||||
"follower_count": "",
|
# 粉丝数
|
||||||
# 关注数
|
"follower_count": "",
|
||||||
"following_count": "",
|
# 关注数
|
||||||
# 昵称
|
"following_count": "",
|
||||||
"nickname": "",
|
# 昵称
|
||||||
# 是否允许下载
|
"nickname": "",
|
||||||
"prevent_download": "",
|
# 是否允许下载
|
||||||
# 用户 url id
|
"prevent_download": "",
|
||||||
"sec_uid": "",
|
# 用户 url id
|
||||||
# 是否私密账号
|
"sec_uid": "",
|
||||||
"secret": "",
|
# 是否私密账号
|
||||||
# 短id
|
"secret": "",
|
||||||
"short_id": "",
|
# 短id
|
||||||
# 签名
|
"short_id": "",
|
||||||
"signature": "",
|
# 签名
|
||||||
# 总获赞数
|
"signature": "",
|
||||||
"total_favorited": "",
|
# 总获赞数
|
||||||
# 用户id
|
"total_favorited": "",
|
||||||
"uid": "",
|
# 用户id
|
||||||
# 用户自定义唯一id 抖音号
|
"uid": "",
|
||||||
"unique_id": "",
|
# 用户自定义唯一id 抖音号
|
||||||
# 年龄
|
"unique_id": "",
|
||||||
"user_age": "",
|
# 年龄
|
||||||
|
"user_age": "",
|
||||||
}
|
|
||||||
# 图片信息
|
}
|
||||||
self.picDict = {
|
# 图片信息
|
||||||
"height": "",
|
self.picDict = {
|
||||||
"mask_url_list": "",
|
"height": "",
|
||||||
"uri": "",
|
"mask_url_list": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
}
|
"width": ""
|
||||||
# 音乐信息
|
}
|
||||||
self.musicDict = {
|
# 音乐信息
|
||||||
"cover_hd": {
|
self.musicDict = {
|
||||||
"height": "",
|
"cover_hd": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"cover_large": {
|
},
|
||||||
"height": "",
|
"cover_large": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"cover_medium": {
|
},
|
||||||
"height": "",
|
"cover_medium": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"cover_thumb": {
|
},
|
||||||
"height": "",
|
"cover_thumb": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
# 音乐作者抖音号
|
},
|
||||||
"owner_handle": "",
|
# 音乐作者抖音号
|
||||||
# 音乐作者id
|
"owner_handle": "",
|
||||||
"owner_id": "",
|
# 音乐作者id
|
||||||
# 音乐作者昵称
|
"owner_id": "",
|
||||||
"owner_nickname": "",
|
# 音乐作者昵称
|
||||||
"play_url": {
|
"owner_nickname": "",
|
||||||
"height": "",
|
"play_url": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_key": "",
|
"uri": "",
|
||||||
"url_list": [],
|
"url_key": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
# 音乐名字
|
},
|
||||||
"title": "",
|
# 音乐名字
|
||||||
}
|
"title": "",
|
||||||
# 视频信息
|
}
|
||||||
self.videoDict = {
|
# 视频信息
|
||||||
"play_addr": {
|
self.videoDict = {
|
||||||
"uri": "",
|
"play_addr": {
|
||||||
"url_list": "",
|
"uri": "",
|
||||||
},
|
"url_list": "",
|
||||||
"cover_original_scale": {
|
},
|
||||||
"height": "",
|
"cover_original_scale": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"dynamic_cover": {
|
},
|
||||||
"height": "",
|
"dynamic_cover": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"origin_cover": {
|
},
|
||||||
"height": "",
|
"origin_cover": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
},
|
"width": ""
|
||||||
"cover": {
|
},
|
||||||
"height": "",
|
"cover": {
|
||||||
"uri": "",
|
"height": "",
|
||||||
"url_list": [],
|
"uri": "",
|
||||||
"width": ""
|
"url_list": [],
|
||||||
}
|
"width": ""
|
||||||
}
|
}
|
||||||
# 作品信息
|
}
|
||||||
self.awemeDict = {
|
# 作品信息
|
||||||
# 作品创建时间
|
self.awemeDict = {
|
||||||
"create_time": "",
|
# 作品创建时间
|
||||||
# awemeType=0 视频, awemeType=1 图集, awemeType=2 直播
|
"create_time": "",
|
||||||
"awemeType": "",
|
# awemeType=0 视频, awemeType=1 图集, awemeType=2 直播
|
||||||
# 作品 id
|
"awemeType": "",
|
||||||
"aweme_id": "",
|
# 作品 id
|
||||||
# 作者信息
|
"aweme_id": "",
|
||||||
"author": self.authorDict,
|
# 作者信息
|
||||||
# 作品描述
|
"author": self.authorDict,
|
||||||
"desc": "",
|
# 作品描述
|
||||||
# 图片
|
"desc": "",
|
||||||
"images": [],
|
# 图片
|
||||||
# 音乐
|
"images": [],
|
||||||
"music": self.musicDict,
|
# 音乐
|
||||||
# 视频
|
"music": self.musicDict,
|
||||||
"video": self.videoDict,
|
# 视频
|
||||||
# 作品信息统计
|
"video": self.videoDict,
|
||||||
"statistics": {
|
# 作品信息统计
|
||||||
"admire_count": "",
|
"statistics": {
|
||||||
"collect_count": "",
|
"admire_count": "",
|
||||||
"comment_count": "",
|
"collect_count": "",
|
||||||
"digg_count": "",
|
"comment_count": "",
|
||||||
"play_count": "",
|
"digg_count": "",
|
||||||
"share_count": ""
|
"play_count": "",
|
||||||
}
|
"share_count": ""
|
||||||
}
|
}
|
||||||
# 用户作品信息
|
}
|
||||||
self.awemeList = []
|
# 用户作品信息
|
||||||
# 直播信息
|
self.awemeList = []
|
||||||
self.liveDict = {
|
# 直播信息
|
||||||
# awemeType=0 视频, awemeType=1 图集, awemeType=2 直播
|
self.liveDict = {
|
||||||
"awemeType": "",
|
# awemeType=0 视频, awemeType=1 图集, awemeType=2 直播
|
||||||
# 是否在播
|
"awemeType": "",
|
||||||
"status": "",
|
# 是否在播
|
||||||
# 直播标题
|
"status": "",
|
||||||
"title": "",
|
# 直播标题
|
||||||
# 直播cover
|
"title": "",
|
||||||
"cover": "",
|
# 直播cover
|
||||||
# 头像
|
"cover": "",
|
||||||
"avatar": "",
|
# 头像
|
||||||
# 观看人数
|
"avatar": "",
|
||||||
"user_count": "",
|
# 观看人数
|
||||||
# 昵称
|
"user_count": "",
|
||||||
"nickname": "",
|
# 昵称
|
||||||
# sec_uid
|
"nickname": "",
|
||||||
"sec_uid": "",
|
# sec_uid
|
||||||
# 直播间观看状态
|
"sec_uid": "",
|
||||||
"display_long": "",
|
# 直播间观看状态
|
||||||
# 推流
|
"display_long": "",
|
||||||
"flv_pull_url": "",
|
# 推流
|
||||||
# 分区
|
"flv_pull_url": "",
|
||||||
"partition": "",
|
# 分区
|
||||||
"sub_partition": "",
|
"partition": "",
|
||||||
# 最清晰的地址
|
"sub_partition": "",
|
||||||
"flv_pull_url0": "",
|
# 最清晰的地址
|
||||||
}
|
"flv_pull_url0": "",
|
||||||
|
}
|
||||||
# 将得到的json数据(dataRaw)精简成自己定义的数据(dataNew)
|
|
||||||
# 转换得到的数据
|
# 将得到的json数据(dataRaw)精简成自己定义的数据(dataNew)
|
||||||
def dataConvert(self, awemeType, dataNew, dataRaw):
|
# 转换得到的数据
|
||||||
for item in dataNew:
|
def dataConvert(self, awemeType, dataNew, dataRaw):
|
||||||
try:
|
for item in dataNew:
|
||||||
# 作品创建时间
|
try:
|
||||||
if item == "create_time":
|
# 作品创建时间
|
||||||
dataNew['create_time'] = time.strftime(
|
if item == "create_time":
|
||||||
"%Y-%m-%d %H.%M.%S", time.localtime(dataRaw['create_time']))
|
dataNew['create_time'] = time.strftime(
|
||||||
continue
|
"%Y-%m-%d %H.%M.%S", time.localtime(dataRaw['create_time']))
|
||||||
# 设置 awemeType
|
continue
|
||||||
if item == "awemeType":
|
# 设置 awemeType
|
||||||
dataNew["awemeType"] = awemeType
|
if item == "awemeType":
|
||||||
continue
|
dataNew["awemeType"] = awemeType
|
||||||
# 当 解析的链接 是图片时
|
continue
|
||||||
if item == "images":
|
# 当 解析的链接 是图片时
|
||||||
if awemeType == 1:
|
if item == "images":
|
||||||
for image in dataRaw[item]:
|
if awemeType == 1:
|
||||||
for i in image:
|
for image in dataRaw[item]:
|
||||||
self.picDict[i] = image[i]
|
for i in image:
|
||||||
# 字典要深拷贝
|
self.picDict[i] = image[i]
|
||||||
self.awemeDict["images"].append(copy.deepcopy(self.picDict))
|
# 字典要深拷贝
|
||||||
continue
|
self.awemeDict["images"].append(copy.deepcopy(self.picDict))
|
||||||
# 当 解析的链接 是视频时
|
continue
|
||||||
if item == "video":
|
# 当 解析的链接 是视频时
|
||||||
if awemeType == 0:
|
if item == "video":
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
if awemeType == 0:
|
||||||
continue
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
||||||
# 将小头像放大
|
continue
|
||||||
if item == "avatar":
|
# 将小头像放大
|
||||||
for i in dataNew[item]:
|
if item == "avatar":
|
||||||
if i == "url_list":
|
for i in dataNew[item]:
|
||||||
for j in self.awemeDict["author"]["avatar_thumb"]["url_list"]:
|
if i == "url_list":
|
||||||
dataNew[item][i].append(j.replace("100x100", "1080x1080"))
|
for j in self.awemeDict["author"]["avatar_thumb"]["url_list"]:
|
||||||
elif i == "uri":
|
dataNew[item][i].append(j.replace("100x100", "1080x1080"))
|
||||||
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i].replace("100x100",
|
elif i == "uri":
|
||||||
"1080x1080")
|
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i].replace("100x100",
|
||||||
else:
|
"1080x1080")
|
||||||
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i]
|
else:
|
||||||
continue
|
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i]
|
||||||
|
continue
|
||||||
# 原来的json是[{}] 而我们的是 {}
|
|
||||||
if item == "cover_url":
|
# 原来的json是[{}] 而我们的是 {}
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item][0])
|
if item == "cover_url":
|
||||||
continue
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item][0])
|
||||||
|
continue
|
||||||
# 根据 uri 获取 1080p 视频
|
|
||||||
if item == "play_addr":
|
# 根据 uri 获取 1080p 视频
|
||||||
dataNew[item]["uri"] = dataRaw["bit_rate"][0]["play_addr"]["uri"]
|
if item == "play_addr":
|
||||||
# 使用 这个api 可以获得1080p
|
dataNew[item]["uri"] = dataRaw["bit_rate"][0]["play_addr"]["uri"]
|
||||||
# dataNew[item]["url_list"] = "https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0" \
|
# 使用 这个api 可以获得1080p
|
||||||
# % dataNew[item]["uri"]
|
# dataNew[item]["url_list"] = "https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0" \
|
||||||
dataNew[item]["url_list"] = dataRaw["bit_rate"][0]["play_addr"]["url_list"][0]
|
# % dataNew[item]["uri"]
|
||||||
continue
|
dataNew[item]["url_list"] = dataRaw["bit_rate"][0]["play_addr"]["url_list"][0]
|
||||||
|
continue
|
||||||
# 常规 递归遍历 字典
|
|
||||||
if isinstance(dataNew[item], dict):
|
# 常规 递归遍历 字典
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
if isinstance(dataNew[item], dict):
|
||||||
else:
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
||||||
# 赋值
|
else:
|
||||||
dataNew[item] = dataRaw[item]
|
# 赋值
|
||||||
except Exception as e:
|
dataNew[item] = dataRaw[item]
|
||||||
# 删除这个警告, 总是让人误会出错了
|
except Exception as e:
|
||||||
# print("[ 警告 ]:转换数据时在接口中未找到 %s\r" % (item))
|
# 删除这个警告, 总是让人误会出错了
|
||||||
pass
|
# print("[ 警告 ]:转换数据时在接口中未找到 %s\r" % (item))
|
||||||
|
pass
|
||||||
def clearDict(self, data):
|
|
||||||
for item in data:
|
def clearDict(self, data):
|
||||||
# 常规 递归遍历 字典
|
for item in data:
|
||||||
if isinstance(data[item], dict):
|
# 常规 递归遍历 字典
|
||||||
self.clearDict(data[item])
|
if isinstance(data[item], dict):
|
||||||
elif isinstance(data[item], list):
|
self.clearDict(data[item])
|
||||||
data[item] = []
|
elif isinstance(data[item], list):
|
||||||
else:
|
data[item] = []
|
||||||
data[item] = ""
|
else:
|
||||||
|
data[item] = ""
|
||||||
|
210
TikTokTest.py
210
TikTokTest.py
@ -1,101 +1,109 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@Description:TikTok.py
|
@Description:TikTok.py
|
||||||
@Date :2023/02/11 13:06:23
|
@Date :2023/02/11 13:06:23
|
||||||
@Author :imgyh
|
@Author :imgyh
|
||||||
@version :1.0
|
@version :1.0
|
||||||
@Github :https://github.com/imgyh
|
@Github :https://github.com/imgyh
|
||||||
@Mail :admin@imgyh.com
|
@Mail :admin@imgyh.com
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
Change Log :
|
Change Log :
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
'''
|
'''
|
||||||
import TikTokUtils
|
import TikTokUtils
|
||||||
from TikTok import TikTok
|
from TikTok import TikTok
|
||||||
|
|
||||||
def getAwemeInfo():
|
|
||||||
share_link_video = "3.56 uSy:/ 复制打开抖音,看看【小透明的作品】没有女朋友就用我的吧哈哈哈哈 # 表情包锁屏 https://v.douyin.com/BugmVVD/"
|
def getAwemeInfo():
|
||||||
share_link_pic = "8.20 MJI:/ 复制打开抖音,看看【舍溪的图文作品】我又来放图集啦~还有你们要的小可爱大图也放啦~# ... https://v.douyin.com/BugrFTN/"
|
share_link_video = "3.56 uSy:/ 复制打开抖音,看看【小透明的作品】没有女朋友就用我的吧哈哈哈哈 # 表情包锁屏 https://v.douyin.com/BugmVVD/"
|
||||||
tk = TikTok()
|
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)
|
url = tk.getShareLink(share_link_pic)
|
||||||
datanew, dataraw = tk.getAwemeInfo(key)
|
key_type, key = tk.getKey(url)
|
||||||
print(datanew)
|
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/"
|
def getUserInfo():
|
||||||
tk = TikTok()
|
share_link_post = "1- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BupCppt/"
|
||||||
|
share_link_like = "2- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BusJrfr/"
|
||||||
url = tk.getShareLink(share_link_like)
|
tk = TikTok()
|
||||||
key_type, key = tk.getKey(url)
|
|
||||||
awemeList = tk.getUserInfo(key, mode="like", count=35)
|
url = tk.getShareLink(share_link_like)
|
||||||
print(awemeList)
|
key_type, key = tk.getKey(url)
|
||||||
|
awemeList = tk.getUserInfo(key, mode="like", count=35)
|
||||||
def getLiveInfo():
|
print(awemeList)
|
||||||
live_link = "https://live.douyin.com/40768897856"
|
|
||||||
tk = TikTok()
|
|
||||||
|
def getLiveInfo():
|
||||||
url = tk.getShareLink(live_link)
|
live_link = "https://live.douyin.com/40768897856"
|
||||||
key_type, key = tk.getKey(url)
|
tk = TikTok()
|
||||||
live_json = tk.getLiveInfo(key)
|
|
||||||
print(live_json)
|
url = tk.getShareLink(live_link)
|
||||||
|
key_type, key = tk.getKey(url)
|
||||||
def getMixInfo():
|
live_json = tk.getLiveInfo(key)
|
||||||
mix_link = 'https://v.douyin.com/B3J63Le/'
|
print(live_json)
|
||||||
tk = TikTok()
|
|
||||||
|
|
||||||
url = tk.getShareLink(mix_link)
|
def getMixInfo():
|
||||||
key_type, key = tk.getKey(url)
|
mix_link = 'https://v.douyin.com/B3J63Le/'
|
||||||
awemeList = tk.getMixInfo(key, count=35)
|
tk = TikTok()
|
||||||
print(len(awemeList))
|
|
||||||
|
url = tk.getShareLink(mix_link)
|
||||||
def getUserAllMixInfo():
|
key_type, key = tk.getKey(url)
|
||||||
user_all_mix_link = 'https://v.douyin.com/B38oovu/'
|
awemeList = tk.getMixInfo(key, count=35)
|
||||||
tk = TikTok()
|
print(len(awemeList))
|
||||||
|
|
||||||
url = tk.getShareLink(user_all_mix_link)
|
|
||||||
key_type, key = tk.getKey(url)
|
def getUserAllMixInfo():
|
||||||
mixIdNameDict = tk.getUserAllMixInfo(key, count=35)
|
user_all_mix_link = 'https://v.douyin.com/B38oovu/'
|
||||||
print(mixIdNameDict)
|
tk = TikTok()
|
||||||
|
|
||||||
def getMusicInfo():
|
url = tk.getShareLink(user_all_mix_link)
|
||||||
music_link = 'https://v.douyin.com/S6YMNXs/'
|
key_type, key = tk.getKey(url)
|
||||||
tk = TikTok()
|
mixIdNameDict = tk.getUserAllMixInfo(key, count=35)
|
||||||
|
print(mixIdNameDict)
|
||||||
url = tk.getShareLink(music_link)
|
|
||||||
key_type, key = tk.getKey(url)
|
|
||||||
awemeList = tk.getMusicInfo(key,count=35)
|
def getMusicInfo():
|
||||||
print(len(awemeList))
|
music_link = 'https://v.douyin.com/S6YMNXs/'
|
||||||
|
tk = TikTok()
|
||||||
def test():
|
|
||||||
utils=TikTokUtils.Utils()
|
url = tk.getShareLink(music_link)
|
||||||
user_all_mix_link = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?'+\
|
key_type, key = tk.getKey(url)
|
||||||
utils.getXbogus(url='device_platform=webapp&aid=6383&sec_user_id=MS4wLjABAAAAjQn6ONfaGgUpk0Q1ep8dPiD3W4T_lxTJmemfy3MTJ64&max_cursor=1676441180000&count=10')
|
awemeList = tk.getMusicInfo(key, count=35)
|
||||||
headers = {
|
print(len(awemeList))
|
||||||
'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,
|
def test():
|
||||||
'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"' }
|
utils = TikTokUtils.Utils()
|
||||||
|
user_all_mix_link = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?' + \
|
||||||
import requests
|
utils.getXbogus(
|
||||||
|
url='device_platform=webapp&aid=6383&sec_user_id=MS4wLjABAAAAjQn6ONfaGgUpk0Q1ep8dPiD3W4T_lxTJmemfy3MTJ64&max_cursor=1676441180000&count=10')
|
||||||
res = requests.get(user_all_mix_link,headers=headers).text
|
headers = {
|
||||||
import json
|
'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',
|
||||||
datadict = json.loads(res)
|
'referer': 'https://www.douyin.com/',
|
||||||
print(datadict["aweme_list"][0]["video"]["bit_rate"])
|
'accept-encoding': None,
|
||||||
print(len(datadict["aweme_list"][0]["video"]["bit_rate"]))
|
'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"'}
|
||||||
|
|
||||||
if __name__ == "__main__":
|
import requests
|
||||||
# test()
|
|
||||||
# getMusicInfo()
|
res = requests.get(user_all_mix_link, headers=headers).text
|
||||||
# getUserAllMixInfo()
|
import json
|
||||||
# getMixInfo()
|
datadict = json.loads(res)
|
||||||
# getAwemeInfo()
|
print(datadict["aweme_list"][0]["video"]["bit_rate"])
|
||||||
# getUserInfo()
|
print(len(datadict["aweme_list"][0]["video"]["bit_rate"]))
|
||||||
# getLiveInfo()
|
|
||||||
pass
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# test()
|
||||||
|
# getMusicInfo()
|
||||||
|
# getUserAllMixInfo()
|
||||||
|
# getMixInfo()
|
||||||
|
# getAwemeInfo()
|
||||||
|
# getUserInfo()
|
||||||
|
# getLiveInfo()
|
||||||
|
pass
|
||||||
|
179
TikTokUrls.py
179
TikTokUrls.py
@ -1,89 +1,90 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@Description:TikTok.py
|
@Description:TikTok.py
|
||||||
@Date :2023/02/11 13:06:23
|
@Date :2023/02/11 13:06:23
|
||||||
@Author :imgyh
|
@Author :imgyh
|
||||||
@version :1.0
|
@version :1.0
|
||||||
@Github :https://github.com/imgyh
|
@Github :https://github.com/imgyh
|
||||||
@Mail :admin@imgyh.com
|
@Mail :admin@imgyh.com
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
Change Log :
|
Change Log :
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class Urls(object):
|
class Urls(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# https://langyue.cc/APIdocV1.0.html
|
# https://langyue.cc/APIdocV1.0.html
|
||||||
######################################### WEB #########################################
|
######################################### WEB #########################################
|
||||||
# 首页推荐
|
# 首页推荐
|
||||||
self.TAB_FEED = 'https://www.douyin.com/aweme/v1/web/tab/feed/?'
|
self.TAB_FEED = 'https://www.douyin.com/aweme/v1/web/tab/feed/?'
|
||||||
|
|
||||||
# 用户短信息(给多少个用户secid就返回多少的用户信息)
|
# 用户短信息(给多少个用户secid就返回多少的用户信息)
|
||||||
self.USER_SHORT_INFO = 'https://www.douyin.com/aweme/v1/web/im/user/info/?'
|
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/?'
|
self.USER_DETAIL = 'https://www.douyin.com/aweme/v1/web/user/profile/other/?'
|
||||||
|
|
||||||
# 用户作品
|
# 用户作品
|
||||||
# cookies 暂时只需要 __ac_signature, s_v_web_id两个参数, 好像会过期
|
# cookies 暂时只需要 __ac_signature, s_v_web_id两个参数, 好像会过期
|
||||||
# url 暂时不需要携带 msToken, X-Bogus, _signature
|
# url 暂时不需要携带 msToken, X-Bogus, _signature
|
||||||
# 每次返回数据很少
|
# 每次返回数据很少
|
||||||
# self.USER_POST = 'https://m.douyin.com/web/api/v2/aweme/post/?'
|
# self.USER_POST = 'https://m.douyin.com/web/api/v2/aweme/post/?'
|
||||||
# 2023/02/19 失效
|
# 2023/02/19 失效
|
||||||
self.USER_POST = 'https://www.douyin.com/aweme/v1/web/aweme/post/?'
|
self.USER_POST = 'https://www.douyin.com/aweme/v1/web/aweme/post/?'
|
||||||
|
|
||||||
# 作品信息
|
# 作品信息
|
||||||
self.POST_DETAIL = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?'
|
self.POST_DETAIL = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?'
|
||||||
|
|
||||||
# 用户喜欢A
|
# 用户喜欢A
|
||||||
# 需要 odin_tt
|
# 需要 odin_tt
|
||||||
self.USER_FAVORITE_A = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?'
|
self.USER_FAVORITE_A = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?'
|
||||||
|
|
||||||
# 用户喜欢B
|
# 用户喜欢B
|
||||||
self.USER_FAVORITE_B = 'https://www.iesdouyin.com/web/api/v2/aweme/like/?'
|
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_HISTORY = 'https://www.douyin.com/aweme/v1/web/history/read/?'
|
||||||
|
|
||||||
# 用户收藏
|
# 用户收藏
|
||||||
self.USER_COLLECTION = 'https://www.douyin.com/aweme/v1/web/aweme/listcollection/?'
|
self.USER_COLLECTION = 'https://www.douyin.com/aweme/v1/web/aweme/listcollection/?'
|
||||||
|
|
||||||
# 用户评论
|
# 用户评论
|
||||||
self.COMMENT = 'https://www.douyin.com/aweme/v1/web/comment/list/?'
|
self.COMMENT = 'https://www.douyin.com/aweme/v1/web/comment/list/?'
|
||||||
|
|
||||||
# 首页朋友作品
|
# 首页朋友作品
|
||||||
self.FRIEND_FEED = 'https://www.douyin.com/aweme/v1/web/familiar/feed/?'
|
self.FRIEND_FEED = 'https://www.douyin.com/aweme/v1/web/familiar/feed/?'
|
||||||
|
|
||||||
# 关注用户作品
|
# 关注用户作品
|
||||||
self.FOLLOW_FEED = 'https://www.douyin.com/aweme/v1/web/follow/feed/?'
|
self.FOLLOW_FEED = 'https://www.douyin.com/aweme/v1/web/follow/feed/?'
|
||||||
|
|
||||||
# 合集下所有作品
|
# 合集下所有作品
|
||||||
# 只需要X-Bogus
|
# 只需要X-Bogus
|
||||||
self.USER_MIX = 'https://www.douyin.com/aweme/v1/web/mix/aweme/?'
|
self.USER_MIX = 'https://www.douyin.com/aweme/v1/web/mix/aweme/?'
|
||||||
|
|
||||||
# 用户所有合集列表
|
# 用户所有合集列表
|
||||||
# 需要 ttwid
|
# 需要 ttwid
|
||||||
self.USER_MIX_LIST = 'https://www.douyin.com/aweme/v1/web/mix/list/?'
|
self.USER_MIX_LIST = 'https://www.douyin.com/aweme/v1/web/mix/list/?'
|
||||||
|
|
||||||
# 直播
|
# 直播
|
||||||
self.LIVE = 'https://live.douyin.com/webcast/room/web/enter/?'
|
self.LIVE = 'https://live.douyin.com/webcast/room/web/enter/?'
|
||||||
self.LIVE2 = 'https://webcast.amemv.com/webcast/room/reflow/info/?'
|
self.LIVE2 = 'https://webcast.amemv.com/webcast/room/reflow/info/?'
|
||||||
|
|
||||||
# 音乐
|
# 音乐
|
||||||
self.MUSIC = 'https://www.douyin.com/aweme/v1/web/music/aweme/?'
|
self.MUSIC = 'https://www.douyin.com/aweme/v1/web/music/aweme/?'
|
||||||
|
|
||||||
# X-Bogus Path
|
# X-Bogus Path
|
||||||
# 60 秒内,请求同一URI累计超过 600 次,封锁IP 300 秒
|
# 60 秒内,请求同一URI累计超过 600 次,封锁IP 300 秒
|
||||||
# 两个都可以用
|
# 两个都可以用
|
||||||
# 服务器在国外
|
# 服务器在国外
|
||||||
# self.GET_XB_PATH = 'https://tiktok.199933.xyz/xb'
|
# self.GET_XB_PATH = 'https://tiktok.199933.xyz/xb'
|
||||||
# 服务器在国内
|
# 服务器在国内
|
||||||
self.GET_XB_PATH = 'http://47.115.208.101:9090/xb'
|
self.GET_XB_PATH = 'http://47.115.208.101:9090/xb'
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
Urls()
|
if __name__ == '__main__':
|
||||||
|
Urls()
|
||||||
|
@ -22,6 +22,7 @@ import sys
|
|||||||
import json
|
import json
|
||||||
from TikTokUrls import Urls
|
from TikTokUrls import Urls
|
||||||
|
|
||||||
|
|
||||||
class Utils(object):
|
class Utils(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
@ -52,7 +53,7 @@ class Utils(object):
|
|||||||
# 去除前后空格
|
# 去除前后空格
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def resource_path(self,relative_path):
|
def resource_path(self, relative_path):
|
||||||
if getattr(sys, 'frozen', False): # 是否Bundle Resource
|
if getattr(sys, 'frozen', False): # 是否Bundle Resource
|
||||||
base_path = sys._MEIPASS
|
base_path = sys._MEIPASS
|
||||||
else:
|
else:
|
||||||
@ -62,9 +63,10 @@ class Utils(object):
|
|||||||
def getXbogus(self, url, headers=None):
|
def getXbogus(self, url, headers=None):
|
||||||
# getXbogus算法开源地址https://github.com/B1gM8c/tiktok
|
# getXbogus算法开源地址https://github.com/B1gM8c/tiktok
|
||||||
user_agent = headers.get(
|
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"
|
'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:
|
try:
|
||||||
xbogus = execjs.compile(open(self.resource_path(os.path.join("X-Bogus.js"))).read()).call('sign', url, user_agent)
|
xbogus = execjs.compile(open(self.resource_path(os.path.join("X-Bogus.js"))).read()).call('sign', url,
|
||||||
|
user_agent)
|
||||||
params = url + "&X-Bogus=" + xbogus
|
params = url + "&X-Bogus=" + xbogus
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# print('[ 错误 ]:X-Bogus算法异常或者本地没有JS环境')
|
# print('[ 错误 ]:X-Bogus算法异常或者本地没有JS环境')
|
||||||
@ -79,8 +81,6 @@ class Utils(object):
|
|||||||
return
|
return
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def str2bool(self, v):
|
def str2bool(self, v):
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
return v
|
return v
|
||||||
@ -97,7 +97,7 @@ class Utils(object):
|
|||||||
data = '{"region":"cn","aid":1768,"needFid":false,"service":"www.ixigua.com","migrate_info":{"ticket":"","source":"node"},"cbUrlProtocol":"https","union":true}'
|
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)
|
res = requests.post(url=url, data=data)
|
||||||
|
|
||||||
for i,j in res.cookies.items():
|
for i, j in res.cookies.items():
|
||||||
return j
|
return j
|
||||||
|
|
||||||
|
|
||||||
|
16
TikTokWeb.py
16
TikTokWeb.py
@ -33,7 +33,8 @@ def work(share_link, max_cursor, mode, cookie):
|
|||||||
has_more = None
|
has_more = None
|
||||||
if key_type == "user":
|
if key_type == "user":
|
||||||
if mode == 'post' or mode == 'like':
|
if mode == 'post' or mode == 'like':
|
||||||
datalist, rawdatalist, cursor, has_more = tk.getUserInfoApi(sec_uid=key, mode=mode, count=35, max_cursor=max_cursor)
|
datalist, rawdatalist, cursor, has_more = tk.getUserInfoApi(sec_uid=key, mode=mode, count=35,
|
||||||
|
max_cursor=max_cursor)
|
||||||
elif mode == 'mix':
|
elif mode == 'mix':
|
||||||
datalist, rawdatalist, cursor, has_more = tk.getUserAllMixInfoApi(sec_uid=key, count=35, cursor=max_cursor)
|
datalist, rawdatalist, cursor, has_more = tk.getUserAllMixInfoApi(sec_uid=key, count=35, cursor=max_cursor)
|
||||||
elif key_type == "mix":
|
elif key_type == "mix":
|
||||||
@ -45,7 +46,7 @@ def work(share_link, max_cursor, mode, cookie):
|
|||||||
elif key_type == "live":
|
elif key_type == "live":
|
||||||
datalist, rawdatalist = tk.getLiveInfoApi(web_rid=key)
|
datalist, rawdatalist = tk.getLiveInfoApi(web_rid=key)
|
||||||
|
|
||||||
datadict={}
|
datadict = {}
|
||||||
|
|
||||||
if datalist is not None and datalist != []:
|
if datalist is not None and datalist != []:
|
||||||
datadict["data"] = datalist
|
datadict["data"] = datalist
|
||||||
@ -57,6 +58,7 @@ def work(share_link, max_cursor, mode, cookie):
|
|||||||
datadict["status_code"] = 500
|
datadict["status_code"] = 500
|
||||||
return datadict
|
return datadict
|
||||||
|
|
||||||
|
|
||||||
def deal(mode=None):
|
def deal(mode=None):
|
||||||
usefuldict = {}
|
usefuldict = {}
|
||||||
if request.headers.get("content_type") == "application/json":
|
if request.headers.get("content_type") == "application/json":
|
||||||
@ -83,10 +85,12 @@ def deal(mode=None):
|
|||||||
usefuldict["status_code"] = 500
|
usefuldict["status_code"] = 500
|
||||||
return jsonify(usefuldict)
|
return jsonify(usefuldict)
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
# 设置编码
|
# 设置编码
|
||||||
app.config['JSON_AS_ASCII'] = False
|
app.config['JSON_AS_ASCII'] = False
|
||||||
|
|
||||||
|
|
||||||
def argument():
|
def argument():
|
||||||
parser = argparse.ArgumentParser(description='抖音去水印工具 使用帮助')
|
parser = argparse.ArgumentParser(description='抖音去水印工具 使用帮助')
|
||||||
parser.add_argument("--port", "-p", help="Web端口",
|
parser.add_argument("--port", "-p", help="Web端口",
|
||||||
@ -95,34 +99,42 @@ def argument():
|
|||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/music", methods=["POST"])
|
@app.route("/douyin/music", methods=["POST"])
|
||||||
def douyinMusic():
|
def douyinMusic():
|
||||||
return deal()
|
return deal()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/mix", methods=["POST"])
|
@app.route("/douyin/mix", methods=["POST"])
|
||||||
def douyinMix():
|
def douyinMix():
|
||||||
return deal()
|
return deal()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/user/mix", methods=["POST"])
|
@app.route("/douyin/user/mix", methods=["POST"])
|
||||||
def douyinUserMix():
|
def douyinUserMix():
|
||||||
return deal(mode="mix")
|
return deal(mode="mix")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/user/like", methods=["POST"])
|
@app.route("/douyin/user/like", methods=["POST"])
|
||||||
def douyinUserLike():
|
def douyinUserLike():
|
||||||
return deal(mode="like")
|
return deal(mode="like")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/user/post", methods=["POST"])
|
@app.route("/douyin/user/post", methods=["POST"])
|
||||||
def douyinUserPost():
|
def douyinUserPost():
|
||||||
return deal(mode="post")
|
return deal(mode="post")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/aweme", methods=["POST"])
|
@app.route("/douyin/aweme", methods=["POST"])
|
||||||
def douyinAweme():
|
def douyinAweme():
|
||||||
return deal()
|
return deal()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin/live", methods=["POST"])
|
@app.route("/douyin/live", methods=["POST"])
|
||||||
def douyinLive():
|
def douyinLive():
|
||||||
return deal()
|
return deal()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/douyin", methods=["POST"])
|
@app.route("/douyin", methods=["POST"])
|
||||||
def douyin():
|
def douyin():
|
||||||
return deal()
|
return deal()
|
||||||
|
162
config.yml
162
config.yml
@ -1,81 +1,81 @@
|
|||||||
#######################################
|
#######################################
|
||||||
# 说明:
|
# 说明:
|
||||||
# 1. 井号(#)为注释
|
# 1. 井号(#)为注释
|
||||||
# 2. 缩进严格对齐,使用空格缩进, 注意有些冒号后面有一个空格, 有些没有空格
|
# 2. 缩进严格对齐,使用空格缩进, 注意有些冒号后面有一个空格, 有些没有空格
|
||||||
# 3. 请使用英文字符
|
# 3. 请使用英文字符
|
||||||
# 4. 更多yaml语法请上网查看
|
# 4. 更多yaml语法请上网查看
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
|
|
||||||
# 作品(视频或图集)、直播、合集、音乐集合、个人主页的分享链接或者电脑浏览器网址
|
# 作品(视频或图集)、直播、合集、音乐集合、个人主页的分享链接或者电脑浏览器网址
|
||||||
# (删除文案, 保证只有URL, https://v.douyin.com/kcvMpuN/ 或者 https://www.douyin.com/开头的)
|
# (删除文案, 保证只有URL, https://v.douyin.com/kcvMpuN/ 或者 https://www.douyin.com/开头的)
|
||||||
# 可以设置多个链接, 确保至少一个链接
|
# 可以设置多个链接, 确保至少一个链接
|
||||||
# 必选
|
# 必选
|
||||||
link:
|
link:
|
||||||
- https://live.douyin.com/759547612580
|
- https://live.douyin.com/759547612580
|
||||||
- https://v.douyin.com/BugmVVD/
|
- https://v.douyin.com/BugmVVD/
|
||||||
- https://v.douyin.com/BugrFTN/
|
- https://v.douyin.com/BugrFTN/
|
||||||
- https://v.douyin.com/B72pdU5/
|
- https://v.douyin.com/B72pdU5/
|
||||||
- https://v.douyin.com/B72QgDw/
|
- https://v.douyin.com/B72QgDw/
|
||||||
- https://v.douyin.com/AJp8D3f/
|
- https://v.douyin.com/AJp8D3f/
|
||||||
- https://v.douyin.com/B38oovu/
|
- https://v.douyin.com/B38oovu/
|
||||||
- https://v.douyin.com/S6YMNXs/
|
- https://v.douyin.com/S6YMNXs/
|
||||||
|
|
||||||
# 下载保存位置, 默认当前文件位置
|
# 下载保存位置, 默认当前文件位置
|
||||||
# 必选
|
# 必选
|
||||||
path: /mnt/c/project/test333
|
path: /mnt/c/project/test333
|
||||||
|
|
||||||
# 是否下载视频中的音乐(True/False), 默认为True
|
# 是否下载视频中的音乐(True/False), 默认为True
|
||||||
# 可选
|
# 可选
|
||||||
music: True
|
music: True
|
||||||
|
|
||||||
# 是否下载视频的封面(True/False), 默认为True, 当下载视频时有效
|
# 是否下载视频的封面(True/False), 默认为True, 当下载视频时有效
|
||||||
# 可选
|
# 可选
|
||||||
cover: True
|
cover: True
|
||||||
|
|
||||||
# 是否下载作者的头像(True/False), 默认为True
|
# 是否下载作者的头像(True/False), 默认为True
|
||||||
# 可选
|
# 可选
|
||||||
avatar: True
|
avatar: True
|
||||||
|
|
||||||
# 是否保存获取到的数据(True/False), 默认为True
|
# 是否保存获取到的数据(True/False), 默认为True
|
||||||
# 可选
|
# 可选
|
||||||
json: True
|
json: True
|
||||||
|
|
||||||
# link是个人主页时, 设置下载发布的作品(post)或喜欢的作品(like)或者用户所有合集(mix), 默认为post, 可以设置多种模式
|
# link是个人主页时, 设置下载发布的作品(post)或喜欢的作品(like)或者用户所有合集(mix), 默认为post, 可以设置多种模式
|
||||||
# 可选
|
# 可选
|
||||||
mode:
|
mode:
|
||||||
- post
|
- post
|
||||||
- like
|
- like
|
||||||
- mix
|
- mix
|
||||||
|
|
||||||
# 下载作品个数设置
|
# 下载作品个数设置
|
||||||
# 可选
|
# 可选
|
||||||
number:
|
number:
|
||||||
post: 5 # 主页下作品下载个数设置, 默认为0 全部下载
|
post: 5 # 主页下作品下载个数设置, 默认为0 全部下载
|
||||||
like: 5 # 主页下喜欢下载个数设置, 默认为0 全部下载
|
like: 5 # 主页下喜欢下载个数设置, 默认为0 全部下载
|
||||||
allmix: 1 # 主页下合集下载个数设置, 默认为0 全部下载
|
allmix: 1 # 主页下合集下载个数设置, 默认为0 全部下载
|
||||||
mix: 5 # 单个合集下作品下载个数设置, 默认为0 全部下载
|
mix: 5 # 单个合集下作品下载个数设置, 默认为0 全部下载
|
||||||
music: 5 # 音乐(原声)下作品下载个数设置, 默认为0 全部下载
|
music: 5 # 音乐(原声)下作品下载个数设置, 默认为0 全部下载
|
||||||
|
|
||||||
# 设置线程数, 默认5个线程
|
# 设置线程数, 默认5个线程
|
||||||
# 可选
|
# 可选
|
||||||
thread: 5
|
thread: 5
|
||||||
|
|
||||||
# cookie 请登录网页抖音后F12查看
|
# cookie 请登录网页抖音后F12查看
|
||||||
# cookies 和 cookie 二选一, 要使用这种形式, 请注释下面的cookie
|
# cookies 和 cookie 二选一, 要使用这种形式, 请注释下面的cookie
|
||||||
# 目前只需要msToken、ttwid、odin_tt、passport_csrf_token、sid_guard
|
# 目前只需要msToken、ttwid、odin_tt、passport_csrf_token、sid_guard
|
||||||
# 可以动态添加, 程序会根据填的键查找,并没有写死, 如果抖音需要更多的cookie自己加上就行了
|
# 可以动态添加, 程序会根据填的键查找,并没有写死, 如果抖音需要更多的cookie自己加上就行了
|
||||||
cookies:
|
cookies:
|
||||||
msToken: xxx
|
msToken: xxx
|
||||||
ttwid: xxx
|
ttwid: xxx
|
||||||
odin_tt: xxx
|
odin_tt: xxx
|
||||||
passport_csrf_token: xxx
|
passport_csrf_token: xxx
|
||||||
sid_guard: xxx
|
sid_guard: xxx
|
||||||
|
|
||||||
# cookie 请登录网页抖音后F12查看
|
# cookie 请登录网页抖音后F12查看
|
||||||
# cookies 和 cookie 二选一, 要使用这种形式, 请注释上面的cookies及包含的所有键值对
|
# cookies 和 cookie 二选一, 要使用这种形式, 请注释上面的cookies及包含的所有键值对
|
||||||
# 设置了这个后上面的cookies选项自动失效, 这个优先级更高
|
# 设置了这个后上面的cookies选项自动失效, 这个优先级更高
|
||||||
# 格式: "name1=value1; name2=value2;" 注意要加冒号
|
# 格式: "name1=value1; name2=value2;" 注意要加冒号
|
||||||
# 冒号中的内容包括不限于以下键值对, 如果抖音需要更多的cookie自己加上就行了
|
# 冒号中的内容包括不限于以下键值对, 如果抖音需要更多的cookie自己加上就行了
|
||||||
#cookie: "msToken=xxx; ttwid=xxx; odin_tt=xxx; passport_csrf_token=xxx; sid_guard=xxx;"
|
#cookie: "msToken=xxx; ttwid=xxx; odin_tt=xxx; passport_csrf_token=xxx; sid_guard=xxx;"
|
||||||
|
|
||||||
|
1264
static/css/style.css
1264
static/css/style.css
File diff suppressed because it is too large
Load Diff
@ -1,229 +1,229 @@
|
|||||||
// 发 post 请求
|
// 发 post 请求
|
||||||
function SendAjax() {
|
function SendAjax() {
|
||||||
var data = {};
|
var data = {};
|
||||||
data = $('#form1').serialize();
|
data = $('#form1').serialize();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: "/douyin",
|
url: "/douyin",
|
||||||
data: data,
|
data: data,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
$("#loading").attr("style", "display:block;");//在请求后台数据之前显示loading图标
|
$("#loading").attr("style", "display:block;");//在请求后台数据之前显示loading图标
|
||||||
$("#download").attr("style", "display:none;");//隐藏 download
|
$("#download").attr("style", "display:none;");//隐藏 download
|
||||||
},
|
},
|
||||||
success: function (result) {
|
success: function (result) {
|
||||||
// console.log(result);//打印服务端返回的数据(调试用)
|
// console.log(result);//打印服务端返回的数据(调试用)
|
||||||
if (result.status_code === 200) {
|
if (result.status_code === 200) {
|
||||||
result = result.data
|
result = result.data
|
||||||
if (result.awemeType === 0) {
|
if (result.awemeType === 0) {
|
||||||
$("#awemeType").html("预览视频");
|
$("#awemeType").html("预览视频");
|
||||||
$("#AwemeOrLive").html("下载视频");
|
$("#AwemeOrLive").html("下载视频");
|
||||||
$("#video").attr("href", result.video.play_addr.url_list);
|
$("#video").attr("href", result.video.play_addr.url_list);
|
||||||
$("#pre_video").attr("src", result.video.play_addr.url_list);
|
$("#pre_video").attr("src", result.video.play_addr.url_list);
|
||||||
$("#video").attr("style", "display:inline;");//显示 video
|
$("#video").attr("style", "display:inline;");//显示 video
|
||||||
}
|
}
|
||||||
if (result.awemeType === 1) {
|
if (result.awemeType === 1) {
|
||||||
$("#awemeType").html("预览图集");
|
$("#awemeType").html("预览图集");
|
||||||
var images = result.images;
|
var images = result.images;
|
||||||
var licontent = ""; // 拼接输入的 li 标签的字符串
|
var licontent = ""; // 拼接输入的 li 标签的字符串
|
||||||
for (var i = 0; i < images.length; i++) {
|
for (var i = 0; i < images.length; i++) {
|
||||||
licontent += "<li><img src= " + images[i].url_list[0] + "></li>"
|
licontent += "<li><img src= " + images[i].url_list[0] + "></li>"
|
||||||
}
|
}
|
||||||
document.getElementById("images").innerHTML = licontent;
|
document.getElementById("images").innerHTML = licontent;
|
||||||
$("#video").attr("style", "display:none;");//隐藏 video
|
$("#video").attr("style", "display:none;");//隐藏 video
|
||||||
}
|
}
|
||||||
if (result.awemeType === 0 || result.awemeType === 1) {
|
if (result.awemeType === 0 || result.awemeType === 1) {
|
||||||
$("#cover").attr("href", result.video.cover_original_scale.url_list[0]);
|
$("#cover").attr("href", result.video.cover_original_scale.url_list[0]);
|
||||||
$("#pre_video").attr("poster", result.video.dynamic_cover.url_list[0]);
|
$("#pre_video").attr("poster", result.video.dynamic_cover.url_list[0]);
|
||||||
$("#music").attr("href", result.music.play_url.url_list[0]);
|
$("#music").attr("href", result.music.play_url.url_list[0]);
|
||||||
|
|
||||||
$("#avatar").attr("src", result.author.avatar.url_list[0]);
|
$("#avatar").attr("src", result.author.avatar.url_list[0]);
|
||||||
$("#avatar").attr("alt", result.author.nickname);
|
$("#avatar").attr("alt", result.author.nickname);
|
||||||
$("#nickname").html(result.author.nickname);
|
$("#nickname").html(result.author.nickname);
|
||||||
$("#desc").html(result.desc);
|
$("#desc").html(result.desc);
|
||||||
|
|
||||||
|
|
||||||
var count = result.statistics.digg_count;
|
var count = result.statistics.digg_count;
|
||||||
var digg_count;
|
var digg_count;
|
||||||
if (count < 1000) {
|
if (count < 1000) {
|
||||||
digg_count = count
|
digg_count = count
|
||||||
} else if (count >= 1000 && count < 10000) {
|
} else if (count >= 1000 && count < 10000) {
|
||||||
digg_count = (count / 1000).toFixed(1) + "K"
|
digg_count = (count / 1000).toFixed(1) + "K"
|
||||||
} else {
|
} else {
|
||||||
digg_count = (count / 10000).toFixed(1) + "W"
|
digg_count = (count / 10000).toFixed(1) + "W"
|
||||||
}
|
}
|
||||||
$("#aweme_digg_count").html(digg_count);
|
$("#aweme_digg_count").html(digg_count);
|
||||||
count = result.statistics.comment_count;
|
count = result.statistics.comment_count;
|
||||||
var comment_count;
|
var comment_count;
|
||||||
if (count < 1000) {
|
if (count < 1000) {
|
||||||
comment_count = count
|
comment_count = count
|
||||||
} else if (count >= 1000 && count < 10000) {
|
} else if (count >= 1000 && count < 10000) {
|
||||||
comment_count = (count / 1000).toFixed(1) + "K"
|
comment_count = (count / 1000).toFixed(1) + "K"
|
||||||
} else {
|
} else {
|
||||||
comment_count = (count / 10000).toFixed(1) + "W"
|
comment_count = (count / 10000).toFixed(1) + "W"
|
||||||
}
|
}
|
||||||
$("#aweme_comment_count").html(comment_count);
|
$("#aweme_comment_count").html(comment_count);
|
||||||
count = result.statistics.collect_count;
|
count = result.statistics.collect_count;
|
||||||
var collect_count;
|
var collect_count;
|
||||||
if (count < 1000) {
|
if (count < 1000) {
|
||||||
collect_count = count
|
collect_count = count
|
||||||
} else if (count >= 1000 && count < 10000) {
|
} else if (count >= 1000 && count < 10000) {
|
||||||
collect_count = (count / 1000).toFixed(1) + "K"
|
collect_count = (count / 1000).toFixed(1) + "K"
|
||||||
} else {
|
} else {
|
||||||
collect_count = (count / 10000).toFixed(1) + "W"
|
collect_count = (count / 10000).toFixed(1) + "W"
|
||||||
}
|
}
|
||||||
$("#aweme_collect_count").html(collect_count);
|
$("#aweme_collect_count").html(collect_count);
|
||||||
count = result.statistics.share_count;
|
count = result.statistics.share_count;
|
||||||
var share_count;
|
var share_count;
|
||||||
if (count < 1000) {
|
if (count < 1000) {
|
||||||
share_count = count
|
share_count = count
|
||||||
} else if (count >= 1000 && count < 10000) {
|
} else if (count >= 1000 && count < 10000) {
|
||||||
share_count = (count / 1000).toFixed(1) + "K"
|
share_count = (count / 1000).toFixed(1) + "K"
|
||||||
} else {
|
} else {
|
||||||
share_count = (count / 10000).toFixed(1) + "W"
|
share_count = (count / 10000).toFixed(1) + "W"
|
||||||
}
|
}
|
||||||
$("#aweme_share_count").html(share_count);
|
$("#aweme_share_count").html(share_count);
|
||||||
|
|
||||||
$("#icons").attr("style", "display:flex;");//显示 icons
|
$("#icons").attr("style", "display:flex;");//显示 icons
|
||||||
$("#icon").attr("style", "display:table-row;");//显示 icon
|
$("#icon").attr("style", "display:table-row;");//显示 icon
|
||||||
$("#music").attr("style", "display:inline;");//显示 music
|
$("#music").attr("style", "display:inline;");//显示 music
|
||||||
|
|
||||||
$("#loading").attr("style", "display:none;");//隐藏 loading
|
$("#loading").attr("style", "display:none;");//隐藏 loading
|
||||||
$("#download").attr("style", "display:block;");//显示 download
|
$("#download").attr("style", "display:block;");//显示 download
|
||||||
// alert("SUCCESS");
|
// alert("SUCCESS");
|
||||||
// 执行弹框
|
// 执行弹框
|
||||||
narnSuccess();
|
narnSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.awemeType === 2) {
|
if (result.awemeType === 2) {
|
||||||
if (result.status === 4) {
|
if (result.status === 4) {
|
||||||
$("#loading").attr("style", "display:none;");//隐藏 loading
|
$("#loading").attr("style", "display:none;");//隐藏 loading
|
||||||
$("#download").attr("style", "display:none;");//隐藏 download
|
$("#download").attr("style", "display:none;");//隐藏 download
|
||||||
// 执行弹框
|
// 执行弹框
|
||||||
narnWarn()
|
narnWarn()
|
||||||
} else {
|
} else {
|
||||||
$("#AwemeOrLive").html("下载直播");
|
$("#AwemeOrLive").html("下载直播");
|
||||||
$("#awemeType").html("预览直播");
|
$("#awemeType").html("预览直播");
|
||||||
$("#video").attr("href", result.flv_pull_url0);
|
$("#video").attr("href", result.flv_pull_url0);
|
||||||
$("#pre_video").attr("src", result.flv_pull_url0);
|
$("#pre_video").attr("src", result.flv_pull_url0);
|
||||||
|
|
||||||
$("#cover").attr("href", result.cover);
|
$("#cover").attr("href", result.cover);
|
||||||
$("#pre_video").attr("poster", result.cover);
|
$("#pre_video").attr("poster", result.cover);
|
||||||
$("#avatar").attr("src", result.avatar);
|
$("#avatar").attr("src", result.avatar);
|
||||||
$("#avatar").attr("alt", result.nickname);
|
$("#avatar").attr("alt", result.nickname);
|
||||||
$("#nickname").html(result.nickname);
|
$("#nickname").html(result.nickname);
|
||||||
$("#desc").html(result.title);
|
$("#desc").html(result.title);
|
||||||
|
|
||||||
$("#video").attr("style", "display:inline;");//显示 video
|
$("#video").attr("style", "display:inline;");//显示 video
|
||||||
$("#icons").attr("style", "display:none;");//隐藏 icons
|
$("#icons").attr("style", "display:none;");//隐藏 icons
|
||||||
$("#icon").attr("style", "display:none;");//隐藏 icon
|
$("#icon").attr("style", "display:none;");//隐藏 icon
|
||||||
$("#music").attr("style", "display:none;");//隐藏 music
|
$("#music").attr("style", "display:none;");//隐藏 music
|
||||||
|
|
||||||
$("#loading").attr("style", "display:none;");//隐藏 loading
|
$("#loading").attr("style", "display:none;");//隐藏 loading
|
||||||
$("#download").attr("style", "display:block;");//显示 download
|
$("#download").attr("style", "display:block;");//显示 download
|
||||||
// alert("SUCCESS");
|
// alert("SUCCESS");
|
||||||
// 执行弹框
|
// 执行弹框
|
||||||
narnSuccess();
|
narnSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$("#loading").attr("style", "display:none;");//隐藏 loading
|
$("#loading").attr("style", "display:none;");//隐藏 loading
|
||||||
$("#download").attr("style", "display:none;");//隐藏 download
|
$("#download").attr("style", "display:none;");//隐藏 download
|
||||||
|
|
||||||
// 执行弹框
|
// 执行弹框
|
||||||
narnFail();
|
narnFail();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
},
|
},
|
||||||
error: function (xhr, type) {
|
error: function (xhr, type) {
|
||||||
$("#loading").attr("style", "display:none;");//隐藏 loading
|
$("#loading").attr("style", "display:none;");//隐藏 loading
|
||||||
$("#download").attr("style", "display:none;");//隐藏 download
|
$("#download").attr("style", "display:none;");//隐藏 download
|
||||||
// alert("异常!");
|
// alert("异常!");
|
||||||
|
|
||||||
// 执行弹框
|
// 执行弹框
|
||||||
narnFail();
|
narnFail();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右上角弹框
|
// 右上角弹框
|
||||||
function narnSuccess() {
|
function narnSuccess() {
|
||||||
naranja().success({
|
naranja().success({
|
||||||
title: '解析成功',
|
title: '解析成功',
|
||||||
text: '请及时下载音视频',
|
text: '请及时下载音视频',
|
||||||
icon: true,
|
icon: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
buttons: []
|
buttons: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function narnFail() {
|
function narnFail() {
|
||||||
naranja().error({
|
naranja().error({
|
||||||
title: '解析失败',
|
title: '解析失败',
|
||||||
text: '直播/视频/图集不存在或接口失效',
|
text: '直播/视频/图集不存在或接口失效',
|
||||||
icon: true,
|
icon: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
buttons: []
|
buttons: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function narnWarn() {
|
function narnWarn() {
|
||||||
naranja().warn({
|
naranja().warn({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
text: '直播未开始',
|
text: '直播未开始',
|
||||||
icon: true,
|
icon: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
buttons: []
|
buttons: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', function () {
|
window.addEventListener('DOMContentLoaded', function () {
|
||||||
document.getElementById('view_aweme').addEventListener('click', function () {
|
document.getElementById('view_aweme').addEventListener('click', function () {
|
||||||
var awemeType = document.getElementById("awemeType").innerText;
|
var awemeType = document.getElementById("awemeType").innerText;
|
||||||
|
|
||||||
if (awemeType === "预览视频") {
|
if (awemeType === "预览视频") {
|
||||||
// 调小音量
|
// 调小音量
|
||||||
var videoElement = document.getElementById("pre_video");
|
var videoElement = document.getElementById("pre_video");
|
||||||
videoElement.volume = 0.6
|
videoElement.volume = 0.6
|
||||||
/*弹出视频播放层*/
|
/*弹出视频播放层*/
|
||||||
$("#show-video").show();
|
$("#show-video").show();
|
||||||
}
|
}
|
||||||
// 图片查看器
|
// 图片查看器
|
||||||
if (awemeType === "预览图集") {
|
if (awemeType === "预览图集") {
|
||||||
|
|
||||||
var viewer = new Viewer(document.getElementById('images'), {
|
var viewer = new Viewer(document.getElementById('images'), {
|
||||||
hidden: function () {
|
hidden: function () {
|
||||||
viewer.destroy();
|
viewer.destroy();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// image.click();
|
// image.click();
|
||||||
viewer.show();
|
viewer.show();
|
||||||
}
|
}
|
||||||
// 预览直播
|
// 预览直播
|
||||||
if (awemeType === "预览直播") {
|
if (awemeType === "预览直播") {
|
||||||
if (flvjs.isSupported()) {//检查flvjs能否正常使用
|
if (flvjs.isSupported()) {//检查flvjs能否正常使用
|
||||||
var videoElement = document.getElementById('pre_video');//使用id选择器找到第二步设置的dom元素
|
var videoElement = document.getElementById('pre_video');//使用id选择器找到第二步设置的dom元素
|
||||||
var flvPlayer = flvjs.createPlayer({//创建一个新的flv播放器对象
|
var flvPlayer = flvjs.createPlayer({//创建一个新的flv播放器对象
|
||||||
type: 'flv',//类型flv
|
type: 'flv',//类型flv
|
||||||
url: $("#video").attr("href")//flv文件地址
|
url: $("#video").attr("href")//flv文件地址
|
||||||
});
|
});
|
||||||
flvPlayer.attachMediaElement(videoElement);//将flv视频装载进video元素内
|
flvPlayer.attachMediaElement(videoElement);//将flv视频装载进video元素内
|
||||||
flvPlayer.load();//载入视频
|
flvPlayer.load();//载入视频
|
||||||
flvPlayer.play();//播放视频,如果不想要自动播放,去掉本行
|
flvPlayer.play();//播放视频,如果不想要自动播放,去掉本行
|
||||||
|
|
||||||
/*弹出视频播放层*/
|
/*弹出视频播放层*/
|
||||||
$("#show-video").show();
|
$("#show-video").show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
/*关闭视频播放层*/
|
/*关闭视频播放层*/
|
||||||
$(".video-close").click(function () {
|
$(".video-close").click(function () {
|
||||||
var videoElement = document.getElementById("pre_video");
|
var videoElement = document.getElementById("pre_video");
|
||||||
videoElement.pause()
|
videoElement.pause()
|
||||||
$("#show-video").hide();
|
$("#show-video").hide();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -1,172 +1,175 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zhxx">
|
<html lang="zhxx">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>抖音去水印工具</title>
|
<title>抖音去水印工具</title>
|
||||||
<!-- Meta tag Keywords -->
|
<!-- Meta tag Keywords -->
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<meta name="keywords" content="抖音去水印工具"/>
|
<meta name="keywords" content="抖音去水印工具"/>
|
||||||
<meta name="referrer" content="never">
|
<meta name="referrer" content="never">
|
||||||
<script>
|
<script>
|
||||||
addEventListener("load", function () {
|
addEventListener("load", function () {
|
||||||
setTimeout(hideURLbar, 0);
|
setTimeout(hideURLbar, 0);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
function hideURLbar() {
|
function hideURLbar() {
|
||||||
window.scrollTo(0, 1);
|
window.scrollTo(0, 1);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<!-- //Meta tag Keywords -->
|
<!-- //Meta tag Keywords -->
|
||||||
<!-- /Favicons -->
|
<!-- /Favicons -->
|
||||||
<link href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/img/favicon.ico" rel="shortcut icon" type="image/x-icon">
|
<link href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/img/favicon.ico" rel="shortcut icon"
|
||||||
<!-- //Favicons -->
|
type="image/x-icon">
|
||||||
<!--/Style-CSS -->
|
<!-- //Favicons -->
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/style.css" type="text/css" media="all"/>
|
<!--/Style-CSS -->
|
||||||
<!--//Style-CSS -->
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/style.css" type="text/css"
|
||||||
<!-- font-awesome-icons -->
|
media="all"/>
|
||||||
<link href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/font-awesome.css" rel="stylesheet">
|
<!--//Style-CSS -->
|
||||||
<!-- //font-awesome-icons -->
|
<!-- font-awesome-icons -->
|
||||||
<!-- naranja 右下角弹框提示 https://github.com/e1016/naranja-->
|
<link href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/font-awesome.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/naranja.min.css" type="text/css"/>
|
<!-- //font-awesome-icons -->
|
||||||
<!-- //naranja -->
|
<!-- naranja 右下角弹框提示 https://github.com/e1016/naranja-->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/naranja.min.css" type="text/css"/>
|
||||||
<!-- viewerjs 图片查看器 https://github.com/fengyuanchen/viewerjs-->
|
<!-- //naranja -->
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/viewer.min.css" type="text/css"/>
|
|
||||||
<!-- //viewerjs -->
|
<!-- viewerjs 图片查看器 https://github.com/fengyuanchen/viewerjs-->
|
||||||
</head>
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/css/viewer.min.css" type="text/css"/>
|
||||||
|
<!-- //viewerjs -->
|
||||||
<body>
|
</head>
|
||||||
|
|
||||||
<div class="error-61-mian">
|
<body>
|
||||||
<div class="wrapper">
|
|
||||||
<div class="errors-16-top">
|
<div class="error-61-mian">
|
||||||
|
<div class="wrapper">
|
||||||
<p style="color:#00c4b6;font-size:32px;">抖音去水印工具</p>
|
<div class="errors-16-top">
|
||||||
<br>
|
|
||||||
<p>支持视频/图集/直播解析,粘贴视频/图集/直播分享链接时无需删除文案,但如果链接正确但解析失败请删掉文案后重试 https://v.douyin.com/kcvMpuN/</p>
|
<p style="color:#00c4b6;font-size:32px;">抖音去水印工具</p>
|
||||||
{# <p>2.支持直播解析,需要网页版直播链接 https://live.douyin.com/343806013144</p>#}
|
<br>
|
||||||
<p>关于抖音批量下载与去水印工具的更多实现细节请点击: <a href="https://www.imgyh.com/archives/41.html" target="_blank" style="color:#00c4b6;">抖音批量下载与去水印工具</a></p>
|
<p>支持视频/图集/直播解析,粘贴视频/图集/直播分享链接时无需删除文案,但如果链接正确但解析失败请删掉文案后重试 https://v.douyin.com/kcvMpuN/</p>
|
||||||
<form id="form1" onsubmit="return false" action="#" method="post" class="d-flex error-page-form">
|
{# <p>2.支持直播解析,需要网页版直播链接 https://live.douyin.com/343806013144</p>#}
|
||||||
{# 以前需要手动选择 图片 或者 视频 现在加了自动判断#}
|
<p>关于抖音批量下载与去水印工具的更多实现细节请点击: <a href="https://www.imgyh.com/archives/41.html" target="_blank"
|
||||||
{# <div class="select">#}
|
style="color:#00c4b6;">抖音批量下载与去水印工具</a></p>
|
||||||
{# <select name="awemeType" required="required">#}
|
<form id="form1" onsubmit="return false" action="#" method="post" class="d-flex error-page-form">
|
||||||
{# <option value="0" selected="selected">视频</option>#}
|
{# 以前需要手动选择 图片 或者 视频 现在加了自动判断#}
|
||||||
{# <option value="1">图集</option>#}
|
{# <div class="select">#}
|
||||||
{# </select>#}
|
{# <select name="awemeType" required="required">#}
|
||||||
{# </div>#}
|
{# <option value="0" selected="selected">视频</option>#}
|
||||||
|
{# <option value="1">图集</option>#}
|
||||||
<input type="text" placeholder="粘贴视频/图集/直播分享地址" name="share_link" required="required">
|
{# </select>#}
|
||||||
<button type="reset" onclick="SendAjax()">解析</button>
|
{# </div>#}
|
||||||
</form>
|
|
||||||
{# <div class="social-coming-icons">#}
|
<input type="text" placeholder="粘贴视频/图集/直播分享地址" name="share_link" required="required">
|
||||||
{# <a href="#" title="Facebook" class="footer-fb"><span class="fa fa-facebook"#}
|
<button type="reset" onclick="SendAjax()">解析</button>
|
||||||
{# aria-hidden="true"></span></a>#}
|
</form>
|
||||||
{# <a href="#" title="Twitter" class="footer-tw"><span class="fa fa-twitter"#}
|
{# <div class="social-coming-icons">#}
|
||||||
{# aria-hidden="true"></span></a>#}
|
{# <a href="#" title="Facebook" class="footer-fb"><span class="fa fa-facebook"#}
|
||||||
{# <a href="#" title="Google Plus" class="footer-gg"><span class="fa fa-google-plus"#}
|
{# aria-hidden="true"></span></a>#}
|
||||||
{# aria-hidden="true"></span></a>#}
|
{# <a href="#" title="Twitter" class="footer-tw"><span class="fa fa-twitter"#}
|
||||||
{# <a href="#" title="Linkedin" class="footer-lin"><span class="fa fa-linkedin"#}
|
{# aria-hidden="true"></span></a>#}
|
||||||
{# aria-hidden="true"></span></a>#}
|
{# <a href="#" title="Google Plus" class="footer-gg"><span class="fa fa-google-plus"#}
|
||||||
{# </div>#}
|
{# aria-hidden="true"></span></a>#}
|
||||||
|
{# <a href="#" title="Linkedin" class="footer-lin"><span class="fa fa-linkedin"#}
|
||||||
</div>
|
{# aria-hidden="true"></span></a>#}
|
||||||
<div class="errors-16-mid">
|
{# </div>#}
|
||||||
<div class="loading" id="loading">
|
|
||||||
<div class="shape shape-1"></div>
|
</div>
|
||||||
<div class="shape shape-2"></div>
|
<div class="errors-16-mid">
|
||||||
<div class="shape shape-3"></div>
|
<div class="loading" id="loading">
|
||||||
<div class="shape shape-4"></div>
|
<div class="shape shape-1"></div>
|
||||||
</div>
|
<div class="shape shape-2"></div>
|
||||||
|
<div class="shape shape-3"></div>
|
||||||
<div id="download" style="display: none;">
|
<div class="shape shape-4"></div>
|
||||||
<div class="photo">
|
</div>
|
||||||
<img id="avatar" src="#" class="avatar" alt="avatar">
|
|
||||||
<br>
|
<div id="download" style="display: none;">
|
||||||
<p id="nickname" class="nickname"></p>
|
<div class="photo">
|
||||||
</div>
|
<img id="avatar" src="#" class="avatar" alt="avatar">
|
||||||
<div class="info">
|
<br>
|
||||||
<div id="icons" class="icons">
|
<p id="nickname" class="nickname"></p>
|
||||||
<div id="icon" class="icon">
|
</div>
|
||||||
<i class="fa fa-heart" style="color:#fd325c;" aria-hidden="true"></i>
|
<div class="info">
|
||||||
<p id="aweme_digg_count"></p>
|
<div id="icons" class="icons">
|
||||||
</div>
|
<div id="icon" class="icon">
|
||||||
<div id="icon" class="icon">
|
<i class="fa fa-heart" style="color:#fd325c;" aria-hidden="true"></i>
|
||||||
<i class="fa fa-comment" style="color:#efeeec;" aria-hidden="true"></i>
|
<p id="aweme_digg_count"></p>
|
||||||
<p id="aweme_comment_count"></p>
|
</div>
|
||||||
</div>
|
<div id="icon" class="icon">
|
||||||
<div id="icon" class="icon">
|
<i class="fa fa-comment" style="color:#efeeec;" aria-hidden="true"></i>
|
||||||
<i class="fa fa-star" style="color:#fcb505;" aria-hidden="true"></i>
|
<p id="aweme_comment_count"></p>
|
||||||
<p id="aweme_collect_count"></p>
|
</div>
|
||||||
</div>
|
<div id="icon" class="icon">
|
||||||
<div id="icon" class="icon">
|
<i class="fa fa-star" style="color:#fcb505;" aria-hidden="true"></i>
|
||||||
<i class="fa fa-share" style="color:#e7e8e6;" aria-hidden="true"></i>
|
<p id="aweme_collect_count"></p>
|
||||||
<p id="aweme_share_count"></p>
|
</div>
|
||||||
</div>
|
<div id="icon" class="icon">
|
||||||
</div>
|
<i class="fa fa-share" style="color:#e7e8e6;" aria-hidden="true"></i>
|
||||||
<br>
|
<p id="aweme_share_count"></p>
|
||||||
<p id="desc"></p>
|
</div>
|
||||||
<br>
|
</div>
|
||||||
<a id="cover" href="#" target="_blank">
|
<br>
|
||||||
<button type="button" class="btn btn1 ">
|
<p id="desc"></p>
|
||||||
<span>下载封面</span>
|
<br>
|
||||||
</button>
|
<a id="cover" href="#" target="_blank">
|
||||||
</a>
|
<button type="button" class="btn btn1 ">
|
||||||
<a id="video" href="#" target="_blank">
|
<span>下载封面</span>
|
||||||
<button type="button" class="btn btn1">
|
</button>
|
||||||
<span id="AwemeOrLive"></span>
|
</a>
|
||||||
</button>
|
<a id="video" href="#" target="_blank">
|
||||||
</a>
|
<button type="button" class="btn btn1">
|
||||||
<a id="music" href="#" target="_blank">
|
<span id="AwemeOrLive"></span>
|
||||||
<button type="button" class="btn btn1">
|
</button>
|
||||||
<span>下载音乐</span>
|
</a>
|
||||||
</button>
|
<a id="music" href="#" target="_blank">
|
||||||
</a>
|
<button type="button" class="btn btn1">
|
||||||
<button id="view_aweme" type="button" class="btn btn1">
|
<span>下载音乐</span>
|
||||||
<span id="awemeType"></span>
|
</button>
|
||||||
</button>
|
</a>
|
||||||
</div>
|
<button id="view_aweme" type="button" class="btn btn1">
|
||||||
</div>
|
<span id="awemeType"></span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
<div class="copy-right">
|
</div>
|
||||||
<p>Copyright © 2021-2023.我的博客 <a href="https://www.imgyh.com/" target="_blank">GYH's Blog</a> && 项目地址 <a
|
|
||||||
href="https://github.com/imgyh/douyin" target="_blank">Github</a>
|
</div>
|
||||||
All rights reserved.</p>
|
<div class="copy-right">
|
||||||
</div>
|
<p>Copyright © 2021-2023.我的博客 <a href="https://www.imgyh.com/" target="_blank">GYH's Blog</a> && 项目地址 <a
|
||||||
</div>
|
href="https://github.com/imgyh/douyin" target="_blank">Github</a>
|
||||||
|
All rights reserved.</p>
|
||||||
{# 视频预览效果 https://blog.csdn.net/qq_45140694/article/details/115266928 #}
|
</div>
|
||||||
<div id="show-video">
|
</div>
|
||||||
<a class="video-close">
|
|
||||||
<span>
|
{# 视频预览效果 https://blog.csdn.net/qq_45140694/article/details/115266928 #}
|
||||||
<svg t="1614676844098" class="icon" viewBox="0 0 1024 1024"
|
<div id="show-video">
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="2082"
|
<a class="video-close">
|
||||||
width="30" height="30">
|
<span>
|
||||||
<path d="M591.506286 511.853714l417.133714-416.914285a54.601143 54.601143 0 0 0 0-76.8l-2.267429-2.267429a54.601143 54.601143 0 0 0-76.8 0L512.438857 433.481143 95.305143 15.798857a54.601143 54.601143 0 0 0-76.8 0L16.237714 18.066286a53.577143 53.577143 0 0 0 0 76.8l417.097143 416.987428L16.201143 929.097143a54.601143 54.601143 0 0 0 0 76.8l2.267428 2.267428a54.601143 54.601143 0 0 0 76.8 0l417.170286-417.060571 417.097143 417.097143a54.601143 54.601143 0 0 0 76.8 0l2.267429-2.267429a54.601143 54.601143 0 0 0 0-76.8z"
|
<svg t="1614676844098" class="icon" viewBox="0 0 1024 1024"
|
||||||
p-id="2083" fill="#e6e6e6"></path>
|
xmlns="http://www.w3.org/2000/svg" p-id="2082"
|
||||||
</svg>
|
width="30" height="30">
|
||||||
</span>
|
<path d="M591.506286 511.853714l417.133714-416.914285a54.601143 54.601143 0 0 0 0-76.8l-2.267429-2.267429a54.601143 54.601143 0 0 0-76.8 0L512.438857 433.481143 95.305143 15.798857a54.601143 54.601143 0 0 0-76.8 0L16.237714 18.066286a53.577143 53.577143 0 0 0 0 76.8l417.097143 416.987428L16.201143 929.097143a54.601143 54.601143 0 0 0 0 76.8l2.267428 2.267428a54.601143 54.601143 0 0 0 76.8 0l417.170286-417.060571 417.097143 417.097143a54.601143 54.601143 0 0 0 76.8 0l2.267429-2.267429a54.601143 54.601143 0 0 0 0-76.8z"
|
||||||
</a>
|
p-id="2083" fill="#e6e6e6"></path>
|
||||||
{# https://blog.csdn.net/seeeeeeeeeee/article/details/119981594 #}
|
</svg>
|
||||||
<video src="" id="pre_video" controls="controls" poster=""></video>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
|
{# https://blog.csdn.net/seeeeeeeeeee/article/details/119981594 #}
|
||||||
<div style="display: none">
|
<video src="" id="pre_video" controls="controls" poster=""></video>
|
||||||
<ul id="images">
|
</div>
|
||||||
{# <li><img src="picture-1.jpg" alt="Picture 1"></li>#}
|
|
||||||
{# <li><img src="picture-2.jpg" alt="Picture 2"></li>#}
|
<div style="display: none">
|
||||||
{# <li><img src="picture-3.jpg" alt="Picture 3"></li>#}
|
<ul id="images">
|
||||||
</ul>
|
{# <li><img src="picture-1.jpg" alt="Picture 1"></li>#}
|
||||||
</div>
|
{# <li><img src="picture-2.jpg" alt="Picture 2"></li>#}
|
||||||
|
{# <li><img src="picture-3.jpg" alt="Picture 3"></li>#}
|
||||||
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/jquery-1.8.2.min.js" type="text/javascript"></script>
|
</ul>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/naranja.min.js" type="text/javascript"></script>
|
</div>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/viewer.min.js" type="text/javascript"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/custom.js" type="text/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/jquery-1.8.2.min.js" type="text/javascript"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/flv.min.js" type="text/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/naranja.min.js" type="text/javascript"></script>
|
||||||
</body>
|
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/viewer.min.js" type="text/javascript"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/custom.js" type="text/javascript"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/imgyh/tiktok/static/js/flv.min.js" type="text/javascript"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
x
Reference in New Issue
Block a user