2026春SDU软件创新实训第四周个人工作总结

news2026/4/3 11:45:08
第四周我做的工作总结如下从原始网页爬取科一科四题库书接上期我们找到了两个网页的题库驾照吧https://www.jiazhaoba.com/tiba元贝驾考https://www.ybjk.com/tiku其中的题目是以链表的形式前后存储的。这里我提取的思路是下载一页题目HTML的样例页代码把它作为提示词输入给LLM首先让它分析网页的代码按照不同种类题目单选、多选、判断三类找出我们要提取的题干、选项、解析、图中图片等信息所对应的HTML标签同时给出一个输出的样例模板让它首先通过爬虫技术提取出这些关键信息再将这些信息按照模板结构输出为json格式的文件主体对话如下上图是给定样例网页代码。上图定义了我们期望得到的json结构内容有题干question类型type选项判断题默认两个选项、答案key、解析以及上一页和下一页的链接url主要是方便我们断点重传涉及图片的也要提取img标签保存到对应服务器路径下并且img字段是非空的保存图片结构声明如下单页题目提取完毕后我们期望爬虫脚本能根据next_url的链接值自动跳转到下一题下一个页面直到到达链尾停止页面上没有next标签了。综合上述关键词LLM给出的分析结果如下初步给出的代码如下import os import json import time import random import requests from bs4 import BeautifulSoup from urllib.parse import urljoin # ── 配置项 ──────────────────────────────────────────────── BASE_URL https://www.jiazhaoba.com START_URL https://www.jiazhaoba.com/tiba/1/ OUTPUT_FILE subject4_questions.json IMAGE_DIR subject1_images # 伪装请求头 HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Referer: https://www.jiazhaoba.com/tiba/ } # ── 工具函数 ────────────────────────────────────────────── def ensure_env(): if not os.path.exists(IMAGE_DIR): os.makedirs(IMAGE_DIR) def load_data(): 读取已有数据实现断点续爬 if os.path.exists(OUTPUT_FILE): try: with open(OUTPUT_FILE, r, encodingutf-8) as f: return json.load(f) except: return [] return [] def save_data(data): 保存数据到JSON with open(OUTPUT_FILE, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def download_img(session, img_url, q_index): 下载图片命名格式题号_1.jpg if not img_url: return None full_url urljoin(BASE_URL, img_url) try: ext full_url.split(.)[-1] if . in full_url else jpg filename f{q_index}_1.{ext} filepath os.path.join(IMAGE_DIR, filename) # 避免重复下载 if os.path.exists(filepath): return filepath r session.get(full_url, timeout10) if r.status_code 200: with open(filepath, wb) as f: f.write(r.content) return filepath except Exception as e: print(f [Error] 图片下载失败: {e}) return None # ── 核心爬取逻辑 ────────────────────────────────────────── def scrape(): ensure_env() session requests.Session() session.headers.update(HEADERS) questions load_data() visited_urls {q[url] for q in questions} # 确定起点 current_url START_URL if questions and questions[-1].get(next_url): current_url questions[-1][next_url] print(f[*] 检测到历史记录从断点继续: {current_url}) count len(questions) while current_url: if current_url in visited_urls: print(f[!] 检测到重复URL或环路停止: {current_url}) break print(f\n[{time.strftime(%H:%M:%S)}] 正在爬取第 {count 1} 题: {current_url}) try: resp session.get(current_url, timeout15) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) # --- 1. 提取题干与选项 --- topic_box soup.select_one(.topic-l ul) if not topic_box: print( [Error] 未能找到题目容器可能触发反爬或结构变化) break lis topic_box.find_all(li, recursiveFalse) raw_question lis[0].get_text(stripTrue) # 过滤掉 class 为 answer 的 li提取纯选项 option_items [li.get_text(stripTrue) for li in lis[1:] if answer not in li.get(class, [])] # --- 2. 提取答案与解析 --- answer_tag soup.select_one(.answer strong) key answer_tag.get_text(stripTrue) if answer_tag else analysis_tag soup.select_one(.topic-b.analy-note p) analysis analysis_tag.get_text(stripTrue) if analysis_tag else # --- 3. 提取图片 --- img_tag soup.select_one(.imgorvideo img) img_path None if img_tag: img_path download_img(session, img_tag.get(src), count 1) # --- 4. 判定题目类型 --- # 如果选项包含“正确”“错误”且只有两个判为 judge if len(option_items) 2: q_type judge else: q_type single_choose # --- 5. 获取下一页链接 --- next_url None # 查找“下一题”所在的 a 标签 next_link_tag soup.find(label, string下一题) if next_link_tag: a_tag next_link_tag.find_next_sibling(a) if a_tag: next_url urljoin(BASE_URL, a_tag.get(href)) # 如果上面方法没找到尝试在整个 .preandnext 区域搜寻 if not next_url: for div in soup.select(.preandnext div): if 下一题 in div.get_text(): a div.find(a) if a: next_url urljoin(BASE_URL, a.get(href)) # --- 6. 构造数据并保存 --- item { question: raw_question, type: q_type, img: img_path, options: option_items, key: key, analysis: analysis, url: current_url, next_url: next_url } questions.append(item) visited_urls.add(current_url) save_data(questions) count 1 # Debug 输出 print(f 题干: {raw_question[:30]}...) print(f 类型: {q_type} | 答案: {key} | 图片: {img_path}) print(f 下一题: {next_url}) # 退出条件 if not next_url: print(\n[√] 已到达最后一题爬取结束。) break # 随机延迟保护 delay random.uniform(2.0, 4.0) time.sleep(delay) current_url next_url except Exception as e: print(f [Fatal Error] 爬取中断: {e}) break print(f\n{*30}) print(f统计: 共计获取 {len(questions)} 道题目) print(f结果已保存至: {OUTPUT_FILE}) if __name__ __main__: scrape()正当满心欢喜的使用这个脚本直接提取1000题目时候现实出现了这样的问题与LLM交流后我明白了“爬取”的过程也是需要遵循规则的网站后台的服务器会记录每个IP地址的访问频率如果访问过快就会被视为机器人程序而非真人导致IP被临时封锁无法继续读取。吸取了这个教训我在LLM的建议下加入了预热机制模拟真实人类浏览顺序先到主页再到题目页面还提高了每两题之间的等待时间等待大约4s左右确保符合人类阅读时间防止出发封禁def warmup(session): 先模拟人工浏览几个页面再开始爬题 pages [ (https://www.ybjk.com/, None), (https://www.ybjk.com/tiku/, https://www.ybjk.com/), (https://www.ybjk.com/tiku/kms.htm,https://www.ybjk.com/tiku/), ] print([预热] 模拟人工浏览...) for url, ref in pages: try: r session.get(url, timeout20, proxiesPROXY, headersmake_headers(ref)) print(f {url} → {r.status_code} ({len(r.content)} bytes)) except Exception as e: print(f [预热失败] {url} - {e}) time.sleep(random.uniform(2.0, 4.0)) print([预热完成]\n)在这个过程中还是有意外发生的网站实际的链接顺序有问题中间存在跳跃现象漏掉了几百题针对这个问题我微调了一下代码利用url中编号自增的顺序手动补充上了剩下的几百题经过上面的操作我成功爬取了1309道科目一的题目和1126道科目四的题目基本能够满足搭建一个小型驾考APP的数据量了调研所得大部分APP科一题目量在1700科四在1200。效果预览如下{ question: 路面上的黄色标线是何含义, type: single_choose, img: subject1_images\\948_1.jpg, options: [ A、车行道变多标线, B、路面宽度渐变标线, C、接近障碍物标线, D、施工路段提示线 ], key: B, analysis: 该标志为路面宽度渐变标线。, url: https://www.jiazhaoba.com/tiba/868/, next_url: https://www.jiazhaoba.com/tiba/9264/ }, { question: 夜间行车驾驶人视距变短影响观察同时注意力高度集中易产生疲劳。, type: judge, img: null, options: [ A、正确, B、错误 ], key: A, analysis: 高度集中注意力很费神的久了就会疲倦。, url: https://www.jiazhaoba.com/tiba/893/, next_url: https://www.jiazhaoba.com/tiba/9264/ }, { question: 林某驾车以110公里/小时的速度在城市道路行驶与一辆机动车追尾后弃车逃离被群众拦下。经鉴定事发时林某血液中的酒精浓度为135.8毫克/百毫升。林某的主要违法行为是什么, type: multi_choose, img: null, options: [ A、醉酒驾驶, B、超速驾驶, C、疲劳驾驶, D、肇事逃逸 ], key: ABD, analysis: 根据法律规定和题干信息\n林某的行为\n构成以下三项违法行为\n1、【\n城三五\n公四七】\n城市道路限速规定\n无中心线30公里/小时有中心线50公里/小时林某110公里/小时的速度行驶属于\n超速驾驶\n\n2、追尾后\n弃车逃离\n属于\n肇事逃逸\n\n3、血液中酒精含量在\n80毫克/百毫升含以上\n属于\n醉酒驾驶\n。\n而题目中没有任何信息如“连续驾驶X小时”、“感觉困倦”等表明林某存在疲劳驾驶的行为。因此不能凭主观臆断选择此项。, url: https://www.ybjk.com/tiku/07f6d.htm, next_url: https://www.ybjk.com/tiku/ed8f7.htm },保存了对应题目的图片至此我们就成功提取出来了所需的题库信息他们将成为整个项目的数据基础的一部分为科一科四题库添加标签我和队友针对每个题目各自考察的重点结合原始网页题库中的题目描述对原有down下来的题目进行了重新的标签划分主要步骤如下将原始的题库送入LLM由它结合检索到的驾驶人考试大纲的细节根据题目类型和情境的分布对科一和科四的1000题分别进行标签的分类并且明确定义每一类标签的题目的含义由本人和队友讨论确定无误后确定下来回答的分类方式如下科目一题目分类方式确定如上科目四同理此处略。随后我们基于分类好的标签分类标准编写脚本调用通用LLM的API来给每一个题目进行类别的智能分类并且详细规定返回格式同时一旦返回格式不符合要求就重新请求。首先是提示词设计我们需要把题目分类依据和方式说明清楚并且要设计好输出json的结构格式确保返回的结果可以直接解析下列代码均由LLM产生BATCH_SIZE 10 # 每批处理的题目数量建议 10-20 之间 SLEEP_TIME 3 # 每批之间的休息时间 VALID_LABELS [ 法律法规与违法处罚, 驾驶证与车辆管理规定, 交通标志、标线与信号灯, 交通警察手势含义, 驾驶操作基础与仪表常识, 一般道路安全驾驶策略, 高速公路及特殊路环境驾驶, 紧急避险与事故处理常识 ] client openai.OpenAI(api_keyAPI_KEY, base_urlBASE_URL) # --- 提示词模板 --- LABEL_DEFINITIONS 1. 法律法规与违法处罚侧重法律定性违法行为、处罚标准扣分、罚款、拘役、吊销、法律责任。 2. 驾驶证与车辆管理规定侧重准驾车型、申领流程、换证时间、丢失补办、车辆登记/报废、审验规定。 3. 交通标志、标线与信号灯侧重识别图片中的标志牌、地面标线实线、虚线、导向线以及红绿灯信号含义。 4. 交通警察手势含义侧重识别交警各种手势停止、转弯、变道等对应的指令。 5. 驾驶操作基础与仪表常识侧重车内按键灯光、雨刮、空调、仪表盘符号冷却液、机油、ABS、安全带、自动挡位等。 6. 一般道路安全驾驶策略侧重普通路口的转弯礼让、跟车距离、超车/会车规范、灯光切换、文明行车等符合安全、道德和交通法律的行为。 7. 高速公路及特殊路环境驾驶侧重高速公路特有规定限速、车道、进出、恶劣天气雨雪雾、山区、隧道、桥梁驾驶方式。 8. 紧急避险与事故处理常识侧重车辆故障爆胎、刹车失灵、伤员急救止血、搬运、事故现场保护、报警处理等意外状态的操作。 SYSTEM_PROMPT f你是一个驾驶员考试题库标注专家。请为提供的题目组选择最合适的知识点标签。 标准标签库{VALID_LABELS} 标签定义{LABEL_DEFINITIONS} 输出规则 1. 必须严格按照以下 JSON 格式返回禁止任何额外文字。 2. 每个题目给出 1-2 个标签存入列表之中。优先选择1个最核心标签。若确实涉及两个领域用中文逗号“”分隔。 3. 标签必须完全匹配标准标签库中的名称严禁自己创造标签。 优先选择1个最核心标签。若确实涉及两个领域用中文逗号“”分隔。 格式示例请严格按照这个来无需其余任何说明 [ {{index: 0, labels: [法律法规与违法处罚]}}, {{index: 1, labels: [交通标志、标线与信号灯, 一般道路安全驾驶策略]}} ] 这里的LLM接口用的是推理时代这个中转平台的资源每日有重置的免费额度我们优先将每个题目绑定到它最贴切的一个标签上如果确实涉及多个标签再额外绑定。这种方法确保了标签识别的准确性尽可能减少了明显不同类型的题目却拥有同一个标签的情况。另外由于LLM输出的黑盒性质即使提示词设计的很严格仍然有可能出现不期望出现的多余输出对于这种情况也要进行判断和捕捉重新构造一次问答提取核心逻辑为while True: try: payload { model: MODEL, messages: [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: f请标注以下题目\n{prompt_content}} ], thinking: {type: disabled}, max_tokens: 8192, temperature: 0.2 } headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } response requests.post(BASE_URL, headersheaders, datajson.dumps(payload), timeout60) res_data_raw response.json() #print(返回内容:,res_data_raw) # 提取内容 res_raw res_data_raw[choices][0][message][content].strip() # 清理 Markdown 代码块 res_json_str re.sub(r^json\s*|$, , res_raw, flagsre.MULTILINE) # 解析并提取真正的 JSON 数组 # 有时模型会把思考过程和JSON混在一起这里只取 [...] 部分 json_match re.search(r\[\s*\{.*\}\s*\], res_json_str, re.DOTALL) if json_match: res_json_str json_match.group() labels_result json.loads(res_json_str) if len(labels_result) ! len(batch_list): print(f [校验失败] 数量不匹配重试...) continue final_labels [] for entry in labels_result: valid_labels [l for l in entry.get(labels, []) if l in VALID_LABELS] final_labels.append(valid_labels if valid_labels else [一般道路安全驾驶策略]) return final_labels except Exception as e: print(f [Error] 请求或解析异常: {e}10秒后重试...) time.sleep(10)这样我们就成功完成了题库的标签标注它有利于我们后续的专项学习、定点推荐等功能的实施。效果预览如下{ question: 正面安全气囊与什么配合才能充分发挥保护作用, type: single_choose, img: subject1_images\\1309_1.jpg, options: [ A、座椅安全带, B、防抱死制动系统, C、座椅安全头枕, D、安全玻璃 ], key: A, analysis: 研究表明假设气囊加安全带是100%安全的话安全带的作用是70%气囊的作用是30%。, url: https://www.jiazhaoba.com/tiba/1229/, next_url: https://www.jiazhaoba.com/tiba/9264/, label: [ 驾驶操作基础与仪表常识 ] }整理补充知识库文件这一部分我们将基于上面提取出来的标签对这些不同标签可能所对应需要的知识库进行了梳理通过长期和LLM的对话讨论最终生成了一个excel文件描述了每一类标签的题目所需要对应的知识库文件最终梳理出这个文件有些之前已经找了有些还没有通过各种渠道我们找齐了这些规范性的文件并且准备进行提取法律文本提取第一步我们针对上面的六部法律文件两部国家级法律四项公安部条令进行提取这一部分是整个里面最简单的法律文本有着极其明确的条目结构可以用多层json的格式进行提取直接用脚本进行提取即可无需动用LLM的力量。我们期望的结果效果是这样的一个法律文件对应一个json文件里面按照章节和条目分为一级和二级标题。[ { chapter: 第一章 总则, source: 中华人民共和国道路交通安全法, articles: [ { title: 第一条, content: ... }, ... ] }, ... ]输出范例如上将此结构和待提取的PDF交给LLM生成提取脚本即可涉及的核心提取方法如下RE_CHAPTER re.compile(r^第[一二三四五六七八九十百]章) RE_SECTION re.compile(r^第[一二三四五六七八九十百]节) RE_ARTICLE re.compile(r^(第[一二三四五六七八九十百]条)\s*(.*)) def clean(text: str) - str: 全角空格转半角压缩连续空格去首尾空白。 text text.replace(\u3000, ) text re.sub(r {2,}, , text) return text.strip() def extract_law(docx_path: str, source: str, has_toc: bool) - list: doc Document(str(docx_path)) chapters [] cur_chapter None cur_article None # has_tocTrue遇到第二轮章标题才算正文has_tocFalse第一次就是正文 in_body not has_toc seen_chapters set() # 记录目录中见过的章标题 def save_article(): if cur_article and cur_chapter is not None: content \n.join(cur_article[lines]).strip() cur_chapter[articles].append({ title: cur_article[title], content: content, }) def save_chapter(): if cur_chapter and cur_chapter[articles]: chapters.append({ chapter: cur_chapter[name], source: source, articles: cur_chapter[articles], }) for para in doc.paragraphs: text clean(para.text) if not text: continue # ---- 章标题 ---- if RE_CHAPTER.match(text): if not in_body: # 目录区记录已见章名若该章名已见过说明正文开始了 if text in seen_chapters: in_body True # 进入正文后正常处理这一行fall through else: seen_chapters.add(text) continue # 仍在目录跳过 # 正文中遇到章标题 → 切换章节 save_article() cur_article None save_chapter() cur_chapter {name: text, articles: []} continue # ---- 节标题忽略 ---- if RE_SECTION.match(text): continue # 目录区其他内容跳过 if not in_body: continue # ---- 条目起始行 ---- m RE_ARTICLE.match(text) if m: save_article() rest m.group(2).strip() cur_article { title: m.group(1), lines: [rest] if rest else [], } continue # ---- 普通段落追加到当前条目 ---- if cur_article is not None: cur_article[lines].append(text) # 收尾 save_article() save_chapter() return chapters这个提取的核心思想就是利用文本里面的“第X章”、“第Y节”这种带有明显标识性的文字来进行正则匹配和定位找到分割地点并且按照分割点进行分层提取。成功的前提是读取完全正确没有乱码且没有其余无关信息。很幸运这些条件都满足全部一次成功。这样我们就得到了下面的提取后的json文件其余五部同理可复用这个脚本交通标志和标线的提取这一部分比较困难尝试了好久发现用脚本提取主要有以下难点原始的国家强制标准GB5768交通标志和标线是PDF格式且存在读取乱码的问题选择复制的时候会复制下来一堆奇怪的符号尝试用脚本提取会得到一堆乱码难以像上面法律文本提取时候那样利用正则匹配方式进行分割图片的提取基本依赖写死的图注位置相对窗口大小定位窗口大小一般是写死的很难完全兼容不同大小的图片导致有些图片留白过多有些则不完整文档内噪声信息实在过多如页码、页眉、页脚等往往防不胜防很容易被带偏正文提取到一半就突然新开一个章节了。。。。。。。此处省略1w字基于这样难以使用脚本直接提取的现状困局我选择退而求其次找了一个前人整理的包含大部分GB-5768标志的word文档每个标志都具有名称、样图和含义注释天然就是适合转换为Json保存的格式。当然我也进行过尝试使用脚本对这个简化后的word文档进行提取但是终究因为换行符位置难以预测、跨行信息难以对齐而宣告失败。于是我转向寻求一种更为朴素的方法在LLM时代 谁还手写脚本做这种事情啊不都是让LLM看一眼直接导出吗这在一定程度上给了我一些思路或许我们不用搞那么麻烦直接将文档内容送给LLM让它解析里面的内容并且按照要求给出结果不就行了说干就干我们发现如果把页面截取下来作为图片输入给豆老师并且要求他给出适当的输出方式就可以达到提取的效果。页面也不多因此可以尝试使用这种方法上述为问题它也根据我们设定好的规则返回了适配的结果识别相当准确的当然这个也有缺陷只能识别里面的文字图片需要我们手动截取并且保存到它所对应的路径下满足他的命名要求可能看起来比较原始但是和之前修改脚本工作量比起来至少做的都是有效工作之前是一直原地转圈悲机动车仪表盘、操纵杆界面组件提取提取的是GB4094文件这个官方文档和上面的GB5768提取类似直接使用PDF提取也有类似的问题虽然没有乱码但是仍然有随机重开新块的几率噪声也特别多。这里我发现相对于GB5768这个的提取难度和精度要小很多无需提取完整的章节结构而是只要找到所有的组件图片让每个图片的名称和描述性解析能够正常识别出来就行了。上面是第一次对话后面又增加了过滤噪声页面、页脚以及预先输出层次分析结果确认无误后在生成实际提取结果的逻辑最终的脚本如下import os import re import json import docx from pathlib import Path # 固定章节标题双验证 LEGAL { 1: 范围, 2: 规范性引用文件, 3: 术语和定义, 4: 要求, 5: 标志种类及信号装置的显示颜色, 3.1: 操纵件, 3.2: 指示器, 3.3: 信号装置, 3.4: 标志, 3.5: 相似标志, 3.6: 共用空间, 3.7: 邻近, 4.1: 基本要求, 4.2: 信号装置标志的颜色, 4.3: 标志的位置, 5.1: 汽车操纵件、指示器及信号装置中强制标示的标志及信号装置的显示颜色, 5.2: 汽车操纵件、指示器及信号装置中非强制标示的标志及信号装置的显示颜色 } # ✅ 温和清洗你要的规则 def remove_spaces(s): if not s: return return re.sub(r\s, , s) def clean_line(s): if not s: return # 全角空格 → 半角 s s.replace(\u3000, ) # 多个空格 → 一个 s re.sub(r\s, , s) # 处理编号里的空格 # 3. 1 → 3.1 s re.sub(r(\d)\s*\.\s*(\d), r\1.\2, s) # 4. 1. 1 → 4.1.1 s re.sub(r(\d\.\d)\s*\.\s*(\d), r\1.\2, s) # 去首尾 return s.strip() # 提取图片 def extract_images(doc, out_dir): os.makedirs(out_dir, exist_okTrue) # 先收集所有图片关系 image_rels [rel for rel in doc.part.rels.values() if image in rel.target_ref] total_count len(image_rels) # 遍历并使用反向索引 for i, rel in enumerate(image_rels): data rel.target_part.blob # 如果 1号变成了 51号说明顺序是倒过来的 # 计算新索引总数 - 当前索引 (例如51 - 0 51, 51 - 50 1) real_idx total_count - i with open(f{out_dir}/图{real_idx}.jpg, wb) as f: f.write(data) print(f✅ 图片提取完成共 {total_count} 张已执行反序修正。) # 读取 def load_doc(path): doc docx.Document(path) lines [] for p in doc.paragraphs: t p.text.strip() if t: lines.append(clean_line(t)) return lines, doc # 解析结构最长匹配 双验证 def parse(lines): root [] curr1 None curr2 None # 匹配 1 / 1.2 / 1.2.3 r3 re.compile(r^(\d\.\d\.\d)\s*(.*)) r2 re.compile(r^(\d\.\d)\s*(.*)) r1 re.compile(r^(\d)\s*(.*)) img_r re.compile(r图\s*(\d)) for line in lines: # ---- 三级条目 ---- m3 r3.match(line) if m3 and curr2: n, c m3.groups() imgs [fGB4094/图{g}.jpg for g in img_r.findall(c)] curr2[children].append({ number: n, content: remove_spaces(c), images: imgs }) continue # ---- 二级标题双验证---- m2 r2.match(line) if m2: n, t m2.groups() if n in LEGAL and LEGAL[n] in line: node { number: n, title: LEGAL[n], content: , children: [] } if curr1: curr1[children].append(node) curr2 node continue # ---- 一级标题双验证---- m1 r1.match(line) if m1: n, t m1.groups() if n in LEGAL and LEGAL[n] in line: node { number: n, title: LEGAL[n], content: , children: [] } root.append(node) curr1 node curr2 None continue # ---- 普通内容 ---- if curr2: curr2[content] line elif curr1: curr1[content] line return root # 打印结构 def show(tree): print(\n *80) print( 最终结构完美版) print(*80) for l1 in tree: print(f\n 1级 {l1[number]} {l1[title]}) for l2 in l1[children]: print(f ├─ 2级 {l2[number]} {l2[title]}) for l3 in l2[children]: print(f ├─ 3级 {l3[number]} {l3[content][:520]}) # 主函数 def main(): file rE:\pythonCode\DriveGenius\data\original\GB-4094汽车操纵件、指示器及信号装置的标志.docx out rE:\pythonCode\DriveGenius\data\outputs img_dir f{out}/GB4094 lines, doc load_doc(file) extract_images(doc, img_dir) root parse(lines) show(root) if input(\n生成 JSONy/n) y: with open(f{out}/GB4094.json, w, encodingutf-8) as f: json.dump({ 标准: GB4094-2016, 名称: 汽车操纵件、指示器及信号装置的标志, 内容: root }, f, ensure_asciiFalse, indent2) print(✅ 生成完成) if __name__ __main__: main()总体思路是通过分级标题1,1.2,2.3.1这种进行界定给每个区域都确定归属的文本块图片通过图注图XX单独提取并保存。演示运行结果如下正常提取出了结构随后点击确认正式产生对应的json文档。图片提取效果正常基本都正常提取到了没有切多或者切少了。《安全驾驶从这里开始》提取这是一本公安部于2013年出版的道路安全宣传小册子内容和驾驶员培训要求高度重合提取它作为知识库对于弥补上述材料中缺乏的信息源是十分有必要的可以看到该书还包含了上述其余文件没有包含的文明驾驶、特殊情况驾驶策略以及应急处理策略等方面的知识这些知识在实际考试中也占了很大的篇幅而且他的编写风格和题目也极其相似因此提取这方面的信息是十分有必要的。为简化工作量我们只提取了五六七三章的内容。关于提取方式由于书排版非常花里胡哨不仅有主线正文部分还有很多小插曲、小知识等。因此使用脚本进行完美提取几乎是不可能完成的。同样的我们参考之前提取GB5768的思路将这一过程利用LLM进行简化由它完成主要任务我们首先将要提取的章节进行PDF切分专门保存一份然后将它发给LLM并且说明我们的目的让它首先进行结构上的分析主要是进行标题的分层后面再利用现成的硬编码标题进行比对和提取强化它的理解记忆经过反馈纠正后最终确定的结构如下之后我们就按照这个结构让它有目的、有方向的进行提取在此之前我们还设计了一个提取的模板让它按照我们预想的结构进行提取均有三级标题三级标题下方若有显式分点就使用四级标题否则合并为内容只关注文字内容这样它就知道怎么提取、提取哪些、怎么返回等几个重要问题了通过适当的指令即可让它产生下面这样符合条件和要求的结果每次保持提取适当大小的上下文长度可以让它充分尊重原文原文、对非正文部分的表格等信息如各种受伤情况的救护措施表尽可能自然提取并且不覆盖正文这样逐个小节提取即可获得完整的知识库了图标知识库管理UI由于我们前期搜集的GB5768和GB4096的图标实际上并不完整需要后续补充为了方便补充我制作了一个图形化界面 用来管理这两类标志原理非常简单启动一个简易flask进程从json文件读取文字说明和路径并且找到相应的图片全部展示在页面上即可。除了检查图标和说明是否对应之外这个页面还支持上传新的图标、修改现有的图片有更好更清晰的话方便直接操作无需修改多个路径下文件。外观如下右上角点击新增条目可以传入图片实现增加图像会修改json脚本将标题和说明加入进去后期规划目前数据的收集和预处理以及基本完毕接下来计划的工作准备开始编写RAG查询接口将获取到的json文件和图像嵌入到向量数据库里面并完成底层的查询接口方法的实现。可以考虑做一个简易查询demo能够针对原始题目问题检索出来对应的法律条文/标志的官方解释含义。学习多数据源知识图谱的整合提取的方法要保证不同法律条令文本之间共有的实体能够在图数据库中共享一个节点做到多源异构信息的整合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2469072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…