Skip to content

Commit

Permalink
Merge pull request #383 from z0z0r4/dev
Browse files Browse the repository at this point in the history
rechore: login term and tk
  • Loading branch information
z0z0r4 authored Jul 8, 2023
2 parents f55918f + b05c1d4 commit 63494c4
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 69 deletions.
5 changes: 3 additions & 2 deletions bilibili_api/data/api/login.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"comment": "请求二维码及登录密钥"
},
"get_events": {
"url": "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?source=main-fe-header",
"url": "https://passport.bilibili.com/x/passport-login/web/qrcode/poll",
"method": "GET",
"verify": false,
"data": {
"qrcode_key": "str: 登陆密钥"
"qrcode_key": "str: 登陆密钥",
"source": "main-fe-header"
},
"comment": "获取最新信息"
},
Expand Down
175 changes: 111 additions & 64 deletions bilibili_api/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
import uuid
from yarl import URL
import webbrowser
import sys

import requests
from .exceptions.LoginError import LoginError

from .utils.credential import Credential
Expand Down Expand Up @@ -54,14 +54,40 @@
is_destroy = False
id_ = 0 # 事件 id,用于取消 after 绑定


def parse_credential_url(events: dict) -> Credential:
url = events["data"]["url"]
cookies_list = url.split("?")[1].split("&")
sessdata = ""
bili_jct = ""
dedeuserid = ""
for cookie in cookies_list:
if cookie[:8] == "SESSDATA":
sessdata = cookie[9:]
if cookie[:8] == "bili_jct":
bili_jct = cookie[9:]
if cookie[:11].upper() == "DEDEUSERID=":
dedeuserid = cookie[11:]
ac_time_value=events["data"]["refresh_token"]
buvid3=get_live_buvid()
return Credential(sessdata=sessdata,
bili_jct=bili_jct,
buvid3=buvid3,
dedeuserid=dedeuserid,
ac_time_value=ac_time_value)

def make_qrcode(url) -> str:
qr = qrcode.QRCode()
qr.add_data(url)
img = qr.make_image()
img.save(os.path.join(tempfile.gettempdir(), "qrcode.png"))
print("二维码已保存至", os.path.join(tempfile.gettempdir(), "qrcode.png"))
return os.path.join(tempfile.gettempdir(), "qrcode.png")

def update_qrcode_data() -> dict:
api = API["qrcode"]["get_qrcode_and_token"]
qrcode_data = httpx.get(api["url"], follow_redirects=True).json()['data']
return qrcode_data


