Skip to main content
Glama
guokao_helper.py20.1 kB
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 2025年国考小助手 - 命令行工具 功能: 1. 多条件智能筛选 2. 专业匹配查询 3. 个人条件一键匹配 4. 筛选结果导出(JSON格式) """ import pandas as pd import json import os import re from datetime import datetime class GuokaoHelper: def __init__(self, excel_path): """初始化,加载数据""" self.excel_path = excel_path self.df = self._load_data() print(f"✅ 数据加载成功!共 {len(self.df)} 个岗位,招考 {int(self.df['招考人数'].sum())} 人") def _load_data(self): """加载Excel数据""" all_dfs = [] xls = pd.ExcelFile(self.excel_path) for sheet_name in xls.sheet_names: df = pd.read_excel(xls, sheet_name=sheet_name) df['机关类别'] = sheet_name all_dfs.append(df) return pd.concat(all_dfs, ignore_index=True) def filter_positions(self, **kwargs): """ 功能1: 多条件智能筛选 支持的筛选条件: - 机关类别: 机关类别(精确匹配) - 部门名称: 部门名称(模糊匹配) - 工作地点: 工作地点(模糊匹配) - 学历: 学历要求(模糊匹配) - 政治面貌: 政治面貌(精确匹配或"不限") - 基层工作最低年限: 基层工作年限要求 - 专业: 专业(模糊匹配) - 考试类别: 考试类别(模糊匹配) - 职位属性: 职位属性(模糊匹配) - 招考人数_min: 最小招考人数 - 招考人数_max: 最大招考人数 """ result = self.df.copy() # 机关类别 - 精确匹配 if kwargs.get('机关类别'): result = result[result['机关类别'] == kwargs['机关类别']] # 部门名称 - 模糊匹配 if kwargs.get('部门名称'): result = result[result['部门名称'].str.contains(kwargs['部门名称'], na=False)] # 工作地点 - 模糊匹配 if kwargs.get('工作地点'): result = result[result['工作地点'].str.contains(kwargs['工作地点'], na=False)] # 学历 - 模糊匹配 if kwargs.get('学历'): result = result[result['学历'].str.contains(kwargs['学历'], na=False)] # 政治面貌 - 精确匹配或不限 if kwargs.get('政治面貌'): if kwargs['政治面貌'] == '不限': result = result[result['政治面貌'] == '不限'] else: # 匹配指定的政治面貌或不限 result = result[ (result['政治面貌'] == kwargs['政治面貌']) | (result['政治面貌'] == '不限') | (result['政治面貌'].str.contains(kwargs['政治面貌'], na=False)) ] # 基层工作最低年限 if kwargs.get('基层工作最低年限'): if kwargs['基层工作最低年限'] == '无限制': result = result[result['基层工作最低年限'] == '无限制'] else: result = result[result['基层工作最低年限'].str.contains(kwargs['基层工作最低年限'], na=False)] # 专业 - 模糊匹配 if kwargs.get('专业'): result = result[result['专业'].str.contains(kwargs['专业'], na=False)] # 考试类别 - 模糊匹配 if kwargs.get('考试类别'): result = result[result['考试类别'].str.contains(kwargs['考试类别'], na=False)] # 职位属性 - 模糊匹配 if kwargs.get('职位属性'): result = result[result['职位属性'].str.contains(kwargs['职位属性'], na=False)] # 招考人数范围 if kwargs.get('招考人数_min'): result = result[result['招考人数'] >= kwargs['招考人数_min']] if kwargs.get('招考人数_max'): result = result[result['招考人数'] <= kwargs['招考人数_max']] return result def match_by_major(self, major_keyword): """ 功能2: 专业匹配查询 输入专业关键词,返回所有匹配的岗位 """ result = self.df[self.df['专业'].str.contains(major_keyword, na=False, regex=False)] return result def personal_match(self, education=None, major=None, political_status=None, work_years=None, location=None, base_project=None): """ 功能9: 个人条件一键匹配 根据个人条件筛选可报考的岗位 参数: - education: 学历(本科/硕士研究生/博士研究生) - major: 专业关键词 - political_status: 政治面貌(中共党员/共青团员/群众) - work_years: 基层工作年限(0/1/2/3/5) - location: 期望工作地点 - base_project: 是否有服务基层项目经历(True/False) """ result = self.df.copy() # 学历匹配 if education: education_map = { '大专': ['大专', '大专及以上', '大专或本科'], '本科': ['本科', '本科及以上', '本科或硕士研究生', '大专或本科', '大专及以上', '仅限本科'], '硕士研究生': ['硕士研究生', '硕士研究生及以上', '本科及以上', '本科或硕士研究生', '仅限硕士研究生'], '博士研究生': ['博士研究生', '硕士研究生及以上', '本科及以上', '仅限博士研究生'] } if education in education_map: allowed_edu = education_map[education] result = result[result['学历'].isin(allowed_edu)] # 专业匹配 if major: result = result[result['专业'].str.contains(major, na=False, regex=False)] # 政治面貌匹配 if political_status: if political_status == '中共党员': # 党员可以报考所有岗位 pass elif political_status == '共青团员': # 团员可以报考"不限"和"中共党员或共青团员"的岗位 result = result[ (result['政治面貌'] == '不限') | (result['政治面貌'].str.contains('共青团员', na=False)) ] else: # 群众 result = result[result['政治面貌'] == '不限'] # 基层工作年限匹配 if work_years is not None: year_map = { 0: ['无限制'], 1: ['无限制', '一年'], 2: ['无限制', '一年', '二年'], 3: ['无限制', '一年', '二年', '三年'], 5: ['无限制', '一年', '二年', '三年', '五年以上'] } if work_years in year_map: allowed_years = year_map[work_years] result = result[result['基层工作最低年限'].isin(allowed_years)] # 工作地点匹配 if location: result = result[result['工作地点'].str.contains(location, na=False)] # 服务基层项目经历 if base_project is False: # 没有基层项目经历,只能报考"无限制"的岗位 result = result[result['服务基层项目工作经历'] == '无限制'] return result def export_to_json(self, df, filename=None): """ 功能15: 导出筛选结果为JSON """ if filename is None: timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') filename = f'guokao_result_{timestamp}.json' # 转换为字典列表 records = df.to_dict(orient='records') # 处理NaN值 for record in records: for key, value in record.items(): if pd.isna(value): record[key] = None # 保存为JSON output = { 'total_positions': len(records), 'total_recruitment': int(df['招考人数'].sum()) if len(df) > 0 else 0, 'export_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'positions': records } with open(filename, 'w', encoding='utf-8') as f: json.dump(output, f, ensure_ascii=False, indent=2) print(f"✅ 已导出 {len(records)} 条记录到 {filename}") return filename def display_results(self, df, max_rows=10): """显示筛选结果摘要""" print(f"\n{'='*60}") print(f"📊 筛选结果:共 {len(df)} 个岗位,招考 {int(df['招考人数'].sum())} 人") print(f"{'='*60}") if len(df) == 0: print("未找到符合条件的岗位") return # 显示前几条 display_cols = ['部门名称', '招考职位', '工作地点', '学历', '招考人数', '专业'] print(f"\n前 {min(max_rows, len(df))} 条结果:") print("-" * 60) for i, (_, row) in enumerate(df.head(max_rows).iterrows()): print(f"\n【{i+1}】{row['部门名称']} - {row['招考职位']}") print(f" 📍 工作地点: {row['工作地点']}") print(f" 🎓 学历要求: {row['学历']}") print(f" 👥 招考人数: {row['招考人数']}") # 专业信息太长,截取显示 major = str(row['专业'])[:80] + '...' if len(str(row['专业'])) > 80 else row['专业'] print(f" 📚 专业要求: {major}") if len(df) > max_rows: print(f"\n... 还有 {len(df) - max_rows} 条结果,请导出查看完整列表") def interactive_menu(): """交互式菜单""" excel_path = r'G:\Desktop\guokao_mcp\2025年国考岗位表.xls' if not os.path.exists(excel_path): print(f"❌ 找不到数据文件: {excel_path}") return helper = GuokaoHelper(excel_path) while True: print("\n" + "=" * 60) print("🎯 2025年国考小助手") print("=" * 60) print("1. 多条件智能筛选") print("2. 专业匹配查询") print("3. 个人条件一键匹配") print("4. 退出") print("-" * 60) choice = input("请选择功能 (1-4): ").strip() if choice == '1': # 多条件智能筛选 print("\n📋 多条件智能筛选(直接回车跳过该条件)") print("-" * 40) filters = {} # 机关类别 print("\n机关类别选项:") print(" 1. 中央党群机关") print(" 2. 中央国家行政机关(本级)") print(" 3. 中央国家行政机关省级以下直属机构") print(" 4. 中央国家行政机关参照公务员法管理事业单位") organ_choice = input("请选择机关类别 (1-4, 回车跳过): ").strip() organ_map = { '1': '中央党群机关', '2': '中央国家行政机关(本级)', '3': '中央国家行政机关省级以下直属机构', '4': '中央国家行政机关参照公务员法管理事业单位' } if organ_choice in organ_map: filters['机关类别'] = organ_map[organ_choice] # 其他条件 dept = input("部门名称关键词 (如 税务): ").strip() if dept: filters['部门名称'] = dept location = input("工作地点 (如 北京/广东): ").strip() if location: filters['工作地点'] = location print("\n学历选项:本科及以上/仅限本科/硕士研究生及以上/仅限硕士研究生/仅限博士研究生") edu = input("学历要求: ").strip() if edu: filters['学历'] = edu print("\n政治面貌选项:不限/中共党员/中共党员或共青团员") political = input("政治面貌: ").strip() if political: filters['政治面貌'] = political print("\n基层工作年限选项:无限制/一年/二年/三年/五年以上") years = input("基层工作最低年限: ").strip() if years: filters['基层工作最低年限'] = years major = input("专业关键词 (如 计算机/法学/会计): ").strip() if major: filters['专业'] = major # 执行筛选 result = helper.filter_positions(**filters) helper.display_results(result) # 询问是否导出 if len(result) > 0: export = input("\n是否导出结果为JSON? (y/n): ").strip().lower() if export == 'y': filename = input("输入文件名 (回车使用默认): ").strip() if filename: if not filename.endswith('.json'): filename += '.json' helper.export_to_json(result, filename) else: helper.export_to_json(result) elif choice == '2': # 专业匹配查询 print("\n📚 专业匹配查询") print("-" * 40) major = input("请输入您的专业关键词 (如 计算机/软件/法学/会计/金融): ").strip() if major: result = helper.match_by_major(major) helper.display_results(result) if len(result) > 0: export = input("\n是否导出结果为JSON? (y/n): ").strip().lower() if export == 'y': filename = input("输入文件名 (回车使用默认): ").strip() if filename: if not filename.endswith('.json'): filename += '.json' helper.export_to_json(result, filename) else: helper.export_to_json(result) elif choice == '3': # 个人条件一键匹配 print("\n👤 个人条件一键匹配") print("-" * 40) print("\n学历选项:大专/本科/硕士研究生/博士研究生") education = input("您的学历: ").strip() if not education: education = None major = input("您的专业关键词: ").strip() if not major: major = None print("\n政治面貌选项:中共党员/共青团员/群众") political = input("您的政治面貌: ").strip() if not political: political = None years_input = input("您的基层工作年限 (0/1/2/3/5): ").strip() try: work_years = int(years_input) if years_input else None except ValueError: work_years = None location = input("期望工作地点 (如 北京/上海): ").strip() if not location: location = None base_input = input("是否有服务基层项目经历 (y/n, 回车跳过): ").strip().lower() if base_input == 'y': base_project = True elif base_input == 'n': base_project = False else: base_project = None # 执行匹配 result = helper.personal_match( education=education, major=major, political_status=political, work_years=work_years, location=location, base_project=base_project ) helper.display_results(result) if len(result) > 0: export = input("\n是否导出结果为JSON? (y/n): ").strip().lower() if export == 'y': filename = input("输入文件名 (回车使用默认): ").strip() if filename: if not filename.endswith('.json'): filename += '.json' helper.export_to_json(result, filename) else: helper.export_to_json(result) elif choice == '4': print("\n👋 再见!祝您考试顺利!") break else: print("❌ 无效选择,请重新输入") def main(): """主函数 - 支持命令行参数""" import argparse parser = argparse.ArgumentParser(description='2025年国考小助手') parser.add_argument('--mode', '-m', choices=['interactive', 'filter', 'major', 'personal'], default='interactive', help='运行模式') parser.add_argument('--output', '-o', help='输出JSON文件名') # 筛选条件参数 parser.add_argument('--organ', help='机关类别') parser.add_argument('--dept', help='部门名称关键词') parser.add_argument('--location', help='工作地点') parser.add_argument('--education', help='学历要求') parser.add_argument('--political', help='政治面貌') parser.add_argument('--years', help='基层工作最低年限') parser.add_argument('--major', help='专业关键词') args = parser.parse_args() if args.mode == 'interactive': interactive_menu() else: excel_path = r'G:\Desktop\guokao_mcp\2025年国考岗位表.xls' helper = GuokaoHelper(excel_path) if args.mode == 'filter': filters = {} if args.organ: filters['机关类别'] = args.organ if args.dept: filters['部门名称'] = args.dept if args.location: filters['工作地点'] = args.location if args.education: filters['学历'] = args.education if args.political: filters['政治面貌'] = args.political if args.years: filters['基层工作最低年限'] = args.years if args.major: filters['专业'] = args.major result = helper.filter_positions(**filters) helper.display_results(result, max_rows=20) if args.output: helper.export_to_json(result, args.output) elif args.mode == 'major': if args.major: result = helper.match_by_major(args.major) helper.display_results(result, max_rows=20) if args.output: helper.export_to_json(result, args.output) else: print("❌ 请提供 --major 参数") elif args.mode == 'personal': work_years = int(args.years) if args.years else None result = helper.personal_match( education=args.education, major=args.major, political_status=args.political, work_years=work_years, location=args.location ) helper.display_results(result, max_rows=20) if args.output: helper.export_to_json(result, args.output) if __name__ == '__main__': main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mouseminar/guokao_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server