十一.Python_函数闭包模拟Session

本文介绍了一种使用Python函数闭包来模拟Session机制的方法,通过装饰器实现用户登录验证,控制不同页面的访问权限。文章详细展示了如何利用闭包保存用户登录状态,并在多次函数调用间保持这一状态。

 Python_函数闭包模拟Session

#   19.函数闭包模拟Session

#模拟数据库
list_user=[{"name":"tom","password":"123"},
           {"name": "cat", "password": "123"},
           {"name": "ssh", "password": "123"},
           {"name": "alex", "password": "123"},
           {"name": "marry", "password": "123"},
           {"name": "sam", "password": "123"}]   #模拟数据库的用户
#模拟Session
curren_login={"name":None,"status":False}        #当前登录状态


#判断用户登陆验证的装饰器

def validate(con):                                #获取@validator()的参数
    def _validate(func):                          #获取目标函数
        def wrapper():                            #获取目标函数的参数
            if(curren_login["name"] and curren_login["status"]):    #获取当前登录状态是否存在用户登录
                res = func(curren_login["name"])                     #用户登录调用目标函数
                return res                                           #返回目标函数
            print("欢迎来到京东商城!")
            name=input("请输入用户名:")                              #用户没用登陆让用户输入用户名
            password=input("请输入密码:")                           #用户没用登陆让用户输入用户密码
            for i in list_user:                                      #循环数据库的用户
                if i["name"]==name:                                  #判断该用户是否存在数据库中
                    if(password==i["password"]):                     #判断该用户的密码与数据库存储的密码是否一致
                        print("执行%s函数"%con)                      #输出要执行的函数
                        res=func(name)                                #用户登录成功调用目标函数
                        curren_login["name"]=name                    #设置登录状态的用户
                        curren_login["status"]=True                 #设置登录状态
                        return res                                   #返回目标函数
                    else:                                            #用户名或密码输入有误
                        print("您输入的用户名或密码有误!")         #打印登陆失败的结果
        return wrapper                                               #将wrapper函数作为返回值
    return _validate                                                #将_validate函数作为返回值

#跳转jd首页
@validate("index")                  #相当于index=_validator(index)
def index(name="1223"):
    print("%s!欢迎来到JD页面!"%name)

#跳转jd个人主页
@validate("home")                  #相当于home=_validator(home)
def home(name="1223"):
    print("欢迎%s来到home!"%name)

#跳转jd购物车
@validate("shop")                  #相当于shop=_validator(shop)
def shop(name="1223"):
    print("%s 购物车里有 零食 数码产品"%name)


index()                            #调用index函数
# home()
# shop()

 

