get_douyin_download_link
Generate watermark-free download links for Douyin videos by providing a share link or text containing the link. Returns JSON with video information and direct download URL.
Instructions
获取抖音视频的无水印下载链接
参数:
- share_link: 抖音分享链接或包含链接的文本
返回:
- 包含下载链接和视频信息的JSON字符串
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| share_link | Yes |
Implementation Reference
- douyin_mcp_server/server.py:198-227 (handler)The primary handler function for the 'get_douyin_download_link' tool. Decorated with @mcp.tool() for automatic registration. Parses the share_link using DouyinProcessor and returns JSON with no-watermark download URL.@mcp.tool() def get_douyin_download_link(share_link: str) -> str: """ 获取抖音视频的无水印下载链接 参数: - share_link: 抖音分享链接或包含链接的文本 返回: - 包含下载链接和视频信息的JSON字符串 """ try: processor = DouyinProcessor("") # 获取下载链接不需要API密钥 video_info = processor.parse_share_url(share_link) return json.dumps({ "status": "success", "video_id": video_info["video_id"], "title": video_info["title"], "download_url": video_info["url"], "description": f"视频标题: {video_info['title']}", "usage_tip": "可以直接使用此链接下载无水印视频" }, ensure_ascii=False, indent=2) except Exception as e: return json.dumps({ "status": "error", "error": f"获取下载链接失败: {str(e)}" }, ensure_ascii=False, indent=2)
- douyin_mcp_server/server.py:59-110 (helper)Core helper method in DouyinProcessor class that implements the logic to scrape Douyin share page, parse the embedded JSON, and extract/modify the video URL to no-watermark version.def parse_share_url(self, share_text: str) -> dict: """从分享文本中提取无水印视频链接""" # 提取分享链接 urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', share_text) if not urls: raise ValueError("未找到有效的分享链接") share_url = urls[0] share_response = requests.get(share_url, headers=HEADERS) video_id = share_response.url.split("?")[0].strip("/").split("/")[-1] share_url = f'https://www.iesdouyin.com/share/video/{video_id}' # 获取视频页面内容 response = requests.get(share_url, headers=HEADERS) response.raise_for_status() pattern = re.compile( pattern=r"window\._ROUTER_DATA\s*=\s*(.*?)</script>", flags=re.DOTALL, ) find_res = pattern.search(response.text) if not find_res or not find_res.group(1): raise ValueError("从HTML中解析视频信息失败") # 解析JSON数据 json_data = json.loads(find_res.group(1).strip()) VIDEO_ID_PAGE_KEY = "video_(id)/page" NOTE_ID_PAGE_KEY = "note_(id)/page" if VIDEO_ID_PAGE_KEY in json_data["loaderData"]: original_video_info = json_data["loaderData"][VIDEO_ID_PAGE_KEY]["videoInfoRes"] elif NOTE_ID_PAGE_KEY in json_data["loaderData"]: original_video_info = json_data["loaderData"][NOTE_ID_PAGE_KEY]["videoInfoRes"] else: raise Exception("无法从JSON中解析视频或图集信息") data = original_video_info["item_list"][0] # 获取视频信息 video_url = data["video"]["play_addr"]["url_list"][0].replace("playwm", "play") desc = data.get("desc", "").strip() or f"douyin_{video_id}" # 替换文件名中的非法字符 desc = re.sub(r'[\\/:*?"<>|]', '_', desc) return { "url": video_url, "title": desc, "video_id": video_id }