用Python爬虫+tkinter给NOJ题库做个本地备份工具(附完整源码)
2026/4/6 15:09:28 网站建设 项目流程
Python爬虫实战NOJ题库本地备份工具开发指南期末考试临近许多同学都在为整理NOJ平台的编程题目而烦恼——无法直接复制题目内容、需要手动截图保存、中英文混杂难以分离。本文将手把手教你用Python打造一个专属的NOJ题库备份工具只需点击几下就能将题目完整导出为格式规范的Word文档。1. 工具设计与技术选型这个工具的核心目标是解决三个实际问题题目内容无法复制、手动整理效率低下、中英文混杂难以处理。我们选择Python作为开发语言因为它拥有丰富的库支持和较低的学习门槛。技术栈组成爬虫部分requests处理网络请求 BeautifulSoup解析HTML文档生成python-docx创建格式化的Word文档用户界面tkinter构建简单易用的GUI辅助工具re处理正则匹配 io管理二进制流# 基础依赖库导入 import tkinter as tk from tkinter import messagebox import requests from bs4 import BeautifulSoup from docx import Document import re from io import BytesIO提示开发前请确保已安装所需库可通过pip install requests beautifulsoup4 python-docx一键安装2. 爬虫核心实现细节2.1 登录认证处理NOJ平台采用传统的表单登录我们需要模拟浏览器发送POST请求。关键点在于正确处理会话Session以维持登录状态。def login(username, password): session requests.Session() login_data { username: username, password: password } login_url http://10.12.13.248/cpbox/ response session.post(login_url, datalogin_data) # 验证登录是否成功 if response.status_code 200: return session else: raise Exception(登录失败请检查账号密码)2.2 题目页面抓取策略NOJ的题目内容嵌套在iframe中直接请求无法获取。通过分析发现题目URL有固定规律从主页面提取所有题目的基础链接补全URL前缀形成完整地址逐个请求题目页面获取内容def get_problem_links(session): main_page session.get(http://10.12.13.248/cpbox/cpNPUOJ.aspx#) soup BeautifulSoup(main_page.text, html.parser) links soup.find_all(a, idcpIPPSFReader) problem_urls [] for link in links: onclick link.get(onclick) url_part re.findall(rurl:(.*?), onclick)[0] full_url fhttp://10.12.13.248/cpbox/{url_part} problem_urls.append(full_url) return problem_urls2.3 内容解析与提取每个题目页面包含多个关键部分我们需要准确定位并提取元素ID对应内容处理方式lblIPPDFtitle题目名称直接提取lblIPPDFdescription题目描述中英文分离lblIPPDFiutput输入说明可选提取lblIPPDFoutput输出说明可选提取img题目图片下载嵌入def parse_problem_page(html, need_englishFalse): soup BeautifulSoup(html, html.parser) data { title: soup.find(span, idlblIPPDFtitle).text.strip(), description: process_text(soup.find(span, idlblIPPDFdescription).text, need_english), image: get_image(soup) if soup.find(img) else None } return data3. 中英文分离的智能处理题目内容常混合中英文我们开发了基于标点定位的分离算法从右向左查找最后一个中文标点。或以此为界分割字符串保留需要的语言部分def separate_chinese_english(text, keep_englishFalse): # 查找最后一个中文句号 last_ch_punct max(text.rfind(。), text.rfind()) if last_ch_punct -1: return text if keep_english else if keep_english: return text[last_ch_punct1:].strip() else: return text[:last_ch_punct1].strip()注意此方法对大多数题目有效但特殊格式可能需要额外处理4. 图形界面设计与实现使用tkinter构建用户友好的操作界面包含以下核心组件账号密码输入框用于NOJ平台登录选项复选框控制是否包含英文描述和样例操作按钮触发爬取和导出过程状态提示显示操作进度和结果def create_gui(): root tk.Tk() root.title(NOJ题库备份工具) # 账号密码区域 tk.Label(root, textNOJ账号:).grid(row0, column0) username_entry tk.Entry(root) username_entry.grid(row0, column1) tk.Label(root, text密码:).grid(row1, column0) password_entry tk.Entry(root, show*) password_entry.grid(row1, column1) # 选项区域 include_english tk.BooleanVar() tk.Checkbutton(root, text包含英文描述, variableinclude_english).grid(row2, columnspan2) include_samples tk.BooleanVar() tk.Checkbutton(root, text包含输入输出样例, variableinclude_samples).grid(row3, columnspan2) # 操作按钮 tk.Button(root, text开始导出, commandlambda: start_export( username_entry.get(), password_entry.get(), include_english.get(), include_samples.get() )).grid(row4, columnspan2) root.mainloop()5. Word文档生成技巧使用python-docx库创建专业排版的文档设置不同级别的标题区分题目合理控制段落间距提升可读性自动调整图片大小适应页面添加页眉页脚等辅助信息def create_word_document(problems, filenameNOJ题目备份.docx): doc Document() # 添加文档标题 doc.add_heading(NOJ题目备份, 0) # 逐个添加题目 for i, problem in enumerate(problems, 1): doc.add_heading(f题目{i}: {problem[title]}, level2) doc.add_paragraph(题目描述: problem[description]) if problem.get(image): try: doc.add_picture(problem[image], widthdocx.shared.Inches(4)) except: doc.add_paragraph([图片加载失败]) doc.save(filename) return filename6. 完整工作流程整合将各个模块串联形成完整解决方案用户通过GUI输入凭证和选项程序登录NOJ获取有效会话爬取所有题目链接逐个解析题目内容根据选项处理中英文生成格式化的Word文档提示用户操作完成def start_export(username, password, need_english, need_samples): try: # 登录获取会话 session login(username, password) # 获取题目列表 problem_urls get_problem_links(session) # 逐个爬取题目 problems [] for url in problem_urls: response session.get(url) problem_data parse_problem_page(response.text, need_english) problems.append(problem_data) # 生成文档 output_file create_word_document(problems) messagebox.showinfo(完成, f题目已成功导出到 {output_file}) except Exception as e: messagebox.showerror(错误, f导出失败: {str(e)})7. 实际应用中的优化建议异常处理增强网络波动、页面变更等情况需要更健壮的处理进度反馈添加进度条显示爬取进度图片处理自动调整多张图片的尺寸和位置格式定制允许用户选择不同的文档样式模板批量操作支持选择特定题目而非全部导出在开发过程中最耗时的部分是iframe内容的获取和中文分离算法的调试。通过仔细分析页面结构最终找到了直接获取题目URL的巧妙方法。对于有类似需求的开发者建议先充分研究目标网站的结构再设计针对性的爬取策略。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询