完全对齐目标 ck

This commit is contained in:
yml2213
2026-06-24 08:28:37 +08:00
parent ae92cd2441
commit 8e65af538c
2 changed files with 42 additions and 98 deletions
+41 -8
View File
@@ -56,6 +56,8 @@ class DouyuLogin:
WEBLOGIN_API = "https://msg.douyu.com/webLogin"
CSRF_API = "https://www.douyu.com/japi/carnival/nc/common/generateCsrf"
CSRF_REFERER = "https://www.douyu.com/pages/live-peace-handbook/web/shop?ditchname=pass0&roomId=9263298"
ACF_CCN_API = "https://www.douyu.com/curl/csrfNlApi/getCsrfCookie"
ACF_CCN_REFERER = "https://www.douyu.com/pages/ord-task-center?clientType=web&panelSource=1&rid=0"
LOGIN_REFERER = (
"https://passport.douyu.com/index/login?"
"passport_reg_callback=PASSPORT_REG_SUCCESS_CALLBACK&"
@@ -734,8 +736,9 @@ class DouyuLogin:
except Exception as e:
logger.warning(f"WebLogin请求失败(不影响登录): {e}")
# 登录成功后访问斗鱼 Web CSRF 接口,补齐 cvl_csrf_token;响应里的 acf_ccn 也会进入 session cookie jar
# 登录成功后补齐 Web 侧 Cookie,再导出完整 CK
self._generate_csrf_cookie()
self._generate_acf_ccn_cookie()
return self._format_cookie_string()
@@ -743,8 +746,7 @@ class DouyuLogin:
"""
访问斗鱼 generateCsrf 接口,从 Set-Cookie 中同步 cvl_csrf_token。
requests.Session 会自动接收响应中的 Set-Cookie,所以这里不只保存
cvl_csrf_token;接口额外下发的 acf_ccn 等 Cookie 也会保留到最终 CK。
requests.Session 会自动接收响应中的 Set-Cookie,最终导出时会保留到 CK。
"""
logger.info("补齐CSRF Cookie...")
headers = {
@@ -780,14 +782,45 @@ class DouyuLogin:
if not csrf_token:
raise ValueError("生成CSRF失败: 响应没有 cvl_csrf_token")
if cookies.get('acf_ccn'):
logger.info("已同步 acf_ccn Cookie")
else:
logger.warning("generateCsrf 响应未同步 acf_ccn Cookie")
logger.info("CSRF Cookie已补齐")
return csrf_token
def _generate_acf_ccn_cookie(self) -> str:
"""访问 getCsrfCookie 接口,从 Set-Cookie 中同步 acf_ccn。"""
logger.info("补齐 acf_ccn Cookie...")
headers = {
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Priority': 'u=1, i',
'Referer': self.ACF_CCN_REFERER,
'Sec-CH-UA': '"Google Chrome";v="149", "Chromium";v="149", "Not)A;Brand";v="24"',
'Sec-CH-UA-Mobile': '?0',
'Sec-CH-UA-Platform': '"macOS"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
# 该接口抓包没有 Origin、表单 Content-Type 和 X-Requested-With。
'Origin': None,
'Content-Type': None,
'X-Requested-With': None,
}
response = self._request('get', self.ACF_CCN_API, headers=headers)
response.raise_for_status()
cookies = self.session.cookies.get_dict()
acf_ccn = cookies.get('acf_ccn', '') or response.cookies.get('acf_ccn', '')
if acf_ccn and not cookies.get('acf_ccn'):
# 极少数情况下响应 Cookie 未合入 get_dict,手动补到斗鱼域名下。
self.session.cookies.set('acf_ccn', acf_ccn, domain='.douyu.com', path='/')
if not acf_ccn:
raise ValueError("补齐 acf_ccn 失败: 响应没有 acf_ccn")
logger.info("acf_ccn Cookie已补齐")
return acf_ccn
def _format_cookie_string(self) -> str:
"""把当前 session 中的 Cookie 格式化为可导出的 CK 字符串。"""
cookies = self.session.cookies.get_dict()
+1 -90
View File
@@ -8,99 +8,10 @@ cvl_csrf_token=62083f188904477e9bc1c5a70537145c; acf_ccn=8b025ffcbf403d5e0d880ad
======
自己跑的
dy_accounts_main=; dy_auth=0208CrOVxM5sDK9%2F5WrkVdZhuB4HSkgVod%2F7g6BhzIwaz0KjIUNW%2FkwQP2aNlqlgUCmz40FFwmZlH%2FV%2BKs%2FIfw9NgitHrJUx8w%2F8H1H2Dati3ezwI%2BOR6WYLeQ; wan_auth37wan=36a436a51f20daPv%2B2XfNSB6x4uSc4S%2Bu1ygA0cT%2FjaoFSAvJcFQtC6dlTLGIzT2xhSM8Al1gmJumyROhJOrnC5NFtcWbzxzPwbJEetjQKR58fRcTCcj; LTP0=eyJhbGciOiJtZDUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsicGFzc3BvcnQiXSwiY3QiOjAsImN0aW1lIjoxNzgyMjMwOTMwLCJleHAiOjE3OTc5OTg5MzgsImtleSI6ImR5LWp3dC1tZDUiLCJsdGsiOiIzOWU4ZDZhYzBiZGYwNTEzIiwibHRraWQiOjcxODUwNjE0LCJzdWIiOiJsdCIsInVpZCI6MTAzMDAyMzc0MH0.MjQ3NGQzNWQ1MjkyOGQ1NzUxZjA1OTNiYzAxMmE5MWY; last_login_way=nickname; PHPSESSID=8a7ldg51tuapcngdkdice6pab0; acf_auth=dc71BJkxslSfnGLHIcCLvMmxXDfqt72pB0VW53Z30z7RZfS5NSZRGFvrNShEuX6k0YxPv%2B71Cnhl6O%2FTRQYciZ9l7RhRMqs0ykAhm%2Ftb1ulawonh0V2hoBmU0w; acf_jwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjEwMzAwMjM3NDAsImN0IjowLCJzdWIiOiJzdCIsImF1ZCI6WyJkeSIsIm5vbmUiXSwiYml6IjoxLCJsdGtpZCI6NzE4NTA2MTQsInN0ayI6IjliNDEyMGE2MTFkMDA3NjAiLCJleHAiOjE3ODI4MzU3MzAsImlhdCI6MTc4MjIzMDkzMCwia2V5IjoiZHktand0LW1kNSJ9.ZmE0Y2IwMDIzMmZhZTQzZGIzMmMzNmY2ZWY1NGNjNjQ; acf_dmjwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjEwMzAwMjM3NDAsImN0IjowLCJzdWIiOiJzdCIsImF1ZCI6WyJkbSIsIm5vbmUiXSwiYml6IjoxLCJsdGtpZCI6NzE4NTA2MTQsInN0ayI6IjliNDEyMGE2MTFkMDA3NjAiLCJleHAiOjE3ODI4MzU3MzAsImlhdCI6MTc4MjIzMDkzMCwia2V5IjoiZHktand0LW1kNSJ9.M2QyMWMxYjI2NjY5OTlkMGYyOGVlYTU3ZmRlZTg4YzE; acf_uid=1030023740; acf_username=1030023740; acf_nickname=%E7%94%A8%E6%88%B74965059115; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favatar%2Fdefault%2F24_; acf_ct=0; acf_ltkid=71850614; acf_biz=1; acf_stk=9b4120a611d00760; acf_devid=a72ea6ef2f1f6c51a823d212390ce718
dy_accounts_main=; dy_auth=7febuXzoBCnE7TEoIP28mhEf2OXn6l%2FSwL56eAJA1LYlNzSpDua7PtYlV8gxpxxlPOCFRYwTRw%2BDh6X19MJetWfzOTasWoyu1kxEMg5uitOBAWm5uI%2BqS3M; wan_auth37wan=66e4873d1a6dU7jaNtlupCZ78lHwB7SzAUisHHNHyQlnH3heDOvP4b4CkEPOxy%2FBqT3HGEMra%2FAeflM6D6hfrMpJfXJGoNYwCF08uCnTsYWDiGGHWVE; LTP0=eyJhbGciOiJtZDUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsicGFzc3BvcnQiXSwiY3QiOjAsImN0aW1lIjoxNzgyMjU5OTI5LCJleHAiOjE3OTgwMjc5NDQsImtleSI6ImR5LWp3dC1tZDUiLCJsdGsiOiIwOWJlYWZlZTM2MDBhMjBkIiwibHRraWQiOjU1ODI4NjkxLCJzdWIiOiJsdCIsInVpZCI6NzIyMDUwMDMxfQ.YjVlY2FjNTZkNzIxYjhjMDRjODZhNzE0ZDA3MmQ3OWE; last_login_way=nickname; PHPSESSID=oquhqrc9b6bkfvldj6n7mh9tg2; acf_auth=50c0Hnuwt0o08C%2FaUYAUoiY8QbryaO2fmxkd%2Frn7uktr5WqvmLxNHcpHAcEcgZVmmr29iqA2YTs1adLO%2B4R4NI7Hm8EgLqiKsTw8s152W32rEA9UN7JEL3w; acf_jwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjcyMjA1MDAzMSwiY3QiOjAsInN1YiI6InN0IiwiYXVkIjpbImR5Iiwibm9uZSJdLCJiaXoiOjEsImx0a2lkIjo1NTgyODY5MSwic3RrIjoiMDJhMzM5MjE5YWQxYTdhNSIsImV4cCI6MTc4Mjg2NDcyOSwiaWF0IjoxNzgyMjU5OTI5LCJrZXkiOiJkeS1qd3QtbWQ1In0.YWNlM2FkYTliYjEwMjk5NzdjMDA0Zjc2NGJkNTEwNmQ; acf_dmjwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjcyMjA1MDAzMSwiY3QiOjAsInN1YiI6InN0IiwiYXVkIjpbImRtIiwibm9uZSJdLCJiaXoiOjEsImx0a2lkIjo1NTgyODY5MSwic3RrIjoiMDJhMzM5MjE5YWQxYTdhNSIsImV4cCI6MTc4Mjg2NDcyOSwiaWF0IjoxNzgyMjU5OTI5LCJrZXkiOiJkeS1qd3QtbWQ1In0.ZDljYzlkNTZjNzNhYzMwZjAzNzY5NjQxZmJhM2FmODk; acf_uid=722050031; acf_username=722050031; acf_nickname=%E7%94%A8%E6%88%B76893423879; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favatar%2Fdefault%2F19_; acf_ct=0; acf_ltkid=55828691; acf_biz=1; acf_stk=02a339219ad1a7a5; acf_devid=d5d7050d31074c949bd5394f1241000c; cvl_csrf_token=347aeed3a7974d668de371c1a3213c18
dy_accounts_main=; dy_auth=144fZeqHQY%2F5Q50DbCp7oUK%2FI9%2B7tlIme7rNTAzIvKBMRg0dhiiPgJpK%2B3T3OhZrH5UtVwfQW5ZCszgDFbTR9F8BF%2Fc3Ur7ysvx9Uf%2FT1WsIbZUrWW8BnoI; wan_auth37wan=7d824d0ad6c2wGkeajI%2Fsvzj%2FmYcOzG%2FgdI8oWY6Q4%2FoTS%2F%2FC9sTYuuIj6ri6JJBbmgFykBHwsAAFvMVnLnaabjU2t58%2F2jBuNkq6xn%2BgfgUS6cAMaQ; LTP0=eyJhbGciOiJtZDUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsicGFzc3BvcnQiXSwiY3QiOjAsImN0aW1lIjoxNzgyMjYwNjUzLCJleHAiOjE3OTgwMjg2NjcsImtleSI6ImR5LWp3dC1tZDUiLCJsdGsiOiIzOWM3MDRiYzIyZmU5Nzg2IiwibHRraWQiOjQ0MDI1MTUzLCJzdWIiOiJsdCIsInVpZCI6Njc4MTIyNDkxfQ.ZWQ5NmIxOTAyN2IwYjNhMDE4YmVlM2UyZmFjODFmNTk; last_login_way=nickname; PHPSESSID=6ss9t7f10kpujqh7fpp4a0trh3; acf_auth=f204nj4qW9rQLVFTJu7LrwhJqWaioV%2F7iJjzoycsgLLAMCpnRFgFs8vpaa%2B0RQZPrCYkFYJUICxfVD53UylvFXGAtXq6uTPVtv8sNMn%2B0ukwX1CHbQkUJrs; acf_jwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjY3ODEyMjQ5MSwiY3QiOjAsInN1YiI6InN0IiwiYXVkIjpbImR5Iiwibm9uZSJdLCJiaXoiOjEsImx0a2lkIjo0NDAyNTE1Mywic3RrIjoiZjJhOGFmZTc0ZDc0YTdkMCIsImV4cCI6MTc4Mjg2NTQ1MywiaWF0IjoxNzgyMjYwNjUzLCJrZXkiOiJkeS1qd3QtbWQ1In0.MTM0ZWJkYmQxMDJmODdkMGQwZWE3Y2M3OGE4Y2E3OTM; acf_dmjwt_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJtZDUifQ.eyJ1aWQiOjY3ODEyMjQ5MSwiY3QiOjAsInN1YiI6InN0IiwiYXVkIjpbImRtIiwibm9uZSJdLCJiaXoiOjEsImx0a2lkIjo0NDAyNTE1Mywic3RrIjoiZjJhOGFmZTc0ZDc0YTdkMCIsImV4cCI6MTc4Mjg2NTQ1MywiaWF0IjoxNzgyMjYwNjUzLCJrZXkiOiJkeS1qd3QtbWQ1In0.YjUwODJmYThkMmY2NWNmMTNiM2NkNTk4ZTRhMDE0Y2M; acf_uid=678122491; acf_username=678122491; acf_nickname=%E7%94%A8%E6%88%B77808724800; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favatar%2Fdefault%2F19_; acf_ct=0; acf_ltkid=44025153; acf_biz=1; acf_stk=f2a8afe74d74a7d0; acf_devid=6d4bd35a8ad7facc50bc51ab1792558f; cvl_csrf_token=7252fcd623794ba78c7cb6588caee2e9; acf_ccn=40a9800778aca38c01c39ff7d45eabc8
========
我看了 [对比 ck.txt](/Users/yml/codes/douyu_login_py/对比%20ck.txt),结论是:两组 CK 的核心登录字段都有,但不是同一个账号/同一次登录态;自己跑出来的 CK 少了目标里的 2 个字段,多了 3 个字段。
**字段差异**
目标 CK 独有:
```text
cvl_csrf_token
acf_ccn
```
自己跑的 CK 独有:
```text
dy_accounts_main=
LTP0
last_login_way=nickname
```
其中 `dy_accounts_main=` 是空值,实际意义可能不大;`LTP0` 是 passport 侧的长期 token,目标 CK 里没有。
**相同字段但值不同**
这些字段两边都有,但值都不一样:
```text
PHPSESSID
acf_auth
dy_auth
wan_auth37wan
acf_jwt_token
acf_dmjwt_token
acf_uid
acf_username
acf_nickname
acf_avatar
acf_ltkid
acf_stk
acf_devid
```
账号信息也不同:
```text
目标 uid: 942416451
自己 uid: 1030023740
目标 nickname: 用户4512197651
自己 nickname: 用户4965059115
```
**JWT 载荷对比**
`acf_jwt_token` / `acf_dmjwt_token` 的结构是一致的,区别主要是账号、`ltkid`、`stk`、签发时间、过期时间:
```text
目标:
uid = 942416451
ltkid = 69161685
stk = 4fd469d169f7734b
iat = 2026/6/18 01:39:30
exp = 2026/6/25 01:39:29
自己:
uid = 1030023740
ltkid = 71850614
stk = 9b4120a611d00760
iat = 2026/6/24 00:08:50
exp = 2026/7/1 00:08:50
```
`acf_jwt_token` 的 `aud` 都是 `["dy", "none"]``acf_dmjwt_token` 的 `aud` 都是 `["dm", "none"]`,这部分没问题。
**关键判断**
自己跑出来的 CK 看起来是完整登录态,但和目标 CK 的“形态”不完全一样:主要缺 `cvl_csrf_token` 和 `acf_ccn`。如果某些接口依赖 CSRF 或风控相关 cookie,这两个缺失可能会导致请求失败;如果只是普通登录态校验,核心字段已经都有。