def login_with_qrcode(root=None) -> Credential:
"""
Expand All @@ -85,68 +111,42 @@ def login_with_qrcode(root=None) -> Credential:
if root == None:
root = tkinter.Tk()
root.title("扫码登录")
qrcode_image = update_qrcode()
qrcode_data = update_qrcode_data()
login_key = qrcode_data["qrcode_key"]
qrcode_image = make_qrcode(qrcode_data["url"])
photo = PhotoImage(file=qrcode_image)
qrcode_label = tkinter.Label(root, image=photo, width=500, height=500)
qrcode_label = tkinter.Label(root, image=photo, width=600, height=600)
qrcode_label.pack()
big_font = tkinter.font.Font(root, size=25)
log = tkinter.Label(root, text="请扫描二维码↑", font=big_font, fg="red")
log.pack()

def update_events():
global id_
global start, credential, is_destroy
# log.configure(text="点下确认啊!", fg="orange", font=big_font)
events_api = API["qrcode"]["get_events"]
params = {"qrcode_key": login_key}
events = json.loads(
requests.get(
events_api["url"],
params=params,
cookies={"buvid3": str(uuid.uuid1()), "Domain": ".bilibili.com"},
).text
)
# print(events)
# 新的 events["data"]
# {'url': '', 'refresh_token': '', 'timestamp': 0, 'code': 86101, 'message': '未扫码'}
# {'url': '', 'refresh_token': '', 'timestamp': 0, 'code': 86090, 'message': '二维码已扫码未确认'}
# {'url': 'https://passport.biligame.com/x/passport-login/web/crossDomain?DedeUserID=x&DedeUserID__ckMd5=x&Expires=x&SESSDATA=x&bili_jct=x&gourl=x', 'refresh_token': 'x', 'timestamp': 1683903305723, 'code': 0, 'message': ''}
if "code" in events.keys() and events["code"] == -412:
raise LoginError(events["message"])
if events["data"]["code"] == 86101:
log.configure(text="请扫描二维码↑", fg="red", font=big_font)
elif events["data"]["code"] == 86090:
log.configure(text="点下确认啊!", fg="orange", font=big_font)
elif events["data"]["code"] == 0:
url: str = events["data"]["url"]
cookies_list = url.split("?")[1].split("&")
sessdata = ""
bili_jct = ""
dedeuserid = ""
for cookie in cookies_list:
if cookie[:8] == "SESSDATA":
sessdata = cookie[9:]
if cookie[:8] == "bili_jct":
bili_jct = cookie[9:]
if cookie[:11].upper() == "DEDEUSERID=":
dedeuserid = cookie[11:]
c = Credential(
sessdata=sessdata,
bili_jct=bili_jct,
dedeuserid=dedeuserid,
ac_time_value=events["data"]["refresh_token"],
)
global credential
credential = c
log.configure(text="成功!", fg="green", font=big_font)
global start
start = time.perf_counter()
root.after(1000, destroy)
id_ = root.after(500, update_events)
# 刷新
if time.perf_counter() - start > 120:
update_qrcode()
start = time.perf_counter()
global start, credential, is_destroy, login_key
events = login_with_key(login_key)
if "code" in events.keys() and events["code"] == 0:
if events["data"]["code"] == 86101:
log.configure(text="请扫描二维码↑", fg="red", font=big_font)
elif events["data"]["code"] == 86090:
log.configure(text="点下确认啊!", fg="orange", font=big_font)
elif events["data"]["code"] == 86038:
raise LoginError("二维码过期,请扫新二维码!")
elif events["data"]["code"] == 0:
log.configure(text="成功!", fg="green", font=big_font)
credential = parse_credential_url(events)
root.after(1000, destroy)
return 0
id_ = root.after(500, update_events)
if time.perf_counter() - start > 120: # 刷新
qrcode_data = update_qrcode_data()
login_key = qrcode_data["qrcode_key"]
qrcode_image = make_qrcode(qrcode_data["url"])
photo = PhotoImage(file=qrcode_image)
qrcode_label = tkinter.Label(root, image=photo, width=600, height=600)
qrcode_label.pack()
start = time.perf_counter()

root.update()

def destroy():
Expand All @@ -159,16 +159,63 @@ def destroy():
root.after_cancel(id_) # type: ignore
return credential

def login_with_qrcode_term() -> Credential:
"""
终端扫描二维码登录
def update_qrcode() -> str:
global login_key, qrcode_image
api = API["qrcode"]["get_qrcode_and_token"]
qrcode_login_data = json.loads(httpx.get(api["url"]).text)["data"]
login_key = qrcode_login_data["qrcode_key"]
qrcode = qrcode_login_data["url"]
qrcode_image = make_qrcode(qrcode)
return qrcode_image
Args:
Returns:
Credential: 凭据
"""
import qrcode_terminal
qrcode_data = update_qrcode_data()
qrcode_url = qrcode_data["url"]
login_key = qrcode_data["qrcode_key"]
print(qrcode_terminal.qr_terminal_str(qrcode_url) + "\n")
while True:
events = login_with_key(login_key)
if "code" in events.keys() and events["code"] == 0:
if events["data"]["code"] == 86101:
sys.stdout.write('\r 请扫描二维码↑')
sys.stdout.flush()
elif events["data"]["code"] == 86090:
sys.stdout.write('\r 点下确认啊!')
sys.stdout.flush()
elif events["data"]["code"] == 86038:
print("二维码过期,请扫新二维码!")
qrcode_data = update_qrcode_data()
qrcode_url = qrcode_data["url"]
print(qrcode_terminal.qr_terminal_str(qrcode_url) + "\n")
elif events["data"]["code"] == 0:
sys.stdout.write('\r 成功!')
sys.stdout.flush()
return parse_credential_url(events)
elif "code" in events.keys():
raise LoginError(events["message"])
time.sleep(0.5)


def login_with_key(key: str) -> dict:
params = {"qrcode_key": key, "source": "main-fe-header"}
events_api = API["qrcode"]["get_events"]
events = httpx.get(
events_api["url"],
params=params,
cookies={"buvid3": str(uuid.uuid1()), "Domain": ".bilibili.com"},
).json()
return events


def get_live_buvid():
import re
url = "https://api.live.bilibili.com/gift/v3/live/gift_config"
headers = HEADERS.copy()
response = httpx.get(url, headers=headers)
response.raise_for_status()
set_cookie = response.headers.get("Set-Cookie")
live_buvid = re.findall(r"LIVE_BUVID=(AUTO[0-9]+)", set_cookie)[0]
return live_buvid

# ----------------------------------------------------------------
# 密码登录
Expand Down
2 changes: 1 addition & 1 deletion bilibili_api/login_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_qrcode() -> Tuple[Picture, str]:
Returns:
Tuple[dir, str]: 第一项是二维码图片地址(本地缓存)和登录密钥。登录密钥需要保存。
"""
img = login.update_qrcode()
img = login.update_qrcode_image()
login_key = login.login_key
return (Picture.from_file(img), login_key)

Expand Down
3 changes: 2 additions & 1 deletion docs/examples/login.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
``` python
from bilibili_api import login, user, sync
print("请登录:")
credential = login.login_with_qrcode()
credential = login.login_with_qrcode_term() # 在终端扫描二维码登录
# credential = login.login_with_qrcode() # 使用窗口显示二维码登录
try:
credential.raise_for_no_bili_jct() # 判断是否成功
credential.raise_for_no_sessdata() # 判断是否成功
Expand Down
12 changes: 11 additions & 1 deletion docs/modules/login.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from bilibili_api import login
---
**注意:**

`linux` 的小伙伴在使用 `login_with_qrcode` 时先装一下 `python3-tk` 吧。
建议 `linux` 的用户使用 `login_with_qrcode_term` 通过终端扫码登录,或者在使用 `login_with_qrcode` 时先装一下 `python3-tk` 吧。

``` bash
$ sudo apt-get install python3-tk
Expand Down Expand Up @@ -79,6 +79,14 @@ $ sudo apt-get install python3-tk

---

## def login_with_qrcode_term()

**推荐方式** 扫描终端二维码登录。

**Returns:** Credential 凭据类。

---

## def login_with_qrcode()

| name | type | description |
Expand All @@ -91,6 +99,8 @@ $ sudo apt-get install python3-tk

**Returns:** Credential 凭据类。

---

## def login_with_password()

| name | type | description |
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ pillow~=10.0.0
tqdm~=4.65.0
yarl~=1.9.2
pycryptodomex~=3.18.0
qrcode_terminal~=0.8

0 comments on commit 63494c4

Please sign in to comment.