Skip to content

Commit

Permalink
修复 TikTok 平台作品下载功能
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeanAmier committed Mar 17, 2024
1 parent 36d1c07 commit f61afa7
Show file tree
Hide file tree
Showing 16 changed files with 193 additions and 92 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
<br>
<p>🔥 <b>TikTok 主页/视频/图集/原声;抖音主页/视频/图集/收藏/直播/原声/合集/评论/账号/搜索/热榜数据采集工具:</b>完全开源,基于 Requests 模块实现的免费工具;批量下载抖音账号发布、喜欢、收藏作品;批量下载 TikTok 账号主页作品;下载抖音链接或 TikTok 链接作品;获取抖音直播推流地址;下载抖音直播视频;采集抖音作品评论数据;批量下载抖音合集作品;采集抖音账号详细数据;采集抖音用户 / 作品 / 直播搜索结果;采集抖音热榜数据。</p>
<p>⭐ Windows 10 及以上用户可前往 <a href="https://github.com/JoeanAmier/TikTokDownloader/releases/latest">Releases</a> 下载已编译的 exe 程序,开箱即用!</p>
<p>❤️ 作者仅在 GitHub 发布 TikTokDownloader,未与任何个人或网站合作发布,项目没有任何收费计划,谨防上当受骗!</p>
<hr>

# 📝 项目功能\(Function\)
Expand Down Expand Up @@ -87,7 +86,7 @@
* 🟡 TikTokDownloader 开发计划及进度可前往 [Projects](https://github.com/users/JoeanAmier/projects/2) 查阅
* 🔴 请注意,最新源码可能存在一些不稳定的 Bug
* 🔴 如果在使用过程中发现程序 Bug,请及时告知作者修复
* 🔴 TikTok 平台作品下载功能已失效,待修复
* 🔴 TikTok 平台作品下载功能失效,已修复
* 🔴 夜晚无法下载高分辨率视频,疑似抖音服务端限制

# 📋 项目说明\(Instructions\)
Expand Down Expand Up @@ -210,7 +209,11 @@
<li>微信公众号: Downloader Tools</li>
<li>QQ 群聊(使用交流): <a href="https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/QQ%E7%BE%A4%E8%81%8A%E4%BA%8C%E7%BB%B4%E7%A0%81.png">扫码加入群聊</a></li>
</ul>
<p><b>如果您对小红书感兴趣,可以了解一下我的另一个开源项目 <a href="https://github.com/JoeanAmier/XHS-Downloader">XHS-Downloader</a></b></p>
<p>✨ <b>作者的其他开源项目:</b></p>
<ul>
<li><b>XHS-Downloader(小红书)</b>:<a href="https://github.com/JoeanAmier/XHS-Downloader">https://github.com/JoeanAmier/XHS-Downloader</a></li>
<li><b>KS-Downloader(快手)</b>:<a href="https://github.com/JoeanAmier/KS-Downloader">https://github.com/JoeanAmier/KS-Downloader</a></li>
</ul>

# ♥️ 支持项目\(Support\)

Expand Down
10 changes: 5 additions & 5 deletions docs/TikTokDownloader文档.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ https://www.douyin.com/note/123456789
"latest": ""
}
],
"accounts_urls_tiktok": "参数设置规则同上",
"accounts_urls_tiktok": "参数规则与 accounts_urls 一致",
"mix_urls": [
{
"mark": "",
Expand All @@ -389,12 +389,12 @@ https://www.douyin.com/note/123456789
"url": "合集链接或者作品链接"
}
],
"mix_urls_tiktok": "参数设置规则同上",
"mix_urls_tiktok": "参数规则与 mix_urls 一致",
"owner_url": {
"mark": "已登录 Cookie 的账号标识,可以设置为空字符串(可选)",
"url": "已登录 Cookie 的账号主页链接(可选)"
},
"owner_url_tiktok": "参数设置规则同上",
"owner_url_tiktok": "参数规则与 owner_url 一致",
"root": "C:\\TikTokDownloader",
"folder_name": "SOLO",
"name_format": "create_time uid id",
Expand All @@ -408,11 +408,11 @@ https://www.douyin.com/note/123456789
"passport_csrf_token_default": "demo",
"odin_tt": "demo"
},
"cookie_tiktok": "参数设置规则同上",
"cookie_tiktok": "参数规则与 cookie 一致",
"dynamic_cover": false,
"original_cover": false,
"proxies": "http://127.0.0.1:9999",
"proxies_tiktok": "参数设置规则同上",
"proxies_tiktok": "参数规则与 proxies 一致",
"download": true,
"max_size": 104857600,
"chunk": 10485760,
Expand Down
2 changes: 1 addition & 1 deletion src/DataAcquirer.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def summary_works(self):

