Skip to content

Commit

Permalink
发布 5.2 版本
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeanAmier committed Dec 23, 2023
1 parent c99a303 commit 4524ce6
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 127 deletions.
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
* 🟡 未来可能新增账号新作品监测功能
* 🟡 未来可能新增合集新作品监测功能
* 🟡 未来可能新增直播开播监测功能
* 🟡 未来可能新增调用 API 下载作品文件功能
* 🟡 未来可能新增获取账号关注列表功能
* 🟡 未来可能新增获取账号收藏合集列表功能
* 🟡 未来可能优化 TikTok 平台批量下载功能
Expand All @@ -110,6 +111,7 @@ TikTokDownloader
│ ├─ DataAcquirer.py // 接口数据获取模块
│ ├─ DataExtractor.py // 数据提取储存模块
│ ├─ DataDownloader.py // 作品文件下载模块
│ ├─ Extender.py // 二次开发接口模块
│ ├─ FileManager.py // 作品文件管理模块
│ ├─ Parameter.py // 加密参数生成模块
│ ├─ Recorder.py // 日志及数据记录模块
Expand Down Expand Up @@ -140,11 +142,13 @@ TikTokDownloader
<ol><b>通过源码运行</b>
<li>安装不低于 <code>3.12</code> 版本的 <a href="https://www.python.org/">Python</a> 解释器</li>
<li>下载最新的源码或 <a href="https://github.com/JoeanAmier/TikTokDownloader/releases/latest">Releases</a> 发布的源码至本地</li>
<li>运行 <code>pip install -r requirements.txt</code> 命令安装程序所需模块</li>
<li>运行 main.py</li>
<li>运行 <code>python -m venv venv</code> 命令创建虚拟环境(可选)</li>
<li>运行 <code>.\venv\Scripts\activate.ps1</code> 或者 <code>venv\Scripts\activate</code> 命令激活虚拟环境(可选)</li>
<li>运行 <code>pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt</code> 命令安装程序所需模块</li>
<li>运行 <code>python .\main.py</code> 或者 <code>python main.py</code> 命令启动 TikTokDownloader</li>
</ol>
</li>
<li>查看屏幕输出的 TikTokDownloader 免责声明,根据提示输入内容</li>
<li>阅读 TikTokDownloader 的免责声明,根据提示输入内容</li>
<li>将 Cookie 信息写入配置文件
<ol><b>手动复制粘贴(推荐)</b>
<li>参考 <a href="https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E6%95%99%E7%A8%8B.md">Cookie 提取教程</a>,复制所需 Cookie 至剪贴板</li>
Expand All @@ -156,7 +160,7 @@ TikTokDownloader
<li>按照提示操作,将 Cookie 写入配置文件</li>
</ol>
</li>
<li>返回程序界面,依次选择 <code>终端命令行模式</code> --> <code>批量下载链接作品</code></li>
<li>返回程序界面,依次选择 <code>终端命令行模式</code> -> <code>批量下载链接作品</code></li>
<li>输入抖音或 TikTok 作品链接即可下载作品文件</li>
<li>更多详细说明请查看 <b><a href="https://github.com/JoeanAmier/TikTokDownloader/wiki/Documentation">项目文档</a></b></li>
</ol>
Expand Down Expand Up @@ -272,5 +276,6 @@ TikTokDownloader
* https://github.com/psf/requests
* https://github.com/pallets/flask
* https://github.com/Textualize/rich
* https://github.com/pyinstaller/pyinstaller
* https://ffmpeg.org/ffmpeg-all.html
* https://html5up.net/hyperspace
2 changes: 1 addition & 1 deletion docs/Cookie教程.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<img src="Cookie教程_1.png" alt="开发人员工具">

**方法二\(貌似无效\)**
**方法二\(不适用\)**

