Python浏览器程序(使用Tkinter)
下面是一个使用Python和Tkinter实现的简单浏览器程序,包含了基本的浏览器功能。
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import tkinter.font as tkfont
from urllib.request import urlopen, Request
from urllib.error import URLError
from urllib.parse import urlparse
import re
import html
import threading
class Browser:
def __init__(self, root):
"""初始化浏览器主窗口"""
self.root = root
self.root.title("Python浏览器") # 设置窗口标题
self.root.geometry("1024x768") # 设置默认窗口大小
# 当前访问的URL
self.current_url = ""
# 历史记录列表
self.history = []
# 当前历史记录索引
self.history_index = -1
self.create_widgets() # 创建界面组件
self.setup_bindings() # 设置事件绑定
def create_widgets(self):
"""创建浏览器界面组件"""
# 创建顶部导航栏框架
nav_frame = ttk.Frame(self.root)
nav_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
# 后退按钮
self.back_button = ttk.Button(nav_frame, text="←", width=3, command=self.go_back)
self.back_button.pack(side=tk.LEFT, padx=2)
# 前进按钮
self.forward_button = ttk.Button(nav_frame, text="→", width=3, command=self.go_forward)
self.forward_button.pack(side=tk.LEFT, padx=2)
# 刷新按钮
self.refresh_button = ttk.Button(nav_frame, text="↻", width=3, command=self.refresh_page)
self.refresh_button.pack(side=tk.LEFT, padx=2)
# 主页按钮
self.home_button = ttk.Button(nav_frame, text="🏠", width=3, command=self.go_home)
self.home_button.pack(side=tk.LEFT, padx=2)
# 地址输入框
self.url_entry = ttk.Entry(nav_frame, width=50)
self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
# 访问按钮
self.go_button = ttk.Button(nav_frame, text="访问", command=self.navigate)
self.go_button.pack(side=tk.LEFT, padx=2)
# 创建浏览器内容显示区域
content_frame = ttk.Frame(self.root)
content_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
# 创建文本区域用于显示网页内容(简化版,实际浏览器应使用更复杂的渲染引擎)
self.content_area = scrolledtext.ScrolledText(
content_frame,
wrap=tk.WORD,
state=tk.DISABLED,
font=tkfont.Font(family="Arial", size=12)
)
self.content_area.pack(fill=tk.BOTH, expand=True)
# 创建状态栏
self.status_bar = ttk.Label(self.root, text="就绪", relief=tk.SUNKEN, anchor=tk.W)
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
def setup_bindings(self):
"""设置事件绑定"""
# 绑定回车键到地址栏
self.url_entry.bind("<Return>", lambda event: self.navigate())
def navigate(self):
"""导航到指定URL"""
url = self.url_entry.get().strip() # 获取地址栏内容并去除首尾空格
# 如果URL没有协议头,自动添加http://
if not re.match(r'^https?://', url, re.IGNORECASE):
url = 'http://' + url
self.current_url = url # 更新当前URL
# 更新地址栏显示
self.url_entry.delete(0, tk.END)
self.url_entry.insert(0, url)
# 添加到历史记录
if not self.history or self.history[-1] != url:
self.history.append(url)
self.history_index = len(self.history) - 1
# 更新按钮状态
self.update_navigation_buttons()
# 在状态栏显示加载状态
self.status_bar.config(text=f"正在加载: {url}")
# 在新线程中加载网页,避免界面冻结
threading.Thread(target=self.load_url, args=(url,), daemon=True).start()
def load_url(self, url):
"""加载URL内容"""
try:
# 设置请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
req = Request(url, headers=headers)
# 打开URL并读取内容
with urlopen(req, timeout=10) as response:
content = response.read().decode('utf-8', errors='replace')
# 在主线程中更新UI
self.root.after(0, self.display_content, content, url)
except Exception as e:
# 显示错误信息
error_msg = f"无法加载页面: {str(e)}"
self.root.after(0, self.show_error, error_msg)
def display_content(self, content, url):
"""显示网页内容(简化版)"""
# 启用文本区域进行编辑
self.content_area.config(state=tk.NORMAL)
self.content_area.delete(1.0, tk.END)
# 提取并显示标题
title_match = re.search(r'<title>(.*?)</title>', content, re.IGNORECASE)
if title_match:
title = html.unescape(title_match.group(1))
self.content_area.insert(tk.END, f"标题: {title}\n\n")
# 提取并显示正文内容(简化处理)
# 移除脚本和样式标签
content = re.sub(r'<script.*?</script>', '', content, flags=re.DOTALL | re.IGNORECASE)
content = re.sub(r'<style.*?</style>', '', content, flags=re.DOTALL | re.IGNORECASE)
# 提取段落文本
paragraphs = re.findall(r'<p.*?>(.*?)</p>', content, re.DOTALL | re.IGNORECASE)
for p in paragraphs:
# 移除HTML标签
text = re.sub(r'<.*?>', '', p)
text = html.unescape(text).strip()
if text:
self.content_area.insert(tk.END, text + "\n\n")
# 禁用文本区域编辑
self.content_area.config(state=tk.DISABLED)
# 更新状态栏
self.status_bar.config(text=f"已加载: {url}")
def show_error(self, error_msg):
"""显示错误信息"""
# 启用文本区域进行编辑
self.content_area.config(state=tk.NORMAL)
self.content_area.delete(1.0, tk.END)
self.content_area.insert(tk.END, f"错误: {error_msg}\n\n请检查URL是否正确,或尝试其他网站。")
# 禁用文本区域编辑
self.content_area.config(state=tk.DISABLED)
# 更新状态栏
self.status_bar.config(text=f"错误: {error_msg}")
def go_back(self):
"""导航到历史记录中的上一个页面"""
if self.history_index > 0:
self.history_index -= 1
url = self.history[self.history_index]
self.url_entry.delete(0, tk.END)
self.url_entry.insert(0, url)
self.navigate()
def go_forward(self):
"""导航到历史记录中的下一个页面"""
if self.history_index < len(self.history) - 1:
self.history_index += 1
url = self.history[self.history_index]
self.url_entry.delete(0, tk.END)
self.url_entry.insert(0, url)
self.navigate()
def refresh_page(self):
"""刷新当前页面"""
if self.current_url:
self.navigate()
def go_home(self):
"""导航到主页(默认为百度)"""
self.url_entry.delete(0, tk.END)
self.url_entry.insert(0, "https://www.baidu.com")
self.navigate()
def update_navigation_buttons(self):
"""更新导航按钮状态"""
# 更新后退按钮状态
if self.history_index > 0:
self.back_button.config(state=tk.NORMAL)
else:
self.back_button.config(state=tk.DISABLED)
# 更新前进按钮状态
if self.history_index < len(self.history) - 1:
self.forward_button.config(state=tk.NORMAL)
else:
self.forward_button.config(state=tk.DISABLED)
def main():
"""主函数"""
# 创建主窗口
root = tk.Tk()
# 创建浏览器实例
browser = Browser(root)
# 默认打开百度首页
browser.url_entry.insert(0, "https://www.baidu.com")
browser.navigate()
# 启动主事件循环
root.mainloop()
if __name__ == "__main__":
main()
功能说明
这个浏览器程序实现了以下功能:
- 导航功能:
· 地址栏输入URL访问网页
· 前进/后退按钮浏览历史记录
· 刷新当前页面
· 主页按钮返回默认首页 - 界面布局:
· 顶部导航栏包含控制按钮和地址栏
· 中部内容区域显示网页内容
· 底部状态栏显示加载状态和信息 - 网页渲染:
· 简化版HTML内容提取和显示
· 提取页面标题和段落内容
· 过滤脚本和样式标签 - 多线程加载:
· 使用多线程加载网页,避免界面冻结
· 加载过程中显示状态信息 - 错误处理:
· 网络错误处理
· URL格式验证和自动补全
使用说明
- 在地址栏输入URL(如:www.baidu.com)
- 按回车或点击"访问"按钮加载页面
- 使用前进/后退按钮浏览历史记录
- 点击刷新按钮重新加载当前页面
- 点击主页按钮返回百度首页
注意:这是一个简化版的浏览器,实际浏览器使用更复杂的渲染引擎(如WebKit/Blink/Gecko),这个程序仅用于演示基本概念。
3578

被折叠的 条评论
为什么被折叠?