class Works(Acquirer):
item_api = "https://www.douyin.com/aweme/v1/web/aweme/detail/"
item_api_tiktok = "https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/"
item_api_tiktok = "https://api22-normal-c-useast2a.tiktokv.com/aweme/v1/feed/"

def __init__(self, params: Parameter, item_id: str, tiktok: bool,
cookie: str = None, ):
Expand Down
27 changes: 21 additions & 6 deletions src/application/TikTokDownloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
from src.encrypt import XBogus
from src.manager import DownloadRecorder
from src.module import Cookie
from src.module import CookieTikTok
from src.module import Register
from src.record import BaseLogger
from src.record import LoggerManager
Expand Down Expand Up @@ -75,6 +74,10 @@ def inner(self, *args, **kwargs):
class TikTokDownloader:
REDUCED = (1, 1, 1, 1, 0, 1, 0, 0, 1, 1) # 禁用项目部分功能
# REDUCED = False # 启用项目全部功能
PLATFORM = {
"1": "cookie",
"2": "cookie_tiktok",
}

NAME = PROJECT_NAME
WIDTH = 50
Expand Down Expand Up @@ -107,7 +110,6 @@ def __init__(self, **kwargs):
self.x_bogus = XBogus()
self.settings = Settings(PROJECT_ROOT, self.console)
self.cookie = Cookie(self.settings, self.console)
self.cookie_tiktok = CookieTikTok(self.settings, self.console)
self.parameter = None
self.running = True
self.default_mode = None
Expand Down Expand Up @@ -286,11 +288,13 @@ def write_cookie(self):
self.console.print(
"Cookie 获取教程:https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E8%8E%B7%E5%8F%96%E6"
"%95%99%E7%A8%8B.md")
self.cookie.run()
self.check_settings()
self.parameter.update_cookie()
if (p := self.__select_platform()) in self.PLATFORM:
self.cookie.run(self.PLATFORM[p])
self.check_settings()
self.parameter.update_cookie()

