diff --git a/biliup/plugins/Danmaku/douyin.py b/biliup/plugins/Danmaku/douyin.py
index 4f146a6..e374756 100644
--- a/biliup/plugins/Danmaku/douyin.py
+++ b/biliup/plugins/Danmaku/douyin.py
@@ -2,7 +2,6 @@
# 2023.07.14:KNaiFen:这部分代码参考了https://github.com/SmallPeaches/DanmakuRender
import gzip
-import time
import aiohttp
import json
@@ -15,9 +14,6 @@ from google.protobuf import json_format
class Douyin:
headers = {
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
- 'Accept-Encoding': 'gzip, deflate',
- 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
'Referer': 'https://live.douyin.com/',
'Cookie': config.get('user', {}).get('douyin_cookie', '')
@@ -28,6 +24,7 @@ class Douyin:
@staticmethod
async def get_ws_info(url):
async with aiohttp.ClientSession() as session:
+ from biliup.plugins.douyin import DouyinUtils
if "/user/" in url:
async with session.get(url, headers=Douyin.headers, timeout=5) as resp:
user_page = await resp.text()
@@ -36,22 +33,19 @@ class Douyin:
room_id = match1(user_page_data, r'"web_rid":"([^"]+)"')
else:
room_id = url.split('douyin.com/')[1].split('/')[0].split('?')[0]
+
if room_id[0] == "+":
room_id = room_id[1:]
- if room_id.isdigit():
- room_id = f"+{room_id}"
- async with session.get(f'https://live.douyin.com/{room_id}', headers=Douyin.headers, timeout=5) as resp:
- page = await resp.text()
- if "ttwid" not in Douyin.headers['Cookie'] and "ttwid" in resp.cookies:
- Douyin.headers['Cookie'] = f'ttwid={resp.cookies.get("ttwid").value};{Douyin.headers["Cookie"]}'
- data = json.loads(
- unquote(
- page.split('')[0]))
- real_rid = data['app']['initialState']['roomStore']['roomInfo']['roomId']
- user_unique_id = data['app']['odin']['user_unique_id']
+ if "ttwid" not in Douyin.headers['Cookie']:
+ Douyin.headers['Cookie'] = f'ttwid={DouyinUtils.get_ttwid()};{Douyin.headers["Cookie"]}'
- url = f"wss://webcast3-ws-web-lf.douyin.com/webcast/im/push/v2/?app_name=douyin_web&version_code=180800&webcast_sdk_version=1.3.0&update_version_code=1.3.0&compress=gzip&internal_ext=internal_src:dim|wss_push_room_id:{real_rid}|wss_push_did:{user_unique_id}|dim_log_id:2023011316221327ACACF0E44A2C0E8200|fetch_time:${int(time.time())}123|seq:1|wss_info:0-1673598133900-0-0|wrds_kvs:WebcastRoomRankMessage-1673597852921055645_WebcastRoomStatsMessage-1673598128993068211&cursor=u-1_h-1_t-1672732684536_r-1_d-1&host=https://live.douyin.com&aid=6383&live_id=1&did_rule=3&debug=false&endpoint=live_pc&support_wrds=1&im_path=/webcast/im/fetch/&device_platform=web&cookie_enabled=true&screen_width=1228&screen_height=691&browser_language=zh-CN&browser_platform=Win32&browser_name=Mozilla&browser_version=5.0%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/92.0.4515.159%20Safari/537.36&browser_online=true&tz_name=Asia/Shanghai&identity=audience&room_id={real_rid}&heartbeatDuration=0&signature=00000000"
+ async with session.get(
+ DouyinUtils.build_request_url(f"https://live.douyin.com/webcast/room/web/enter/?web_rid={room_id}"),
+ headers=Douyin.headers, timeout=5) as resp:
+ room_info = json.loads(await resp.text())['data']['data'][0]
+ url = DouyinUtils.build_request_url(
+ f"wss://webcast3-ws-web-lf.douyin.com/webcast/im/push/v2/?room_id={room_info['id_str']}&compress=gzip&signature=00000000")
return url, []
@staticmethod
diff --git a/biliup/plugins/douyin.py b/biliup/plugins/douyin.py
index 7e84bb6..18efd8f 100644
--- a/biliup/plugins/douyin.py
+++ b/biliup/plugins/douyin.py
@@ -1,12 +1,14 @@
import json
-from urllib.parse import unquote
+from typing import Optional
+from urllib.parse import unquote, urlparse, parse_qs, urlencode, urlunparse
import requests
from . import logger, match1
from biliup.config import config
+from .Danmaku import DanmakuClient
+from ..common.tools import NamedLock
from ..engine.decorators import Plugin
from ..engine.download import DownloadBase
-from biliup.plugins.Danmaku import DanmakuClient
@Plugin.download(regexp=r'(?:https?://)?(?:(?:www|m|live)\.)?douyin\.com')
@@ -27,8 +29,11 @@ class Douyin(DownloadBase):
if room_id is None or not room_id:
logger.debug(f"{Douyin.__name__}: {self.url}: 未开播")
return False
+ except (KeyError, IndexError):
+ logger.warning(f"{Douyin.__name__}: {self.url}: 获取房间ID失败,请检查Cookie设置")
+ return False
except:
- logger.warning(f"{Douyin.__name__}: {self.url}: 获取房间ID错误")
+ logger.warning(f"{Douyin.__name__}: {self.url}: 获取房间ID失败")
return False
else:
try:
@@ -41,19 +46,19 @@ class Douyin(DownloadBase):
if room_id[0] == "+":
room_id = room_id[1:]
- if room_id.isdigit():
- room_id = f"+{room_id}"
-
try:
- page = requests.get(f"https://live.douyin.com/{room_id}", headers=self.fake_headers, timeout=5).text
- page_data = unquote(
- page.split('')[0])
- room_info = json.loads(page_data)['app']['initialState']['roomStore']['roomInfo']['room']
- except (KeyError, IndexError):
- logger.warning(f"{Douyin.__name__}: {self.url}: 获取错误,请检查Cookie设置")
- return False
+ if "ttwid" not in self.fake_headers['Cookie']:
+ self.fake_headers['Cookie'] = f'ttwid={DouyinUtils.get_ttwid()};{self.fake_headers["Cookie"]}'
+ page = requests.get(
+ DouyinUtils.build_request_url(f"https://live.douyin.com/webcast/room/web/enter/?web_rid={room_id}"),
+ headers=self.fake_headers, timeout=5).text
+ room_info = json.loads(page)['data']['data']
+ if len(room_info) > 0:
+ room_info = room_info[0]
+ else:
+ room_info = {}
except:
- logger.warning(f"{Douyin.__name__}: {self.url}: 获取错误")
+ logger.warning(f"{Douyin.__name__}: {self.url}: 获取失败")
return False
try:
@@ -111,3 +116,37 @@ class Douyin(DownloadBase):
def close(self):
if self.danmaku:
self.danmaku.stop()
+
+
+class DouyinUtils:
+ # 抖音ttwid
+ _douyin_ttwid: Optional[str] = None
+
+ @staticmethod
+ def get_ttwid() -> Optional[str]:
+ with NamedLock("douyin_ttwid_get"):
+ if not DouyinUtils._douyin_ttwid:
+ page = requests.get("https://live.douyin.com/1-2-3-4-5-6-7-8-9-0", timeout=5)
+ DouyinUtils._douyin_ttwid = page.cookies.get("ttwid")
+ return DouyinUtils._douyin_ttwid
+
+ @staticmethod
+ def build_request_url(url: str) -> str:
+ parsed_url = urlparse(url)
+ existing_params = parse_qs(parsed_url.query)
+ existing_params['aid'] = ['6383']
+ existing_params['device_platform'] = ['web']
+ existing_params['browser_language'] = ['zh-CN']
+ existing_params['browser_platform'] = ['Win32']
+ existing_params['browser_name'] = ['Chrome']
+ existing_params['browser_version'] = ['92.0.4515.159']
+ new_query_string = urlencode(existing_params, doseq=True)
+ new_url = urlunparse((
+ parsed_url.scheme,
+ parsed_url.netloc,
+ parsed_url.path,
+ parsed_url.params,
+ new_query_string,
+ parsed_url.fragment
+ ))
+ return new_url