# -*- coding: utf-8 -*- """ 从招投标公告中提取招标人、中标人等关键信息 这个示例展示了如何使用 BidiRag 召回 HTML 公告中的内容片段, 并从中提取关键信息。 """ import sys import os import re sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from bdirag.bidi_rag import BidiRag def extract_key_info(html_content): """从 HTML 内容中提取关键信息""" from bs4 import BeautifulSoup info = {} try: # 尝试使用 lxml,如果失败则使用内置的 html.parser try: soup = BeautifulSoup(html_content, 'lxml') except: soup = BeautifulSoup(html_content, 'html.parser') # 查找所有表格行 for tr in soup.find_all('tr'): cells = tr.find_all(['td', 'th']) if len(cells) >= 2: key = cells[0].get_text(strip=True) value = cells[1].get_text(strip=True) # 匹配关键字段 if '招标人' in key: info['招标人'] = value elif '采购人' in key and '意向' not in key: info['采购人'] = value elif '采购意向单位' in key: info['采购意向单位'] = value elif '中标人' in key: info['中标人'] = value elif '项目名称' in key or '采购项目名称' in key: info['项目名称'] = value elif '中标金额' in key: info['中标金额'] = value elif '预算金额' in key: info['预算金额'] = value except Exception as e: # 如果解析失败,使用正则表达式作为后备 patterns = { '招标人': r'招标人\s*([^<]+)', '采购人': r'采购人\s*([^<]+)', '采购意向单位': r'采购意向单位\s*([^<]+)', '中标人': r'中标人\s*([^<]+)', '项目名称': r'项目名称\s*([^<]+)', '中标金额': r'中标金额\s*([^<]+)', '预算金额': r'预算金额\s*([^<]+)', } for key, pattern in patterns.items(): match = re.search(pattern, html_content) if match: info[key] = match.group(1).strip() return info def demo_extract_bid_info(): """演示从招投标公告中提取信息""" print("=" * 80) print("招投标公告信息提取示例") print("=" * 80) # 1. 初始化 BidiRag print("\n[步骤 1] 初始化 BidiRag (使用 bm25_html_tree 方法)...") rag = BidiRag(rag_method='bm25_html_tree') # 2. 添加公告数据 print("\n[步骤 2] 添加招投标公告...") announcements = [ """

政府采购意向公告

采购意向单位大连长兴岛经济技术开发区交流岛街道办事处
采购项目名称交流岛滨海路夜间出行照明提升工程
预算金额147.060000万元
采购品目路灯照明工程
采购需求概况在滨海路安装太阳能路灯200盏(单排)
预计采购时间2026-05
""", """

中标公告

采购人XX市财政局
项目名称办公设备采购项目
中标人XX办公设备有限公司
中标金额50万元
采购内容电脑、打印机、复印机等办公设备
""", """

招标公告

招标人XX市交通运输局
项目名称智慧交通系统建设项目
项目预算5000万元
招标内容交通信号控制系统、视频监控系统
投标截止时间2024-06-15
""", """

中标结果公告

招标人XX市城市建设投资集团
中标人XX建设工程有限公司
项目名称道路建设项目
中标金额18500万元
建设内容道路路基、路面、桥梁工程
""" ] rag.add_texts(announcements) print(f"✓ 已添加 {rag.get_document_count()} 个公告") # 3. 检索招标人信息 print("\n" + "=" * 80) print("[示例 1] 检索所有包含'招标人'或'采购人'的公告") print("=" * 80) # 使用 OR 逻辑:分别搜索 for keyword in ['招标人', '采购人', '采购意向单位']: print(f"\n搜索关键词: '{keyword}'") results = rag.search_keywords([keyword], top_k=10) if results: print(f"找到 {len(results)} 个相关公告:\n") for i, doc in enumerate(results, 1): print(f"--- 公告 {i} ---") info = extract_key_info(doc.page_content) for key, value in info.items(): print(f" {key}: {value}") print() else: print("未找到相关结果\n") # 4. 检索中标人信息 print("\n" + "=" * 80) print("[示例 2] 检索所有包含'中标人'的公告") print("=" * 80) results = rag.search_keywords(['中标人'], top_k=10) if results: print(f"\n找到 {len(results)} 个中标公告:\n") for i, doc in enumerate(results, 1): print(f"--- 中标公告 {i} ---") info = extract_key_info(doc.page_content) for key, value in info.items(): print(f" {key}: {value}") print() # 5. 同时包含招标人和中标人的公告 print("\n" + "=" * 80) print("[示例 3] 检索同时包含'招标人'和'中标人'的公告(完整项目信息)") print("=" * 80) results = rag.search_keywords(['招标人', '中标人'], top_k=10) if results: print(f"\n找到 {len(results)} 个完整项目公告:\n") for i, doc in enumerate(results, 1): print(f"--- 项目 {i} ---") info = extract_key_info(doc.page_content) # 分类显示 purchaser = info.get('招标人') or info.get('采购人') winner = info.get('中标人') project = info.get('项目名称') amount = info.get('中标金额') or info.get('预算金额') print(f" 招标人: {purchaser}") print(f" 中标人: {winner}") print(f" 项目: {project}") print(f" 金额: {amount}") print() # 6. 检索特定类型项目 print("\n" + "=" * 80) print("[示例 4] 检索特定项目类型") print("=" * 80) search_terms = [ (['路灯', '照明'], "照明工程"), (['交通', '系统'], "交通系统"), (['道路', '建设'], "道路建设"), (['办公', '设备'], "办公设备"), ] for keywords, category in search_terms: print(f"\n搜索 '{category}' 相关项目:") results = rag.search_keywords(keywords, top_k=5) if results: for i, doc in enumerate(results, 1): info = extract_key_info(doc.page_content) purchaser = info.get('招标人') or info.get('采购人') or info.get('采购意向单位') project = info.get('项目名称') amount = info.get('中标金额') or info.get('预算金额') print(f" {i}. {project}") print(f" 招标方: {purchaser}") print(f" 金额: {amount}") else: print(" 未找到相关项目") # 7. 总结 print("\n" + "=" * 80) print("提取结果总结") print("=" * 80) # 统计所有公告 all_results = rag.search_keywords(['招标人', '采购人', '中标人'], top_k=100) purchasers = set() winners = set() total_amount = 0 for doc in all_results: info = extract_key_info(doc.page_content) purchaser = info.get('招标人') or info.get('采购人') or info.get('采购意向单位') if purchaser: purchasers.add(purchaser) winner = info.get('中标人') if winner: winners.add(winner) amount_str = info.get('中标金额') or info.get('预算金额') or '' # 提取金额数字(简单处理) amount_match = re.search(r'(\d+(?:\.\d+)?)万', amount_str) if amount_match: total_amount += float(amount_match.group(1)) print(f"\n共处理 {len(all_results)} 个公告") print(f"涉及招标方 {len(purchasers)} 个:") for p in purchasers: print(f" - {p}") print(f"\n涉及中标方 {len(winners)} 个:") for w in winners: print(f" - {w}") print(f"\n项目总金额: 约 {total_amount:.2f} 万元") print("\n" + "=" * 80) print("示例完成!") print("=" * 80) if __name__ == "__main__": demo_extract_bid_info()