import sys import json import sqlite3 import requests from PyQt5.QtWidgets import (QApplication, QMainWindow, QSplitter, QListWidget, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLineEdit, QLabel, QMessageBox, QStatusBar) from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile from PyQt5.QtCore import QUrl, Qt, QTimer from PyQt5.QtNetwork import QNetworkCookie class AccountManager: """账号管理类,处理账号的存储和加载""" def __init__(self, db_name='bilibili_accounts.db'): self.conn = sqlite3.connect(db_name) self.cursor = self.conn.cursor() self._create_table() def _create_table(self): self.cursor.execute(''' CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, cookies TEXT NOT NULL ) ''') self.conn.commit() def add_account(self, name, cookies): """添加新账号""" try: self.cursor.execute( "INSERT INTO accounts (name, cookies) VALUES (?, ?)", (name, json.dumps(cookies)) ) self.conn.commit() return True except sqlite3.IntegrityError: return False def get_accounts(self): """获取所有账号""" self.cursor.execute("SELECT id, name, cookies FROM accounts") return [ {'id': row[0], 'name': row[1], 'cookies': json.loads(row[2])} for row in self.cursor.fetchall() ] def delete_account(self, account_id): """删除账号""" self.cursor.execute("DELETE FROM accounts WHERE id=?", (account_id,)) self.conn.commit() def __del__(self): self.conn.close() class BilibiliBrowser(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("B站多账号浏览器") self.resize(1200, 800) # 初始化账号管理器 self.account_manager = AccountManager() # 创建UI self.init_ui() # 加载账号列表 self.load_accounts() # 设置状态栏 self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("就绪", 3000) def init_ui(self): """初始化用户界面""" # 主分割布局 main_splitter = QSplitter(Qt.Horizontal) # 左侧账号管理区域 account_widget = QWidget() account_layout = QVBoxLayout() # 账号列表 account_layout.addWidget(QLabel("账号列表")) self.account_list = QListWidget() self.account_list.itemClicked.connect(self.switch_account) account_layout.addWidget(self.account_list) # 添加账号区域 add_account_layout = QHBoxLayout() self.account_name_input = QLineEdit() self.account_name_input.setPlaceholderText("输入账号名称") add_account_layout.addWidget(self.account_name_input) add_btn = QPushButton("添加账号") add_btn.clicked.connect(self.add_account) add_account_layout.addWidget(add_btn) account_layout.addLayout(add_account_layout) # 删除账号按钮 del_btn = QPushButton("删除选中账号") del_btn.clicked.connect(self.delete_account) account_layout.addWidget(del_btn) # 检测账号状态按钮 check_btn = QPushButton("检测账号状态") check_btn.clicked.connect(self.check_account_status) account_layout.addWidget(check_btn) account_widget.setLayout(account_layout) # 右侧浏览器区域 browser_widget = QWidget() browser_layout = QVBoxLayout() # 导航栏 nav_layout = QHBoxLayout() self.url_bar = QLineEdit() self.url_bar.setPlaceholderText("输入网址或搜索内容") self.url_bar.returnPressed.connect(self.navigate_to_url) nav_layout.addWidget(self.url_bar) home_btn = QPushButton("首页") home_btn.clicked.connect(self.go_home) nav_layout.addWidget(home_btn) refresh_btn = QPushButton("刷新") refresh_btn.clicked.connect(self.refresh_page) nav_layout.addWidget(refresh_btn) browser_layout.addLayout(nav_layout) # 浏览器视图 self.browser = QWebEngineView() self.browser.load(QUrl("https://www.bilibili.com")) self.browser.urlChanged.connect(self.update_url_bar) browser_layout.addWidget(self.browser) browser_widget.setLayout(browser_layout) # 添加组件到主分割器 main_splitter.addWidget(account_widget) main_splitter.addWidget(browser_widget) main_splitter.setSizes([300, 900]) self.setCentralWidget(main_splitter) def load_accounts(self): """加载所有账号到列表""" self.account_list.clear() accounts = self.account_manager.get_accounts() for account in accounts: self.account_list.addItem(f"{account['name']} (ID:{account['id']})") def add_account(self): """添加新账号""" account_name = self.account_name_input.text().strip() if not account_name: QMessageBox.warning(self, "输入错误", "请输入账号名称") return # 获取当前浏览器的Cookie cookie_store = self.browser.page().profile().cookieStore() cookies = [] # 使用闭包捕获cookies列表 def capture_cookies(cookie): print(cookie) cookies.append({ 'name': cookie.name().data().decode(), 'value': cookie.value().data().decode(), 'domain': cookie.domain(), 'path': cookie.path(), 'expirationDate': cookie.expirationDate().toSecsSinceEpoch() if cookie.expirationDate().isValid() else None }) # 连接信号捕获Cookie cookie_store.cookieAdded.connect(capture_cookies) # 设置一个定时器来等待Cookie收集完成 QTimer.singleShot(1000, lambda: self.finalize_account_creation(account_name, cookies, cookie_store)) # 提示用户登录 self.browser.load(QUrl("https://passport.bilibili.com/login")) self.status_bar.showMessage("请在浏览器中登录B站账号...", 5000) def finalize_account_creation(self, account_name, cookies, cookie_store): """完成账号创建过程""" # 断开信号连接 cookie_store.cookieAdded.disconnect() print(cookies) # 过滤B站相关Cookie bili_cookies = [c for c in cookies if 'bilibili' in c['domain']] print(bili_cookies) if not bili_cookies: QMessageBox.warning(self, "添加失败", "未检测到有效的B站Cookie") return # 保存账号 if self.account_manager.add_account(account_name, bili_cookies): self.load_accounts() self.account_name_input.clear() self.status_bar.showMessage(f"账号 '{account_name}' 添加成功", 3000) else: QMessageBox.warning(self, "添加失败", "账号名称已存在") def delete_account(self): """删除选中账号""" current_item = self.account_list.currentItem() if not current_item: return account_id = int(current_item.text().split("ID:")[1].strip(")")) self.account_manager.delete_account(account_id) self.load_accounts() self.status_bar.showMessage("账号已删除", 3000) def switch_account(self, item): """切换到选中的账号""" account_id = int(item.text().split("ID:")[1].strip(")")) accounts = self.account_manager.get_accounts() account = next((a for a in accounts if a['id'] == account_id), None) if account: self.apply_cookies(account['cookies']) self.browser.load(QUrl("https://www.bilibili.com")) self.status_bar.showMessage(f"已切换到账号: {account['name']}", 3000) def apply_cookies(self, cookies): """应用Cookie到浏览器""" profile = QWebEngineProfile.defaultProfile() cookie_store = profile.cookieStore() cookie_store.deleteAllCookies() # 清除现有Cookie for cookie_data in cookies: cookie = QNetworkCookie() cookie.setName(cookie_data['name'].encode()) cookie.setValue(cookie_data['value'].encode()) cookie.setDomain(cookie_data['domain']) cookie.setPath(cookie_data['path']) if cookie_data['expirationDate']: cookie.setExpirationDate(cookie_data['expirationDate']) cookie_store.setCookie(cookie) def check_account_status(self): """检查选中账号的状态""" current_item = self.account_list.currentItem() if not current_item: return account_id = int(current_item.text().split("ID:")[1].strip(")")) accounts = self.account_manager.get_accounts() account = next((a for a in accounts if a['id'] == account_id), None) if account: # 使用requests验证Cookie有效性 session = requests.Session() for cookie in account['cookies']: session.cookies.set( cookie['name'], cookie['value'], domain=cookie['domain'], path=cookie['path'] ) try: response = session.get("https://api.bilibili.com/x/web-interface/nav") data = response.json() if data['code'] == 0: uname = data['data']['uname'] self.status_bar.showMessage(f"账号有效: {uname}", 5000) else: self.status_bar.showMessage("账号已失效,请重新登录", 5000) except Exception as e: self.status_bar.showMessage(f"检测失败: {str(e)}", 5000) def navigate_to_url(self): """导航到输入的URL""" url = self.url_bar.text().strip() if not url.startswith(('http://', 'https://')): url = 'https://' + url self.browser.load(QUrl(url)) def update_url_bar(self, q): """更新URL地址栏""" self.url_bar.setText(q.toString()) def go_home(self): """返回B站首页""" self.browser.load(QUrl("https://www.bilibili.com")) def refresh_page(self): """刷新当前页面""" self.browser.reload() if __name__ == "__main__": app = QApplication(sys.argv) browser = BilibiliBrowser() browser.show() sys.exit(app.exec_()) 获取不到cookie请帮我检查修改并且完整返回
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值