1. 打开浏览器\(可选无痕模式启动\),访问`https://www.douyin.com/`
2. 登录抖音账号\(可跳过\)
Expand Down
29 changes: 16 additions & 13 deletions docs/TikTokDownloader文档.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</div>
<br>
<p>🔥 <b>TikTok 主页/视频/图集/原声;抖音主页/视频/图集/收藏/直播/原声/合集/评论/账号/搜索/热榜数据采集工具:</b>完全开源,基于 Requests 模块实现的免费工具;批量下载抖音账号发布、喜欢、收藏作品;批量下载 TikTok 账号主页作品;下载抖音链接或 TikTok 链接作品;获取抖音直播推流地址;下载抖音直播视频;采集抖音作品评论数据;批量下载抖音合集作品;采集抖音账号详细数据;采集抖音用户 / 作品 / 直播搜索结果;采集抖音热榜数据。</p>
<p>⭐ <b>此文档正在完善中,如有发现任何错误或描述模糊之处,请告知作者以便改进,欢迎各位使用者共同完善项目文档!</b></p>
<p>⭐ <b>项目文档正在完善中,如有发现任何错误或描述模糊之处,请告知作者以便改进!</b></p>
<hr>
<h1>快速入门</h1>
<ol>
Expand All @@ -22,11 +22,13 @@
<ol><b>通过源码运行</b>
<li>安装不低于 <code>3.12</code> 版本的 <a href="https://www.python.org/">Python</a> 解释器</li>
<li>下载最新的源码或 <a href="https://github.com/JoeanAmier/TikTokDownloader/releases/latest">Releases</a> 发布的源码至本地</li>
<li>运行 <code>pip install -r requirements.txt</code> 命令安装程序所需模块</li>
<li>运行 main.py</li>
<li>运行 <code>python -m venv venv</code> 命令创建虚拟环境(可选)</li>
<li>运行 <code>.\venv\Scripts\activate.ps1</code> 或者 <code>venv\Scripts\activate</code> 命令激活虚拟环境(可选)</li>
<li>运行 <code>pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt</code> 命令安装程序所需模块</li>
<li>运行 <code>python .\main.py</code> 或者 <code>python main.py</code> 命令启动 TikTokDownloader</li>
</ol>
</li>
<li>查看屏幕输出的 TikTokDownloader 免责声明,根据提示输入内容</li>
<li>阅读 TikTokDownloader 的免责声明,根据提示输入内容</li>
<li>将 Cookie 信息写入配置文件
<ol><b>手动复制粘贴(推荐)</b>
<li>参考 <a href="https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E6%95%99%E7%A8%8B.md">Cookie 提取教程</a>,复制所需 Cookie 至剪贴板</li>
Expand All @@ -38,11 +40,11 @@
<li>按照提示操作,将 Cookie 写入配置文件</li>
</ol>
</li>
<li>返回程序界面,依次选择 <code>终端命令行模式</code> --> <code>批量下载链接作品</code></li>
<li>返回程序界面,依次选择 <code>终端命令行模式</code> -> <code>批量下载链接作品</code></li>
<li>输入抖音或 TikTok 作品链接即可下载作品文件</li>
</ol>
<h1>获取 Cookie</h1>
<p><a href="https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E6%95%99%E7%A8%8B.md">点击查看 Cookie 获取教程</a></p>
<p><a href="https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E6%95%99%E7%A8%8B.md">点击查看 Cookie 获取教程</a>,无效的 Cookie 会导致程序获取数据失败或者无法下载高分辨率视频文件;目前尚无检查 Cookie 有效性的方法。</p>
<h1>入门说明</h1>
<h2>关于终端</h2>
<p>⭐ 推荐使用 <a href="https://learn.microsoft.com/zh-cn/windows/terminal/install">Windows 终端</a>(Windows 11 自带默认终端)运行程序以便获得最佳彩色交互显示效果!</p>
Expand All @@ -56,11 +58,11 @@
</thead>
<tbody><tr>
<td align="center"><code>https://v.douyin.com/分享码/</code></td>
<td align="center">账号、视频、图集、直播、合集</td>
<td align="center">账号、视频、图集、直播、合集、话题</td>
</tr>
<tr>
<td align="center"><code>https://vm.tiktok.com/分享码/</code></td>
<td align="center">视频、图集</td>
<td align="center">账号、视频、图集</td>
</tr>
<tr>
<td align="center"><code>https://www.douyin.com/note/作品ID</code></td>
Expand Down Expand Up @@ -213,7 +215,7 @@
<tr>
<td align="center">name_format</td>
<td align="center">str</td>
<td align="center">文件保存时的命名规则, 值之间使用空格分隔<br>默认值: 发布时间-作品类型-账号昵称-描述<br><code>id</code>: 唯一值, <code>desc</code>: 描述, <code>create_time</code>: 发布时间<br><code>nickname</code>: 账号昵称, <code>mark</code>: 账号标识, <code>uid</code>: 账号UID, <code>type</code>: 作品类型</td>
<td align="center">文件保存时的命名规则, 值之间使用空格分隔<br>默认值: 发布时间-作品类型-账号昵称-描述<br><code>id</code>: 作品 ID, <code>desc</code>: 作品描述, <code>create_time</code>: 发布时间<br><code>nickname</code>: 账号昵称, <code>mark</code>: 账号标识, <code>uid</code>: 账号 ID, <code>type</code>: 作品类型</td>
</tr>
<tr>
<td align="center">date_format</td>
Expand Down Expand Up @@ -389,6 +391,7 @@
```

<p>将待下载的账号信息写入配置文件,每个账号对应一个对象/字典,<code>tab</code> 参数设置为 <code>favorite</code> 代表批量下载喜欢作品,支持多账号。</p>
<p><b>批量下载账号喜欢作品需要使用已登录的 Cookie,否则可能无法获取正确的账号信息!</b></p>
<h3>发布日期限制</h3>

```json
Expand Down Expand Up @@ -667,7 +670,7 @@ document.body.removeChild(downloadLink);
</ul>
<p>参数之间使用空格分隔,<code>搜索类型</code> 和 <code>排序规则</code> 支持输入中文或者对应索引,<code>页数</code> 和 <code>时间筛选</code> 仅支持输入整数。</p>
<p>程序采集的抖音搜索结果会储存至文件,储存名称格式:<code>搜索数据_搜索时间_搜索类型_关键词_排序依据_时间筛选</code>;不支持直接下载搜索结果作品;必须设置 <code>storage_format</code> 参数才能正常使用。</p>
<p><code>用户搜索</code> 和 <code>直播搜索</code> 不需要输入排序依据和时间筛选(输入也不会报错)</p>
<p><code>用户搜索</code> 和 <code>直播搜索</code> 不需要输入排序依据和时间筛选</p>
<h4>输入示例</h4>
<p><strong>输入:</strong><code>猫咪</code></p>
<p><strong>含义:</strong> 关键词:<code>猫咪</code>;搜索类型:<code>综合搜索</code>;页数:<code>1</code>;排序依据:<code>综合排序</code>;时间筛选:<code>不限</code></p>
Expand Down Expand Up @@ -1006,7 +1009,7 @@ print(response.json())
<h2>启用/禁用检查更新功能</h2>
<p>启用检查更新功能后,运行程序时会向 <code>https://github.com/JoeanAmier/TikTokDownloader/releases/latest</code>
发送请求获取最新 <code>Releases</code> 版本号,并提示是否存在新版本。</p>
<p>如果存在新版本会提示新版本的 <code>URL</code> 地址,不会自动下载更新。</p>
<p>如果检查新版本失败,可能是访问 GitHub 超时,并非功能异常;如果存在新版本会提示新版本的 <code>URL</code> 地址,不会自动下载更新。</p>
<h2>启用/禁用作品下载记录</h2>
<ul>
<li>启用该功能:程序会记录下载成功的作品 ID,如果对作品文件进行移动、重命名或者删除操作,程序不会重复下载该作品,如果想要重新下载该作品,需要删除记录文件中对应的作品 ID 后保存文件并重新运行程序。</li>
Expand All @@ -1021,7 +1024,7 @@ print(response.json())
<h1>其他功能说明</h1>
<h2>单次输入多个链接</h2>
<p><code>批量下载账号作品</code>、<code>批量下载链接作品</code>、<code>获取直播推流地址</code>、<code>采集作品评论数据</code>、<code>批量下载合集作品</code>、<code>批量采集账号数据</code>
支持单次输入多个链接,实现批量下载 / 提取功能;单次输入多个链接时,链接类型需要保持一致,不支持完整链接与分享链接混合输入。</p>
功能支持单次输入多个链接,实现批量下载 / 提取功能;单次输入多个链接时,链接类型需要保持一致,不支持完整链接与分享链接混合输入。</p>
<h3>输入示例</h3>
<p>输入多个链接时,需要使用空格分隔;无需对复制的链接进行额外处理,程序会自动提取输入文本中的有效链接。</p>
<ul>
Expand All @@ -1039,7 +1042,7 @@ print(response.json())
<li><code>name_format</code> 参数中没有使用 <code>nickname</code> 时,<code>mark</code> 设置没有限制。</li>
<li><code>name_format</code> 参数中使用了 <code>nickname</code> 时,<code>mark</code> 与 <code>nickname</code> 不能设置为包含关系的字符串。</li>
</ul>
<p><strong>示例:</strong></p>
<p><strong>标识示例:</strong></p>
<ul>
<li>✔️ <code>nickname</code>:ABC,<code>mark</code>:DEF</li>
<li>✔️ <code>nickname</code>:ABC,<code>mark</code>:BCD</li>
Expand Down
Binary file modified docs/终端模式截图1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 14 additions & 11 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,17 @@ def inner(self, *args, **kwargs):


