<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>网络 on By.Chi</title><link>https://by-chi.github.io/tags/%E7%BD%91%E7%BB%9C/</link><description>Recent content in 网络 on By.Chi</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 08 May 2026 23:46:11 +0800</lastBuildDate><atom:link href="https://by-chi.github.io/tags/%E7%BD%91%E7%BB%9C/index.xml" rel="self" type="application/rss+xml"/><item><title>用GDScript实现扫码登陆Bilibili获取到SESSDATA</title><link>https://by-chi.github.io/posts/%E7%94%A8gdscript%E5%AE%9E%E7%8E%B0%E6%89%AB%E7%A0%81%E7%99%BB%E9%99%86bilibili%E8%8E%B7%E5%8F%96%E5%88%B0sessdata/</link><pubDate>Fri, 08 May 2026 23:46:11 +0800</pubDate><guid>https://by-chi.github.io/posts/%E7%94%A8gdscript%E5%AE%9E%E7%8E%B0%E6%89%AB%E7%A0%81%E7%99%BB%E9%99%86bilibili%E8%8E%B7%E5%8F%96%E5%88%B0sessdata/</guid><description>&lt;h1 id="godot中使用gdscript-实现-bilibili-扫码登录获取-sessdata-流程"&gt;Godot中使用GDScript 实现 Bilibili 扫码登录获取 SESSDATA 流程&lt;/h1&gt;
&lt;p&gt;本文档总结 Godot 项目中通过 Bilibili 扫码登录获取 &lt;code&gt;SESSDATA&lt;/code&gt; 的核心逻辑，代码位于脚本的 &lt;code&gt;需要用户登陆&lt;/code&gt; 区域。&lt;/p&gt;
&lt;h2 id="功能概述"&gt;功能概述&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;调用 Bilibili 官方接口生成登录二维码，在应用内展示。&lt;/li&gt;
&lt;li&gt;定时轮询二维码扫描状态，检测用户是否已扫码并确认登录。&lt;/li&gt;
&lt;li&gt;扫码成功后通过登录链接交换得到 &lt;code&gt;SESSDATA&lt;/code&gt;，并持久化到项目存储中。&lt;/li&gt;
&lt;li&gt;提供回调机制通知调用方登录结果（成功/失败）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="源代码"&gt;源代码&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# 扫码登录相关变量
var qr_window: Window = null
var _poll_timer: Timer
var on_qr_login_result: Callable
func start_qr_login(login_callback: Callable) -&amp;gt; void:
on_qr_login_result = login_callback
var http = HTTPRequest.new()
add_child(http)
http.request_completed.connect(_on_qr_generated)
var err = http.request(&amp;#34;https://passport.bilibili.com/x/passport-login/web/qrcode/generate&amp;#34;, PackedStringArray(), HTTPClient.METHOD_GET)
func _on_qr_generated(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -&amp;gt; void:
if response_code != 200: return
var json = JSON.new()
if json.parse(body.get_string_from_utf8()) != OK: return
var data = json.get_data()[&amp;#34;data&amp;#34;]
var url = data[&amp;#34;url&amp;#34;]
var qrcode_key = data[&amp;#34;qrcode_key&amp;#34;]
_display_qrcode(url)
_poll_login_status(qrcode_key)
func _display_qrcode(content: String) -&amp;gt; void:
qr_window = preload(&amp;#34;res://Scene/Log_in.tscn&amp;#34;).instantiate()
qr_window.close_requested.connect(_on_qr_window_closed)
add_child(qr_window)
var encoded = content.uri_encode()
var qr_api = &amp;#34;https://api.qrserver.com/v1/create-qr-code/?size=200x200&amp;amp;data=&amp;#34; + encoded
var img_request = HTTPRequest.new()
add_child(img_request)
img_request.request_completed.connect(func(_r, _c, _h, body):
if not is_instance_valid(qr_window):
return
var img = Image.new()
if img.load_png_from_buffer(body) == OK:
var tex = ImageTexture.create_from_image(img)
qr_window.get_node(&amp;#34;QRImage&amp;#34;).texture = tex
else:
push_error(&amp;#34;二维码图片加载失败&amp;#34;)
)
img_request.request(qr_api, PackedStringArray(), HTTPClient.METHOD_GET)
func _on_qr_window_closed() -&amp;gt; void:
if qr_window:
qr_window.queue_free()
qr_window = null
if _poll_timer:
_poll_timer.stop()
_poll_timer.queue_free()
_poll_timer = null
if on_qr_login_result:
on_qr_login_result.call(false)
func _close_qr_window() -&amp;gt; void:
if qr_window:
qr_window.queue_free()
qr_window = null
if _poll_timer:
_poll_timer.stop()
_poll_timer.queue_free()
_poll_timer = null
func _poll_login_status(qrcode_key: String) -&amp;gt; void:
_poll_timer = Timer.new()
_poll_timer.wait_time = 2.0
_poll_timer.autostart = true
_poll_timer.timeout.connect(_check_qr_status.bind(qrcode_key))
add_child(_poll_timer)
func _check_qr_status(qrcode_key: String) -&amp;gt; void:
var http = HTTPRequest.new()
add_child(http)
http.request_completed.connect(func(result, response_code, headers, body):
if response_code != 200: return
var json = JSON.new()
if json.parse(body.get_string_from_utf8()) != OK: return
var data = json.get_data()[&amp;#34;data&amp;#34;]
var code = data[&amp;#34;code&amp;#34;]
if code == 0:
_exchange_cookie(data[&amp;#34;url&amp;#34;])
if on_qr_login_result:
on_qr_login_result.call(true)
_close_qr_window()
elif code == 86038:
if on_qr_login_result:
on_qr_login_result.call(false)
_close_qr_window()
)
http.request(&amp;#34;https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=&amp;#34; + qrcode_key, PackedStringArray(), HTTPClient.METHOD_GET)
func _exchange_cookie(login_url: String) -&amp;gt; void:
var http = HTTPRequest.new()
add_child(http)
http.request_completed.connect(func(result, response_code, headers, body):
for header in headers:
if header.begins_with(&amp;#34;Set-Cookie: SESSDATA=&amp;#34;):
var sess = header.split(&amp;#34;=&amp;#34;)[1].split(&amp;#34;;&amp;#34;)[0]
GdScriptFunc.set_data(&amp;#34;AccountData&amp;#34;,&amp;#34;SESSDATA&amp;#34;,sess)
break
)
http.request(login_url, PackedStringArray(), HTTPClient.METHOD_GET)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="核心流程"&gt;核心流程&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发起登录&lt;/strong&gt;&lt;br&gt;
调用 &lt;code&gt;start_qr_login(login_callback)&lt;/code&gt; 开始流程，传入一个回调函数用于接收登录结果。&lt;/p&gt;</description></item></channel></rss>