如何将SQLite中的Brave浏览器历史数据发送至服务器并实现账户管理
家长监控系统实现指导
一、Ubuntu Server端搭建方案
1. 技术栈选择
用轻量的Flask框架快速搭建后端,搭配SQLite存储数据,JWT做身份认证。先安装依赖:
sudo apt update && sudo apt install python3-pip pip3 install flask flask-sqlalchemy flask-jwt-extended requests
2. 数据库表设计
创建两个核心表:
- 用户表(users):存储家长/孩子账户信息
- 字段:
id(主键)、username(唯一)、password_hash(加密密码)、role(parent/child)、parent_id(孩子关联的家长ID,可为空)
- 字段:
- 浏览历史表(browser_history):存储孩子的上网记录
- 字段:
id(主键)、child_id(关联用户表孩子ID)、url、title、visit_time、created_at(上传时间)
- 字段:
3. 核心API接口实现
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity from werkzeug.security import generate_password_hash, check_password_hash import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///monitor.db' app.config['JWT_SECRET_KEY'] = 'your-random-secret-key' # 替换为随机生成的密钥 db = SQLAlchemy(app) jwt = JWTManager(app) # 模型定义 class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password_hash = db.Column(db.String(120), nullable=False) role = db.Column(db.String(20), nullable=False) parent_id = db.Column(db.Integer, db.ForeignKey('user.id')) class BrowserHistory(db.Model): id = db.Column(db.Integer, primary_key=True) child_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) url = db.Column(db.String(500), nullable=False) title = db.Column(db.String(500)) visit_time = db.Column(db.DateTime, nullable=False) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) # 注册接口 @app.route('/api/register', methods=['POST']) def register(): data = request.get_json() if User.query.filter_by(username=data['username']).first(): return jsonify({'msg': '用户名已存在'}), 400 password_hash = generate_password_hash(data['password']) new_user = User( username=data['username'], password_hash=password_hash, role=data['role'], parent_id=data.get('parent_id') ) db.session.add(new_user) db.session.commit() return jsonify({'msg': '注册成功'}), 201 # 登录接口 @app.route('/api/login', methods=['POST']) def login(): data = request.get_json() user = User.query.filter_by(username=data['username']).first() if not user or not check_password_hash(user.password_hash, data['password']): return jsonify({'msg': '用户名或密码错误'}), 401 access_token = create_access_token(identity={'id': user.id, 'role': user.role}) return jsonify(access_token=access_token), 200 # 上传浏览历史接口 @app.route('/api/history/upload', methods=['POST']) @jwt_required() def upload_history(): current_user = get_jwt_identity() if current_user['role'] != 'child': return jsonify({'msg': '仅孩子账户可上传数据'}), 403 data = request.get_json() for item in data['history']: history_item = BrowserHistory( child_id=current_user['id'], url=item['url'], title=item['title'], visit_time=datetime.datetime.fromisoformat(item['visit_time']) ) db.session.add(history_item) db.session.commit() return jsonify({'msg': '数据上传成功'}), 200 # 获取孩子历史数据接口(家长用) @app.route('/api/history/get', methods=['GET']) @jwt_required() def get_history(): current_user = get_jwt_identity() if current_user['role'] != 'parent': return jsonify({'msg': '仅家长账户可查看数据'}), 403 child_id = request.args.get('child_id') # 验证孩子是否属于当前家长 child = User.query.filter_by(id=child_id, parent_id=current_user['id']).first() if not child: return jsonify({'msg': '无权访问该孩子数据'}), 403 history = BrowserHistory.query.filter_by(child_id=child_id).order_by(BrowserHistory.visit_time.desc()).all() result = [{ 'url': item.url, 'title': item.title, 'visit_time': item.visit_time.isoformat() } for item in history] return jsonify(history=result), 200 if __name__ == '__main__': with app.app_context(): db.create_all() app.run(host='0.0.0.0', port=5000)
二、客户端代码修改(发送数据到服务器)
修改你的Brave历史读取脚本,替换打印逻辑为上传数据:
import sqlite3 import os import requests import json from datetime import datetime # 服务器配置 SERVER_URL = "http://你的Ubuntu服务器IP:5000" CHILD_USERNAME = "孩子账户用户名" CHILD_PASSWORD = "孩子账户密码" def get_access_token(): """获取JWT认证token""" login_data = { "username": CHILD_USERNAME, "password": CHILD_PASSWORD } try: response = requests.post(f"{SERVER_URL}/api/login", json=login_data) response.raise_for_status() return response.json()['access_token'] except Exception as e: print(f"登录失败: {str(e)}") return None def upload_history(history_data, token): """上传浏览历史到服务器""" headers = {"Authorization": f"Bearer {token}"} payload = {"history": history_data} try: response = requests.post(f"{SERVER_URL}/api/history/upload", json=payload, headers=headers) response.raise_for_status() print("数据上传成功") except Exception as e: print(f"上传失败: {str(e)}") def main(): try: # 获取Brave历史路径(适配macOS,Windows/Linux需调整路径) home_dir = os.path.expanduser("~") history_path = os.path.join(home_dir, "Library/Application Support/BraveSoftware/Brave-Browser/Default/History") if not os.path.isfile(history_path): raise FileNotFoundError(f"Brave History文件未找到: {history_path}") # 连接数据库并查询历史 con = sqlite3.connect(history_path) con.row_factory = sqlite3.Row # 让查询结果可通过字段名访问 cur = con.cursor() # 查询最近的50条记录(可按需调整数量) cur.execute("SELECT url, title, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 50") history_data = [] for row in cur.fetchall(): # 转换时间格式:Brave的last_visit_time是微秒级时间戳 visit_time = datetime.fromtimestamp(row['last_visit_time'] / 1_000_000) history_data.append({ "url": row['url'], "title": row['title'], "visit_time": visit_time.isoformat() }) con.close() # 获取token并上传数据 token = get_access_token() if token: upload_history(history_data, token) except sqlite3.Error as e: print(f"SQLite错误: {str(e)}") except Exception as e: print(f"错误: {str(e)}") if __name__ == "__main__": main()
客户端注意事项
- 不同系统的Brave历史路径不同:
- Windows:
C:\Users\{用户名}\AppData\Local\BraveSoftware\Brave-Browser\User Data\Default\History - Linux:
~/.config/BraveSoftware/Brave-Browser/Default/History
- Windows:
- 建议把脚本设为定时任务(比如用crontab),定期自动上传数据
三、账户关联与数据展示逻辑
- 账户创建流程:
- 先注册家长账户:调用
/api/register,role设为parent - 再注册孩子账户:调用
/api/register,role设为child,并填写parent_id为对应家长的ID
- 先注册家长账户:调用
- 数据展示:
- 移动端应用通过家长账户登录获取token
- 调用
/api/history/get接口,传入要查看的孩子ID,获取该孩子的浏览历史 - 前端可按时间排序、关键词搜索、统计访问频率等方式展示数据
内容的提问来源于stack exchange,提问作者Lardsonian
相关产品推荐
相关产品推荐