def auto_cookie(self):
self.console.print("该功能仅支持抖音平台,未来可能会移除!")
if cookie := Register(
self.settings,
self.console,
Expand Down Expand Up @@ -361,4 +365,15 @@ def close(self):
self.parameter.logger.info("程序结束运行")

def browser_cookie(self):
Browser(self.parameter, self.cookie).run()
if (p := self.__select_platform()) in self.PLATFORM:
Browser(self.parameter, self.cookie).run(p == "2")

def __select_platform(self) -> str:
return choose(
"请选择平台:",
(
"抖音平台",
"TikTok 平台",
),
self.console,
)
125 changes: 93 additions & 32 deletions src/config/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,16 @@ def __init__(
self.headers = {
"User-Agent": USERAGENT,
}
self.headers_tiktok = {
"User-Agent": USERAGENT,
}
self.logger = logger(main_path, console)
self.logger.run()
self.xb = xb
self.console = console
self.cookie_cache = None
self.cookie = self.__check_cookie(cookie)
self.cookie_tiktok_cache = None
self.cookie_tiktok = None
self.cookie, self.cookie_cache = self.__check_cookie(cookie)
self.cookie_tiktok, self.cookie_tiktok_cache = self.__check_cookie_tiktok(
cookie_tiktok)
self.root = self.__check_root(root)
self.folder_name = self.__check_folder_name(folder_name)
self.name_format = self.__check_name_format(name_format)
Expand All @@ -165,19 +167,23 @@ def __init__(
self.storage_format = self.__check_storage_format(storage_format)
self.dynamic_cover = self.__check_bool(dynamic_cover)
self.original_cover = self.__check_bool(original_cover)
self.timeout = self.__check_timeout(timeout)
self.proxies = self.__check_proxies(proxies)
self.proxies_tiktok = self.__check_proxies(proxies_tiktok, True)
self.proxies_tiktok = self.__check_proxies_tiktok(proxies_tiktok)
self.download = self.__check_bool(download)
self.max_size = self.__check_max_size(max_size)
self.chunk = self.__check_chunk(chunk)
self.max_retry = self.__check_max_retry(max_retry)
self.max_pages = self.__check_max_pages(max_pages)
self.blacklist = blacklist
self.timeout = self.__check_timeout(timeout)
self.accounts_urls: SimpleNamespace = Extractor.generate_data_object(
self.accounts_urls: list[SimpleNamespace] = Extractor.generate_data_object(
accounts_urls)
self.mix_urls: SimpleNamespace = Extractor.generate_data_object(
self.accounts_urls_tiktok: list[SimpleNamespace] = Extractor.generate_data_object(
accounts_urls_tiktok)
self.mix_urls: list[SimpleNamespace] = Extractor.generate_data_object(
mix_urls)
self.mix_urls_tiktok: list[SimpleNamespace] = Extractor.generate_data_object(
mix_urls_tiktok)
self.owner_url: SimpleNamespace = Extractor.generate_data_object(
owner_url)
self.__reduced = reduced
Expand All @@ -188,6 +194,9 @@ def __init__(
"accounts_urls": None,
"mix_urls": None,
"owner_url": None,
"accounts_urls_tiktok": None,
"mix_urls_tiktok": None,
"owner_url_tiktok": None,
"root": self.__check_root,
"folder_name": self.__check_folder_name,
"name_format": self.__check_name_format,
Expand All @@ -199,6 +208,7 @@ def __init__(
"dynamic_cover": self.__check_bool,
"original_cover": self.__check_bool,
"proxies": self.__check_proxies,
"proxies_tiktok": self.__check_proxies_tiktok,
"download": self.__check_bool,
"max_size": self.__check_max_size,
"chunk": self.__check_chunk,
Expand All @@ -212,18 +222,36 @@ def __init__(
def __check_bool(value: bool, default=False) -> bool:
return value if isinstance(value, bool) else default

def __check_cookie(self, cookie: dict | str) -> dict:
def __check_cookie_tiktok(self, cookie: dict | str, ) -> [dict, str]:
return self.__check_cookie(cookie, name="cookie_tiktok")

def __check_cookie(self, cookie: dict | str, name="cookie") -> [dict, str]:
if isinstance(cookie, dict):
return cookie
return cookie, ""
elif isinstance(cookie, str):
self.cookie_cache = cookie
return {}, cookie
else:
self.logger.warning("Cookie 参数格式错误")
return {}
self.logger.warning(f"{name} 参数格式错误")
return {}, ""

def __get_cookie(self, cookie: dict | str, ):
return self.__check_cookie(cookie)[0]

def __get_cookie_cache(self, cookie: dict | str, ):
return self.__check_cookie(cookie)[1]

def __get_cookie_tiktok(self, cookie: dict | str, ):
return self.__check_cookie_tiktok(cookie)[0]

def __get_cookie_tiktok_cache(self, cookie: dict | str, ):
return self.__check_cookie_tiktok(cookie)[1]

@staticmethod
def __add_cookie(cookie: dict | str) -> None | str:
parameters = (MsToken.get_real_ms_token(), TtWid.get_tt_wid(),)
def __add_cookie(cookie: dict | str, tiktok=False) -> None | str:
if tiktok:
parameters = ()
else:
parameters = (MsToken.get_real_ms_token(), TtWid.get_tt_wid(),)
if isinstance(cookie, dict):
for i in parameters:
if isinstance(i, dict):
Expand Down Expand Up @@ -289,7 +317,13 @@ def __check_split(self, split: str) -> str:
self.logger.info(f"split 参数已设置为 {split}", False)
return split

def __check_proxies(self, proxies: str, tiktok=False) -> dict:
def __check_proxies_tiktok(self, proxies: str) -> dict:
return self.__check_proxies(proxies, "https://www.google.com/")

def __check_proxies(
self,
proxies: str,
url="https://www.baidu.com/") -> dict:
if isinstance(proxies, str) and proxies:
proxies_dict = {
"http": proxies,
Expand All @@ -298,9 +332,9 @@ def __check_proxies(self, proxies: str, tiktok=False) -> dict:
}
try:
response = get(
"https://www.google.com/" if tiktok else "https://www.baidu.com/",
url,
proxies=proxies_dict,
timeout=10)
timeout=self.timeout)
if response.status_code == 200:
self.logger.info(f"代理 {proxies} 测试成功")
return proxies_dict
Expand Down Expand Up @@ -376,11 +410,28 @@ def __check_default_mode(self, default_mode: str) -> list:

def update_cookie(self) -> None:
# self.console.print("Update Cookie")
if self.cookie:
self.__add_cookie(self.cookie)
self.headers["Cookie"] = cookie_dict_to_str(self.cookie)
elif self.cookie_cache:
self.headers["Cookie"] = self.__add_cookie(self.cookie_cache)
self.__update_cookie(
self.headers,
self.cookie,
self.cookie_cache,
False)
self.__update_cookie(
self.headers_tiktok,
self.cookie_tiktok,
self.cookie_tiktok_cache,
True, )

def __update_cookie(
self,
headers: dict,
cookie: dict,
cache: str,
tiktok=False) -> None:
if cookie:
self.__add_cookie(cookie, tiktok, )
headers["Cookie"] = cookie_dict_to_str(cookie)
elif cache:
headers["Cookie"] = self.__add_cookie(cache, tiktok, )

@staticmethod
def __generate_ffmpeg_object(ffmpeg_path: str) -> FFMPEG:
Expand All @@ -389,7 +440,9 @@ def __generate_ffmpeg_object(ffmpeg_path: str) -> FFMPEG:
def get_settings_data(self) -> dict:
return {
"accounts_urls": [vars(i) for i in self.accounts_urls],
"accounts_urls_tiktok": [vars(i) for i in self.accounts_urls_tiktok],
"mix_urls": [vars(i) for i in self.mix_urls],
"mix_urls_tiktok": [vars(i) for i in self.mix_urls_tiktok],
"owner_url": vars(self.owner_url),
"root": str(self.root.resolve()),
"folder_name": self.folder_name,
Expand All @@ -400,9 +453,11 @@ def get_settings_data(self) -> dict:
"music": self.music,
"storage_format": self.storage_format,
"cookie": self.cookie_cache or self.cookie,
"cookie_tiktok": self.cookie_tiktok_cache or self.cookie_tiktok,
"dynamic_cover": self.dynamic_cover,
"original_cover": self.original_cover,
"proxies": self.proxies["https"] or "",
"proxies_tiktok": self.proxies_tiktok["https"] or "",
"download": self.download,
"max_size": self.max_size,
"chunk": self.chunk,
Expand All @@ -413,18 +468,24 @@ def get_settings_data(self) -> dict:
}

def update_settings_data(self, data: dict, ) -> dict:
keys = list(self.check_rules.keys())[6:]
for key, value in data.items():
if key in list(self.check_rules.keys())[3:]:
if key in keys:
# print(key, hasattr(self, key)) # 调试使用
setattr(self, key, self.check_rules[key](value))
if c := data.get("cookie"):
setattr(
self,
"cookie",
self.cookie_object.extract(
c,
False))
self.update_cookie()
self.__update_cookie_data(data)
self.settings.update(data := self.get_settings_data())
# print(data) # 调试使用
return data

def __update_cookie_data(self, data: dict) -> None:
for i in ("cookie", "cookie_tiktok"):
if c := data.get(i):
setattr(
self,
i,
self.cookie_object.extract(
c,
False,
key=i))
self.update_cookie()

0 comments on commit f61afa7

Please sign in to comment.