From 8e65af538c55ea3e1ddf2272e0deda7cec8fb65e Mon Sep 17 00:00:00 2001 From: yml2213 Date: Wed, 24 Jun 2026 08:28:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=85=A8=E5=AF=B9=E9=BD=90=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=20ck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/douyu/login.py | 49 ++++++++++++++++++++---- 对比 ck.txt | 91 +-------------------------------------------- 2 files changed, 42 insertions(+), 98 deletions(-) diff --git a/core/douyu/login.py b/core/douyu/login.py index 8fc62c7..86383ed 100644 --- a/core/douyu/login.py +++ b/core/douyu/login.py @@ -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() diff --git a/对比 ck.txt b/对比 ck.txt index f107d0e..f6db7b0 100644 --- a/对比 ck.txt +++ b/对比 ck.txt @@ -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,这两个缺失可能会导致请求失败;如果只是普通登录态校验,核心字段已经都有。 - - - - - - - - - -