class TikTokDownloader:
PROJECT_ROOT = Path(__file__).resolve().parent # 源码运行
VERSION = 5.2
STABLE = False
PROJECT_ROOT = Path(__file__).resolve().parent
VERSION_MAJOR = 5
VERSION_MINOR = 2
VERSION_BETA = False

REPOSITORY = "https://github.com/JoeanAmier/TikTokDownloader"
LICENCE = "GNU General Public License v3.0"
DOCUMENTATION_URL = "https://github.com/JoeanAmier/TikTokDownloader/wiki/Documentation"
RELEASES = "https://github.com/JoeanAmier/TikTokDownloader/releases/latest"
NAME = f"TikTokDownloader v{VERSION}{'' if STABLE else ' Beta'}"
NAME = f"TikTokDownloader v{VERSION_MAJOR}.{
VERSION_MINOR}{" Beta" if VERSION_BETA else ""}"
WIDTH = 50
LINE = ">" * WIDTH

Expand Down Expand Up @@ -149,7 +151,7 @@ def disclaimer(self):
def version(self):
self.console.print(f"{self.LINE}\n\n\n{self.NAME.center(
self.WIDTH)}\n\n\n{self.LINE}\n", style=MASTER)
self.console.print(f"项目仓库: {self.REPOSITORY}", style=MASTER)
self.console.print(f"项目地址: {self.REPOSITORY}", style=MASTER)
self.console.print(f"项目文档: {self.DOCUMENTATION_URL}", style=MASTER)
self.console.print(f"开源许可: {self.LICENCE}\n", style=MASTER)

