一个输入网址就可显示网站安全性及网站主要内容的含GUI的Python小程序

1.一些杂七杂八的引入

上次发了一个类似爬虫,可以自动下载网页图片的python小程序(详见一个自动下载网页图片的python小程序
居然入选了《Python领域内容榜的33名》!
在这里插入图片描述
于是……
我又做了个Python小程序,用来显示网站安全性及网站主要内容的含GUI的Python小程序……

2.实现

2.1 显示网站安全性

好吧,你猜对了,这个安全性就只是可以判断网站用的是HTTP协议还是HTPS协议而已~
什么?你说这有点鸡肋?
这本来就很鸡肋~

不过……
不会还有人连HTTP协议和HTTPS协议的区别都不知道吧?
好吧,在做这个程序之前我也不知道……

且听我细细道来~

HTTP协议
HTTP全称Hypertext Transfer Protocol,是一种基于文本的协议,用于在Web浏览器和Web服务器之间传输数据。HTTP传输的数据是明文的,容易被攻击者截取和窃听。因此,HTTP不提供加密和数据完整性验证的保护,存在安全风险。通常,HTTP用于传输不敏感的数据,例如公开的网页内容或无需保密的信息。

HTTPS协议
HTTPS全称Hypertext Transfer Protocol Secure,是基于HTTP的安全版本。与HTTP相比,HTTPS通过使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议进行加密和身份验证,提供了更高的安全性。HTTPS的数据传输是加密的,使得中间人无法窃听或篡改传输的数据。HTTPS常用于传输敏感信息,例如信用卡信息、登录凭证等。

要注意的是,使用HTTPS需要服务器拥有数字证书,证书由经过验证的认证机构颁发,用于验证服务器的身份。只有在客户端和服务器之间建立了有效的证书握手,并且证书是受信任的,浏览器才会显示连接是安全的。因此,HTTPS不仅提供了数据的机密性,还提供了对服务器身份的验证。
(关于证书握手什么的,下次有空再讲~)

2.2 安装所需python包

既然都涉及到HTTP和HTTPS了,requests当然不能忘,还要用beautifulsoup库解析网页内容,既然是含GUI的,自然也少不了tkiner库,但是只要是按照我的教程安装Python的,链接:Python安装教程

2.2.1 requests包

安装步骤:
1.按下Win+R,打开“运行”对话框
在这里插入图片描述
2.输入“cmd”
在这里插入图片描述
3.单击“确定”,进入cmd命令提示符,输入以下内容:

pip3 install requests#这个是python版本是3点几的同学
pip install requests#这个是python版本是其他的同学

在这里插入图片描述

2.2.1 beautifulsoup包

安装步骤:
1.按下Win+R,打开“运行”对话框
在这里插入图片描述
2.输入“cmd”
在这里插入图片描述
3.单击“确定”,进入cmd命令提示符,输入以下内容:

pip3 install beautifulsoup4#这个是python版本是3点几的同学
pip install beautifulsoup4#这个是python版本是其他的同学

在这里插入图片描述

3.源码展示

为了方便大家理解,这次在源码上加了注释,不会像上次那样让人一头雾水了:

import requests
from bs4 import BeautifulSoup
import tkinter as tk

def check_website():
    url = entry.get()  # 获取输入的网址

    try:
        response = requests.get(url)  # 发送GET请求获取网页内容
        response.raise_for_status()  # 检查是否发生错误

        # 使用BeautifulSoup解析网页内容
        soup = BeautifulSoup(response.content, 'html.parser')

        # 输出网站安全性信息(HTTPS or HTTP)
        if response.url.startswith('https://'):
            result_text.set("网站使用 HTTPS 安全连接")
        else:
            result_text.set("网站使用 HTTP 连接,不安全")

        # 输出页面标题
        title = soup.title.string.strip()
        info_text.set(f"页面标题:{title}\n")

        # 输出页面描述
        description = soup.find('meta', attrs={'name': 'description'})
        if description:
            info_text.set(info_text.get() + f"\n页面描述:\n{description['content']}")
        else:
            info_text.set(info_text.get() + "\n无页面描述")

        # 输出页面关键词
        keywords = soup.find('meta', attrs={'name': 'keywords'})
        if keywords:
            info_text.set(info_text.get() + f"\n\n页面关键词:\n{keywords['content']}")
        else:
            info_text.set(info_text.get() + "\n\n无页面关键词")

        # 清空文本框内容并滚动到顶部
        text_box.delete("1.0", tk.END)
        text_box.yview(tk.MOVETO, 0.0)

        # 插入页面信息到文本框
        text_box.insert(tk.END, info_text.get())

    except requests.exceptions.RequestException as e:
        result_text.set("发生错误,请检查网址或网络连接")
        info_text.set("")  # 清空页面信息
        text_box.delete("1.0", tk.END)

# 创建GUI窗口
window = tk.Tk()
window.title("网址安全性和页面信息检查")
window.geometry("400x300")

# 创建网址输入框和按钮
entry = tk.Entry(window, width=50)
entry.pack(pady=10)

button = tk.Button(window, text="检查", command=check_website)
button.pack()

# 创建结果和页面信息显示标签
result_text = tk.StringVar()
result_label = tk.Label(window, textvariable=result_text)
result_label.pack(pady=10)

info_text = tk.StringVar()

# 创建滚动条和文本框
scrollbar = tk.Scrollbar(window)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

text_box = tk.Text(window, wrap=tk.WORD, yscrollcommand=scrollbar.set)
text_box.pack(expand=True, fill=tk.BOTH)

# 配置滚动条与文本框的关联
scrollbar.config(command=text_box.yview)

# 启动GUI主循环
window.mainloop()

4.效果展示

输入网址就可显示网站安全性及网站主要内容的小程序的演示

<think>我们计划开发一个用于调试RJ45网线的GUI程序,类似于串口调试助手,但针对以太网通信。以下为设计思路: ### 核心功能需求 1. **基础网络通信** - 支持TCP/UDP协议 - 可配置目标IP和端口 - 支持服务端/客户端模式切换 2. **数据收发功能** - 十六进制/ASCII格式发送与显示 - 自动发送(周期发送) - 发送历史记录 3. **数据解析辅助** - 支持常见协议解析(如Modbus、自定义协议) - 数据包时间戳记录 4. **界面设计** - 简洁的发送区/接收区布局 - 连接状态指示 - 日志记录功能 ### 技术选型 - **GUI框架**:PyQt5(功能全面,跨平台) - **网络库**:Python标准库(`socket`) - **多线程**:`threading`模块(防止界面卡顿) - **数据解析**:`struct`模块(二进制数据解析) ### 代码结构设计 ```lua MainWindow ├── 网络配置区(协议选择、IP、端口、连接按钮) ├── 数据发送区(发送框、格式选择、发送按钮) ├── 数据接收区(显示框、格式切换、清除按钮) ├── 日志区(连接状态、操作记录) └── 后台线程 ├── 网络监听线程 └── 数据发送线程 ``` ### 关键代码实现(PyQt5框架) ```python import sys import socket import threading from PyQt5.QtWidgets import * from PyQt5.QtCore import pyqtSignal, QObject class NetCommThread(QObject): # 自定义信号(用于跨线程更新UI) recv_signal = pyqtSignal(str) # 接收数据信号 status_signal = pyqtSignal(str, bool) # 状态信号(消息,是否连接) def __init__(self, ip, port, protocol='TCP'): super().__init__() self.ip = ip self.port = port self.protocol = protocol self.socket = None self.running = False def connect(self): try: if self.protocol == 'TCP': self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.ip, self.port)) else: # UDP self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.running = True self.status_signal.emit(f"已连接至{self.ip}:{self.port}", True) # 启动接收线程 threading.Thread(target=self.recv_loop, daemon=True).start() except Exception as e: self.status_signal.emit(f"连接失败: {str(e)}", False) def recv_loop(self): while self.running: try: if self.protocol == 'TCP': data = self.socket.recv(4096) else: # UDP data, _ = self.socket.recvfrom(4096) if data: self.recv_signal.emit(data.hex(' ')) # 以十六进制显示 except: break def send_data(self, data_bytes): if not self.socket: return try: if self.protocol == 'TCP': self.socket.sendall(data_bytes) else: self.socket.sendto(data_bytes, (self.ip, self.port)) except Exception as e: self.status_signal.emit(f"发送失败: {str(e)}", False) def disconnect(self): self.running = False if self.socket: self.socket.close() self.status_signal.emit("已断开连接", False) class MainWindow(QMainWindow): def __init__(self): super().__init__() # 界面初始化(省略布局代码) self.net_thread = None def on_connect_clicked(self): ip = self.ip_edit.text() port = int(self.port_edit.text()) protocol = 'TCP' if self.protocol_combo.currentText() == 'TCP' else 'UDP' self.net_thread = NetCommThread(ip, port, protocol) self.net_thread.recv_signal.connect(self.on_recv_data) self.net_thread.status_signal.connect(self.on_status_change) self.net_thread.connect() def on_send_clicked(self): text = self.send_edit.text() if self.hex_send_check.isChecked(): # 处理十六进制输入(如"01 A1 FF") data = bytes.fromhex(text.replace(' ', '')) else: data = text.encode() if self.net_thread: self.net_thread.send_data(data) # 其他回调函数... ``` ### 功能扩展建议 1. **协议解析器**:添加下拉菜单选择预置协议(如Modbus),接收数据时自动解析[^1] 2. **数据图表化**:对连续数据(如传感器数值)用Matplotlib实时绘图 3. **脚本支持**:允许加载Python脚本处理数据(如引用[^2]中的子进程调用思路) ### 注意事项 - **线程安全**:所有UI更新通过信号/槽机制进行 - **资源释放**:窗口关闭时确保断开连接 - **错误处理**:网络异常时提供明确提示 ### 最终实现效果 用户将获得一个类似下图的工具: ``` +---------------------------------------+ | [TCP] IP: [192.168.1.100] Port:[502] | | [连接] [断开] | +---------------------------------------+ | 发送区(HEX) [01 03 00 00 00 01] [发送]| | 自动发送间隔 [1000]ms [ ]启用 | +---------------------------------------+ | 接收区(HEX) | | 2023-01-01 12:00:01 收到: 01 03 02 10| | 2023-01-01 12:00:02 发送: 01 03 ... | +---------------------------------------+ | 状态栏: 已连接 | +---------------------------------------+ ``` 此工具可直接用于调试基于TCP/UDP的RJ45设备(如PLC、智能仪表),结合协议解析可快速验证设备通信。 §§相关问题§§ 1. 如何用Python解析Modbus TCP协议的数据包? 2. 在PyQt中如何实现多线程安全的日志记录? 3. 网络调试工具如何支持SSL/TLS加密通信? </think> # Python RJ45网线调试助手开发指南 我将设计一个功能完整的RJ45网线调试助手,类似于串口调试工具,但针对以太网通信。这个工具将支持TCP/UDP协议,提供直观的GUI界面。 ## 设计思路与功能规划 ### 核心功能 - **基本网络通信**:支持TCP客户端/服务器和UDP模式 - **数据收发**:十六进制/ASCII格式显示和发送 - **协议解析**:支持常见工业协议(如Modbus) - **自动化工具**:周期性发送和脚本支持 ### 界面设计 ``` +-------------------------------+ | 网络设置 | | [TCP] [UDP] [Server] [Client] | | IP: ________ Port: ______ | | [连接] [断开] | +-------------------------------+ | 发送区 (HEX/ASCII) | | [___________________________] | | [发送] [自动发送] [清空] | +-------------------------------+ | 接收区 (HEX/ASCII) | | [接收显示区域...] | | [清空] [保存日志] | +-------------------------------+ | 状态栏: 已连接/未连接 | +-------------------------------+ ``` ## 完整代码实现 ```python import sys import socket import threading import time from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLineEdit, QPushButton, QTextEdit, QComboBox, QCheckBox, QLabel, QMessageBox ) from PyQt5.QtCore import QTimer class RJ45Debugger(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("RJ45网络调试助手 v1.0") self.setGeometry(300, 300, 800, 600) # 网络参数 self.socket = None self.client_socket = None self.is_connected = False self.receive_thread = None self.init_ui() def init_ui(self): main_widget = QWidget() main_layout = QVBoxLayout() # 网络设置区域 net_group = QGroupBox("网络设置") net_layout = QHBoxLayout() self.protocol_combo = QComboBox() self.protocol_combo.addItems(["TCP Client", "TCP Server", "UDP"]) self.ip_input = QLineEdit("127.0.0.1") self.port_input = QLineEdit("502") self.connect_btn = QPushButton("连接") self.connect_btn.clicked.connect(self.toggle_connection) net_layout.addWidget(QLabel("协议:")) net_layout.addWidget(self.protocol_combo) net_layout.addWidget(QLabel("IP:")) net_layout.addWidget(self.ip_input) net_layout.addWidget(QLabel("端口:")) net_layout.addWidget(self.port_input) net_layout.addWidget(self.connect_btn) net_layout.addStretch() net_group.setLayout(net_layout) # 发送区域 send_group = QGroupBox("发送数据") send_layout = QVBoxLayout() self.send_data_input = QLineEdit() self.hex_send_check = QCheckBox("HEX发送") send_btn_layout = QHBoxLayout() self.send_btn = QPushButton("发送") self.send_btn.clicked.connect(self.send_data) self.auto_send_check = QCheckBox("自动发送") self.auto_send_check.stateChanged.connect(self.toggle_auto_send) self.auto_send_interval = QLineEdit("1000") self.auto_send_interval.setMaximumWidth(80) send_btn_layout.addWidget(self.send_btn) send_btn_layout.addWidget(self.auto_send_check) send_btn_layout.addWidget(QLabel("间隔(ms):")) send_btn_layout.addWidget(self.auto_send_interval) send_btn_layout.addStretch() send_layout.addWidget(self.send_data_input) send_layout.addLayout(send_btn_layout) send_group.setLayout(send_layout) # 接收区域 recv_group = QGroupBox("接收数据") recv_layout = QVBoxLayout() self.recv_data_display = QTextEdit() self.recv_data_display.setReadOnly(True) recv_btn_layout = QHBoxLayout() self.clear_recv_btn = QPushButton("清空接收区") self.clear_recv_btn.clicked.connect(lambda: self.recv_data_display.clear()) self.hex_display_check = QCheckBox("HEX显示") self.hex_display_check.stateChanged.connect(self.toggle_hex_display) self.save_log_btn = QPushButton("保存日志") recv_btn_layout.addWidget(self.clear_recv_btn) recv_btn_layout.addWidget(self.hex_display_check) recv_btn_layout.addWidget(self.save_log_btn) recv_btn_layout.addStretch() recv_layout.addWidget(self.recv_data_display) recv_layout.addLayout(recv_btn_layout) recv_group.setLayout(recv_layout) # 状态栏 self.status_bar = self.statusBar() self.status_label = QLabel("状态: 未连接") self.status_bar.addWidget(self.status_label) # 组装主界面 main_layout.addWidget(net_group) main_layout.addWidget(send_group) main_layout.addWidget(recv_group) main_widget.setLayout(main_layout) self.setCentralWidget(main_widget) # 自动发送定时器 self.auto_send_timer = QTimer() self.auto_send_timer.timeout.connect(self.send_data) def toggle_connection(self): if self.is_connected: self.disconnect() else: self.connect() def connect(self): protocol = self.protocol_combo.currentText() ip = self.ip_input.text() port = int(self.port_input.text()) try: if "TCP Client" in protocol: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((ip, port)) self.is_connected = True self.start_receive_thread() elif "TCP Server" in protocol: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((ip, port)) self.socket.listen(1) self.is_connected = True threading.Thread(target=self.accept_client, daemon=True).start() elif "UDP" in protocol: self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.socket.bind((ip, port)) self.is_connected = True self.start_receive_thread() self.update_ui_connected() except Exception as e: QMessageBox.critical(self, "连接错误", f"连接失败: {str(e)}") def accept_client(self): self.client_socket, addr = self.socket.accept() self.status_label.setText(f"状态: 已连接 ({addr[0]}:{addr[1]})") self.start_receive_thread() def start_receive_thread(self): self.receive_thread = threading.Thread(target=self.receive_data, daemon=True) self.receive_thread.start() def receive_data(self): while self.is_connected: try: if self.protocol_combo.currentText() == "TCP Server": data = self.client_socket.recv(1024) else: data = self.socket.recv(1024) if not data: break display_text = self.format_received_data(data) self.recv_data_display.append(display_text) except Exception as e: if self.is_connected: # 仅在连接状态显示错误 self.recv_data_display.append(f"接收错误: {str(e)}") break def format_received_data(self, data): if self.hex_display_check.isChecked(): return ' '.join(f'{b:02X}' for b in data) else: try: return data.decode('utf-8') except: return ' '.join(f'{b:02X}' for b in data) def send_data(self): if not self.is_connected: QMessageBox.warning(self, "发送错误", "未建立连接") return data_str = self.send_data_input.text() if not data_str: return try: if self.hex_send_check.isChecked(): # 处理十六进制输入(去除空格) data_bytes = bytes.fromhex(data_str.replace(' ', '')) else: data_bytes = data_str.encode('utf-8') protocol = self.protocol_combo.currentText() if "TCP Client" in protocol: self.socket.sendall(data_bytes) elif "TCP Server" in protocol and self.client_socket: self.client_socket.sendall(data_bytes) elif "UDP" in protocol: ip = self.ip_input.text() port = int(self.port_input.text()) self.socket.sendto(data_bytes, (ip, port)) # 在接收区显示发送的数据(可选) display_text = f"发送: {self.format_received_data(data_bytes)}" self.recv_data_display.append(display_text) except Exception as e: self.recv_data_display.append(f"发送错误: {str(e)}") def toggle_auto_send(self, state): if state: try: interval = int(self.auto_send_interval.text()) self.auto_send_timer.start(interval) except ValueError: QMessageBox.warning(self, "参数错误", "请输入有效的毫秒数") self.auto_send_check.setChecked(False) else: self.auto_send_timer.stop() def toggle_hex_display(self, state): # 当切换显示格式时清空显示区 self.recv_data_display.clear() def disconnect(self): self.is_connected = False self.auto_send_timer.stop() self.auto_send_check.setChecked(False) if self.socket: try: self.socket.close() except: pass if self.client_socket: try: self.client_socket.close() except: pass self.update_ui_disconnected() def update_ui_connected(self): self.connect_btn.setText("断开") self.status_label.setText("状态: 已连接") self.protocol_combo.setEnabled(False) self.ip_input.setEnabled(False) self.port_input.setEnabled(False) def update_ui_disconnected(self): self.connect_btn.setText("连接") self.status_label.setText("状态: 未连接") self.protocol_combo.setEnabled(True) self.ip_input.setEnabled(True) self.port_input.setEnabled(True) def closeEvent(self, event): self.disconnect() event.accept() if __name__ == "__main__": app = QApplication(sys.argv) window = RJ45Debugger() window.show() sys.exit(app.exec_()) ``` ## 功能扩展建议 1. **协议解析器**(参考引用) ```python # 添加在接收数据处理部分 def parse_modbus(self, data): """解析Modbus协议数据""" if len(data) < 8: # Modbus TCP头部最小长度 return "无效的Modbus数据" transaction_id = int.from_bytes(data[0:2], 'big') protocol_id = int.from_bytes(data[2:4], 'big') length = int.from_bytes(data[4:6], 'big') unit_id = data[6] function_code = data[7] result = (f"Modbus解析:\n" f"事务ID: {transaction_id}\n" f"协议ID: {protocol_id}\n" f"长度: {length}\n" f"单元ID: {unit_id}\n" f"功能码: {function_code}") # 添加更多解析逻辑... return result ``` 2. **脚本自动化**(参考引用[^2]) ```python # 添加脚本执行按钮和功能 def execute_script(self): """执行自定义调试脚本""" script = """ # 示例脚本:发送Modbus读取命令 def send_read_command(address, count): # 构造Modbus读取命令 transaction_id = 1 unit_id = 1 function_code = 3 # 读取保持寄存器 msg = (transaction_id.to_bytes(2, 'big') + b'\x00\x00' + b'\x00\x06' + unit_id.to_bytes(1, 'big') + function_code.to_bytes(1, 'big') + address.to_bytes(2, 'big') + count.to_bytes(2, 'big')) return msg # 发送读取寄存器0-10的命令 return send_read_command(0, 10) """ try: # 在安全环境中执行脚本 locals_dict = {} exec(script, globals(), locals_dict) command = locals_dict.get('send_read_command', lambda: b'')(0, 10) self.send_data_bytes(command) except Exception as e: self.recv_data_display.append(f"脚本错误: {str(e)}") ``` 3. **高级功能** - 添加数据图表展示(使用Matplotlib) - 实现协议模拟器(模拟设备响应) - 添加SSL/TLS支持 - 实现历史命令保存和加载 ## 使用说明 1. 选择网络协议(TCP客户端/服务器或UDP) 2. 输入目标IP和端口 3. 点击"连接"建立网络连接 4. 在发送区输入数据(支持HEX和ASCII格式) 5. 接收区显示接收到的数据 6. 使用"自动发送"功能进行周期性测试 这个工具特别适合调试工业设备(如PLC)、网络服务和物联网设备,可以直观地查看原始网络数据流,并支持协议解析[^1]和自动化脚本[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值