Expand All @@ -174,17 +176,18 @@ def check_update(self):
if self.UPDATE["path"].exists():
return
try:
response = get(self.RELEASES, allow_redirects=False, timeout=5)
tag = float(response.headers['Location'].split("/")[-1])
if tag > self.VERSION:
response = get(self.RELEASES, timeout=5)
latest_major, latest_minor = map(
int, response.url.split("/")[-1].split(".", 1))
if latest_major > self.VERSION_MAJOR or latest_minor > self.VERSION_MINOR:
self.console.print(
f"检测到新版本: {tag}", style=WARNING)
f"检测到新版本: {latest_major}.{latest_minor}", style=WARNING)
self.console.print(self.RELEASES)
elif tag == self.VERSION and not self.STABLE:
elif latest_minor == self.VERSION_MINOR and self.VERSION_BETA:
self.console.print(
"当前版本为开发版, 可更新至正式版", style=WARNING)
self.console.print(self.RELEASES)
elif not self.STABLE:
elif self.VERSION_BETA:
self.console.print("当前已是最新开发版", style=WARNING)
else:
self.console.print("当前已是最新正式版", style=INFO)
Expand Down
6 changes: 3 additions & 3 deletions src/Customizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,23 @@ def condition_filter(data: dict) -> bool:
需要排除的作品返回 False,否则返回 True
"""
# if data["ratio"] in ("720p", "540p"):
# return False
# return False # 过滤低分辨率的视频作品
return True


def rest(count: int, screen):
"""
如需采集大量数据,请启用该函数,可以在处理指定数量的数据后,暂停一段时间,然后继续运行
batches: 每次处理的数据数量上限,比如:每次处理 10 个数据,就会暂停程序
rest_time: 程序暂停的时间,单位:秒;比如:每处理 10 个数据,就暂停 10 分钟
rest_time: 程序暂停的时间,单位:秒;比如:每处理 10 个数据,就暂停 5 分钟
启用该函数需要将第 2 行代码取消注释
仅对 终端命令行模式 的 批量下载账号作品模式 和 批量下载合集作品模式 生效
说明: 此处的一个数据代表一个账号或者一个合集,并非代表一个数据包
"""
# 启用该函数
# batches = 10 # 根据实际需求修改
# if not count % batches:
# rest_time = 60 * 10 # 根据实际需求修改
# rest_time = 60 * 5 # 根据实际需求修改
# screen(
# f"程序已经处理了 {batches} 个数据,为了避免请求频率过高导致账号或 IP 被风控,程序已经暂停运行,"
# f"在 {rest_time} 秒后继续处理数据!", style=GENERAL)
Expand Down
30 changes: 11 additions & 19 deletions src/DataAcquirer.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,28 +247,20 @@ def __init__(self, params: Parameter):

def user(self, text: str) -> list:
urls = self.share.run(text)
if u := self.account_link.findall(urls):
return [i for i in [i[0] for i in u] if i]
elif u := self.account_share.findall(urls):
return u
return []
link = [i for i in [i[0]
for i in self.account_link.findall(urls)] if i]
share = self.account_share.findall(urls)
return link + share

def works(self, text: str) -> tuple:
urls = self.share.run(text)
if u := self.works_link.findall(urls):
tiktok = False
elif u := self.works_link_tiktok.findall(urls):
tiktok = True
elif u := self.works_share.findall(urls):
tiktok = False
elif u := self.account_link.findall(urls):
tiktok = False
u = [i for i in [i[1] for i in u] if i]
# elif u := self.works_id.findall(urls):
# pass
else:
return None, []
return tiktok, u
if u := self.works_link_tiktok.findall(urls):
return True, u
link = self.works_link.findall(urls)
share = self.works_share.findall(urls)
account = [i for i in [i[1]
for i in self.account_link.findall(urls)] if i]
return False, link + share + account

def mix(self, text: str) -> tuple:
urls = self.share.run(text)
Expand Down
17 changes: 13 additions & 4 deletions src/DataDownloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
WARNING,
)
from src.DataAcquirer import retry
from src.Extender import DownloadExtender

__all__ = ["Downloader"]

Expand Down Expand Up @@ -327,7 +328,7 @@ def download_video(
count.skipped_video.add(id_)
return
tasks.append((
item["downloads"],
DownloadExtender.deal(item),
temp_root.with_name(f"{name}.mp4"),
p,
f"视频 {id_}",
Expand Down Expand Up @@ -407,7 +408,7 @@ def request_file(
url,
stream=True,
proxies=self.proxies,
headers=headers or self.Phone_headers if tiktok else self.PC_headers,
headers=self.__adapter_headers(show, headers, tiktok),
timeout=self.timeout) as response:
if not (
content := int(
Expand Down Expand Up @@ -468,6 +469,15 @@ def download_file(
self.add_count(show, id_, count)
return True

def __adapter_headers(
self,
type_: str,
headers: dict,
tiktok: bool) -> dict:
return headers or (
self.Phone_headers if tiktok else self.black_headers if DownloadExtender.MODIFY and type_.startswith(
"视频") else self.PC_headers)

@staticmethod
def add_count(type_: str, id_: str, count: SimpleNamespace):
if type_.startswith("图集"):
Expand Down Expand Up @@ -498,8 +508,7 @@ def generate_works_name(self, data: dict) -> str:
return self.cleaner.filter_name(
self.split.join(
data[i] for i in self.name_format), inquire=False, default=str(
time())[
:10])
time())[:10])

def create_works_folder(
self,
Expand Down
Loading

0 comments on commit 4524ce6

Please sign in to comment.