AI写的地址信息提取解析工具

查看 35|回复 3
作者:五轮离火   
这是为了方便处理补发换货来做的工具,可以配合ERP模板倒入订单,不用一个个新建订单
主要作用
地址信息解析工具是一款专为处理中文地址信息设计的智能数据处理软件。它能够自动从复杂的地址文本中提取姓名、电话号码、省份、城市、区县和街道信息,同时支持商家编码匹配和入库状态标记功能。
功能
1. 智能地址解析
  • 多级地址提取:自动识别并分离省份、城市、区县和街道信息
  • 姓名识别:智能提取收件人姓名,支持中文姓名和英文名识别
  • 电话提取:准确提取手机号和固定电话号码
  • 学习能力:自动学习并记忆已确认的姓名,不断提高识别准确率
    2. 商家编码匹配
  • 根据备注信息自动匹配商家编码
  • 支持自定义编码映射规则
  • 无法匹配时自动留空处理
    3. 入库状态标记
  • 根据寄回单号自动标记入库情况(已入库/未入库)
  • 支持批量处理大量数据
    4. 自动化处理
  • 配置文件记忆功能:自动保存编码文件和入库文件路径
  • 智能输出:处理结果自动保存在输入文件同目录下
  • 批量处理:支持一次性处理大量地址数据

    使用方法
  • 第一次使用时,选择数据文件、编码文件和入库文件
  • 设置地址列索引(从0开始)
  • 编码文件、入库文件和地址列索引的位置会被自动保存
  • 下次打开程序时,这些设置会自动加载
  • 处理完成后,结果文件会自动保存在数据文件同一目录
  • 点击"打开已完成文件"按钮可以打开最近处理完成的文件
    使用流程
  • 准备文件:
  • 数据文件:包含地址信息的Excel文件
  • 编码文件:商家编码映射表
  • 入库文件:入库单管理表
  • 设置参数:
  • 选择地址列索引(从0开始)
  • 系统自动记忆常用文件路径
  • 开始处理:
  • 点击"开始处理"按钮
  • 系统自动解析、匹配和标记
  • 实时显示处理进度
  • 查看结果:
  • 处理完成后自动保存
  • 点击"打开已完成文件"查看结果
  • 结果文件保存在输入文件同目录下




    22222.png (49.35 KB, 下载次数: 0)
    下载附件
    2025-8-26 12:21 上传

    目前这个工具还是有很多问题,姓名提取不是百分百准确,大家有更好的方法可以指导下
    下载地址链接:
    https://www.123865.com/s/rtfeVv-1qZBH提取码:sjDS
    [Python] 纯文本查看 复制代码#!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    一次性完成:
    1. 智能解析姓名、电话、省市区街道
    2. 根据【备注】匹配商家编码(无法确定留空)
    3. 根据【寄回单号】标记入库情况
    4. 自动学习并存储确认正确的姓名,提高后续识别准确率
    [mw_shl_code=python,false]#!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    一次性完成:
    1. 智能解析姓名、电话、省市区街道
    2. 根据【备注】匹配商家编码(无法确定留空)
    3. 根据【寄回单号】标记入库情况
    4. 自动学习并存储确认正确的姓名,提高后续识别准确率
    """
    import re
    import pandas as pd
    import os
    import sys
    import jieba
    import jieba.posseg as pseg
    from typing import Dict, Any, Set, Optional, List, Tuple
    import tkinter as tk
    from tkinter import filedialog, messagebox, ttk
    import threading
    from datetime import datetime
    import json
    from collections import defaultdict
    import configparser
    # 初始化姓名学习系统
    class NameLearningSystem:
        def __init__(self, dict_file="chinese_names.dic", confirmed_file="confirmed_names.json"):
            self.dict_file = dict_file
            self.confirmed_file = confirmed_file
            self.confirmed_names = defaultdict(int)  # 存储确认的姓名及其出现次数
            
            # 加载已确认的姓名
            self.load_confirmed_names()
            
            # 初始化jieba分词器
            self.init_jieba()
       
        def init_jieba(self):
            """初始化jieba分词器,加载自定义词典"""
            # 加载基础词典
            if os.path.exists(self.dict_file):
                jieba.load_userdict(self.dict_file)
            
            # 添加已确认的姓名到jieba词典
            for name in self.confirmed_names:
                jieba.add_word(name, freq=1000, tag='nr')
       
        def load_confirmed_names(self):
            """加载已确认的姓名"""
            if os.path.exists(self.confirmed_file):
                try:
                    with open(self.confirmed_file, 'r', encoding='utf-8') as f:
                        self.confirmed_names = defaultdict(int, json.load(f))
                    print(f"已加载 {len(self.confirmed_names)} 个确认姓名")
                except Exception as e:
                    print(f"加载确认姓名时出错: {e}")
       
        def save_confirmed_names(self):
            """保存已确认的姓名"""
            try:
                with open(self.confirmed_file, 'w', encoding='utf-8') as f:
                    json.dump(dict(self.confirmed_names), f, ensure_ascii=False, indent=2)
                print(f"已保存 {len(self.confirmed_names)} 个确认姓名")
            except Exception as e:
                print(f"保存确认姓名时出错: {e}")
       
        def add_confirmed_name(self, name):
            """添加一个确认正确的姓名"""
            if name and len(name) >= 1:  # 允许单个字的姓名
                self.confirmed_names[name] += 1
                # 添加到jieba词典
                jieba.add_word(name, freq=1000, tag='nr')
                print(f"已添加确认姓名: {name} (出现次数: {self.confirmed_names[name]})")
       
        def get_top_names(self, n=50):
            """获取出现次数最多的前n个姓名"""
            return sorted(self.confirmed_names.items(), key=lambda x: x[1], reverse=True)[:n]
    # 初始化姓名学习系统
    name_learner = NameLearningSystem()
    # -------------------- 1. 地址解析 --------------------
    # 预编译正则表达式以提高性能
    PHONE_PATTERN = re.compile(r'1[3-9]\d{9}|(?:\d{3,4}-)?\d{7,8}')
    # 中国所有省份、直辖市、自治区
    PROVINCES = [
        '北京市', '天津市', '上海市', '重庆市', '河北省', '山西省', '辽宁省', '吉林省', '黑龙江省',
        '江苏省', '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省',
        '广东省', '海南省', '四川省', '贵州省', '云南省', '陕西省', '甘肃省', '青海省', '台湾省',
        '内蒙古自治区', '广西壮族自治区', '西藏自治区', '宁夏回族自治区', '新疆维吾尔自治区',
        '香港特别行政区', '澳门特别行政区'
    ]
    # 常见城市
    CITIES = [
        '北京', '上海', '天津', '重庆', '石家庄', '太原', '沈阳', '长春', '哈尔滨', '南京', '杭州',
        '合肥', '福州', '南昌', '济南', '郑州', '武汉', '长沙', '广州', '深圳', '南宁', '海口', '成都',
        '贵阳', '昆明', '西安', '兰州', '西宁', '台北', '呼和浩特', '拉萨', '银川', '乌鲁木齐'
    ]
    # 常见区县关键词
    DISTRICT_KEYWORDS = ['区', '县', '市', '新区', '开发区', '园区']
    # 常见街道关键词
    STREET_KEYWORDS = ['街道', '路', '街', '大道', '巷', '弄', '胡同', '号', '栋', '单元', '楼', '室']
    # 常见地址关键词(需要过滤掉的)
    ADDRESS_KEYWORDS = [
        '公司', '医院', '酒店', '商店', '饭店', '餐馆', '银行', '学校', '工厂', '部门', '小区', '大厦',
        '广场', '中心', '花园', '店铺', '超市', '商场', '市场', '公园', '村', '镇', '乡', '地址'
    ]
    # 常见姓氏
    COMMON_SURNAMES = [
        '王', '李', '张', '刘', '陈', '杨', '赵', '黄', '周', '吴', '徐', '孙', '胡', '朱', '高', '林',
        '何', '郭', '马', '罗', '梁', '宋', '郑', '谢', '韩', '唐', '冯', '于', '董', '萧', '程', '曹',
        '袁', '邓', '许', '傅', '沈', '曾', '彭', '吕', '苏', '卢', '蒋', '蔡', '贾', '丁', '魏', '薛',
        '叶', '阎', '余', '潘', '杜', '戴', '夏', '钟', '汪', '贺', '伽', '栗', '龙', '姜', '雪', '冉'
    ]
    # 姓名关键词
    NAME_KEYWORDS = [
        '收件人', '收货人', '姓名', '联系人', '收', '先生', '女士', '小姐', '老师', '大姐', '师傅'
    ]
    def extract_phone(text: str) -> str:
        """提取电话号码"""
        phone_match = PHONE_PATTERN.search(text)
        return phone_match.group(0) if phone_match else ""
    def extract_province(text: str) -> str:
        """提取省份"""
        for province in PROVINCES:
            if province in text:
                return province
        return ""
    def extract_city(text: str, province: str) -> str:
        """提取城市"""
        # 如果省份是直辖市,则城市就是省份
        if province in ['北京市', '天津市', '上海市', '重庆市']:
            return province.replace('市', '')
       
        # 查找城市
        for city in CITIES:
            if city in text:
                return city
       
        return ""
    def extract_district(text: str) -> str:
        """提取区县"""
        # 使用正则表达式匹配区县名称
        district_pattern = r'([\u4e00-\u9fa5]+?[区县市])'
        matches = re.findall(district_pattern, text)
       
        for match in matches:
            # 排除省份和城市
            if match not in PROVINCES and match not in CITIES:
                return match
       
        return ""
    def extract_street(text: str) -> str:
        """提取街道地址"""
        # 移除已经提取的省份、城市、区县
        cleaned_text = text
       
        # 查找街道关键词
        street_parts = []
        for keyword in STREET_KEYWORDS:
            pattern = r'([\u4e00-\u9fa5\d]+?' + re.escape(keyword) + ')'
            matches = re.findall(pattern, cleaned_text)
            street_parts.extend(matches)
       
        return ' '.join(street_parts)
    def is_likely_name(text: str) -> bool:
        """判断文本是否可能是姓名"""
        if not text:
            return False
       
        # 如果是已确认的姓名,直接返回True
        if text in name_learner.confirmed_names:
            return True
       
        # 检查是否是单个中文字符或英文字母
        if len(text) == 1:
            # 单个中文字符必须是常见姓氏
            if re.match(r'^[\u4e00-\u9fa5]$', text) and text in COMMON_SURNAMES:
                return True
            # 单个英文字母
            if re.match(r'^[a-zA-Z]$', text):
                return True
            return False
       
        # 检查是否是英文名
        if re.match(r'^[a-zA-Z\s]+$', text):
            return True
       
        # 检查是否是中文姓名(2-4个汉字)
        if not re.match(r'^[\u4e00-\u9fa5]{1,4}$', text):
            return False
       
        # 检查是否包含地址关键词
        for keyword in ADDRESS_KEYWORDS:
            if keyword in text:
                return False
       
        # 检查首字符是否是常见姓氏
        if text[0] in COMMON_SURNAMES:
            return True
       
        return False
    def extract_name_directly(text: str) -> str:
        """直接从文本中提取姓名"""
        # 尝试使用jieba提取姓名
        words = pseg.cut(text)
        for word, flag in words:
            if flag == 'nr' and is_likely_name(word):
                return word
       
        # 尝试使用正则表达式匹配姓名
        name_patterns = [
            r'(?:收件人|收货人|姓名|联系人)[::]\s*([\u4e00-\u9fa5a-zA-Z]{1,20})',
            r'([\u4e00-\u9fa5a-zA-Z]{1,20})[\s]*(?:收|先生|女士|小姐|老师|大姐|师傅)',
            r'(?:先生|女士|小姐|老师|大姐|师傅)[::]\s*([\u4e00-\u9fa5a-zA-Z]{1,20})',
            r'([\u4e00-\u9fa5a-zA-Z]{1,20})[\s]*1[3-9]\d{9}',
            r'1[3-9]\d{9}[\s]*([\u4e00-\u9fa5a-zA-Z]{1,20})',
            r'^([\u4e00-\u9fa5a-zA-Z]{1,20})[\s]*(?:,|,|\.|。)',
            r'(?:,|,|\.|。)[\s]*([\u4e00-\u9fa5a-zA-Z]{1,20})[\s]*$',
        ]
       
        for pattern in name_patterns:
            match = re.search(pattern, text, re.IGNORECASE)
            if match:
                candidate = match.group(1).strip()
                if is_likely_name(candidate):
                    return candidate
       
        return ""
    def extract_name_by_removing_parts(text: str) -> str:
        """通过移除其他部分来提取姓名"""
        # 先移除电话号码
        phone = extract_phone(text)
        if phone:
            text = text.replace(phone, '')
       
        # 移除省份
        province = extract_province(text)
        if province:
            text = text.replace(province, '')
       
        # 移除城市
        city = extract_city(text, province)
        if city:
            text = text.replace(city, '')
       
        # 移除区县
        district = extract_district(text)
        if district:
            text = text.replace(district, '')
       
        # 移除街道
        street = extract_street(text)
        if street:
            text = text.replace(street, '')
       
        # 移除地址关键词
        for keyword in ADDRESS_KEYWORDS:
            text = text.replace(keyword, '')
       
        # 移除特殊字符和数字
        text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z]', ' ', text)
        text = re.sub(r'\s+', ' ', text).strip()
       
        # 尝试提取可能的姓名
        words = text.split()
        for word in words:
            if is_likely_name(word):
                return word
       
        return ""
    def extract_name(text: str) -> str:
        """提取姓名"""
        # 先尝试直接提取
        name = extract_name_directly(text)
        if name:
            return name
       
        # 如果直接提取失败,尝试通过移除其他部分来提取
        return extract_name_by_removing_parts(text)
    def parse_address(text: str) -> Dict[str, Any]:
        """解析地址文本,提取姓名、电话和地址信息"""
        if not isinstance(text, str):
            text = str(text) if text is not None else ''
       
        original_text = text
       
        # 1. 提取电话
        phone = extract_phone(text)
       
        # 2. 提取姓名
        name = extract_name(text)
       
        # 3. 提取省份
        province = extract_province(text)
       
        # 4. 提取城市
        city = extract_city(text, province)
       
        # 5. 提取区县
        district = extract_district(text)
       
        # 6. 提取街道地址
        street = extract_street(text)
       
        # 构建完整的地址
        address_parts = []
        if province:
            address_parts.append(province)
        if city:
            address_parts.append(city)
        if district:
            address_parts.append(district)
        if street:
            address_parts.append(street)
       
        full_address = ' '.join(address_parts)
       
        return {
            "姓名": name,
            "电话": phone,
            "省份": province,
            "城市": city,
            "区县": district,
            "街道": street,
            "完整地址": full_address,
            "原始文本": original_text
        }
    # -------------------- 2. 商家编码匹配 --------------------
    CODE_PATTERN = re.compile(r'[A-Z0-9]+', re.I)
    def build_code_dict(code_df: pd.DataFrame) -> Dict[str, str]:
        """构建商家编码映射字典"""
        mapping = {}
        for _, row in code_df.iterrows():
            code = str(row.get("商家编码", "")).strip()
            if not code:
                continue
                
            for cell in row.astype(str):
                for key in CODE_PATTERN.findall(str(cell).upper()):
                    if key and key not in mapping:
                        mapping[key] = code
        return mapping
    def match_code(df: pd.DataFrame, code_dict: Dict[str, str]) -> pd.DataFrame:
        """在备注列中匹配商家编码"""
        def lookup(remark):
            if pd.isna(remark):
                return None
            for token in CODE_PATTERN.findall(str(remark).upper()):
                if token in code_dict:
                    return code_dict[token]
            return None
       
        if "备注" in df.columns:
            df["商家编码"] = df["备注"].apply(lookup)
        else:
            print("⚠️  警告:数据文件中没有找到'备注'列,跳过商家编码匹配")
            df["商家编码"] = None
            
        return df
    # -------------------- 3. 入库情况标记 --------------------
    def get_inbound_set(inbound_df: pd.DataFrame) -> Set[str]:
        """获取所有入库单号的集合"""
        return set(inbound_df.astype(str).stack().str.strip().dropna())
    def mark_inbound(df: pd.DataFrame, inbound_set: Set[str]) -> pd.DataFrame:
        """标记入库情况"""
        if "寄回单号" in df.columns:
            df["入库情况"] = df["寄回单号"].apply(
                lambda x: "已入库" if (pd.notna(x) and str(x).strip() in inbound_set) else "未入库"
            )
        else:
            print("⚠️  警告:数据文件中没有找到'寄回单号'列,跳过入库标记")
            df["入库情况"] = "未知"
            
        return df
    # -------------------- 4. 处理函数 --------------------
    def process_files(input_file, code_file, inbound_file, address_col, progress_callback=None):
        """处理文件的主函数"""
        try:
            # 读取数据
            df = pd.read_excel(input_file)
            code_df = pd.read_excel(code_file)
            inbound_df = pd.read_excel(inbound_file)
        except Exception as e:
            return False, f"读取文件时出错:{e}", None
       
        if progress_callback:
            progress_callback(10, "开始解析地址信息...")
       
        # 解析地址列
        target_col = address_col
        if target_col >= len(df.columns):
            return False, f"错误:指定的地址列索引 {target_col} 超出范围(0-{len(df.columns)-1})", None
       
        # 添加原始文本列以便调试
        df["原始地址文本"] = df.iloc[:, target_col]
       
        # 解析地址
        total_rows = len(df)
        parsed_results = []
        for i, text in enumerate(df.iloc[:, target_col]):
            parsed_results.append(parse_address(text))
            if progress_callback and i % 10 == 0:
                progress = 10 + int(70 * i / total_rows)
                progress_callback(progress, f"解析地址信息... ({i}/{total_rows})")
       
        parsed_df = pd.DataFrame(parsed_results)
        df["解析姓名"] = parsed_df["姓名"]
        df["解析电话"] = parsed_df["电话"]
        df["解析省份"] = parsed_df["省份"]
        df["解析城市"] = parsed_df["城市"]
        df["解析区县"] = parsed_df["区县"]
        df["解析街道"] = parsed_df["街道"]
        df["解析地址"] = parsed_df["完整地址"]
       
        if progress_callback:
            progress_callback(80, "匹配商家编码...")
       
        # 匹配商家编码
        code_dict = build_code_dict(code_df)
        df = match_code(df, code_dict)
       
        if progress_callback:
            progress_callback(90, "标记入库情况...")
       
        # 标记入库情况
        inbound_set = get_inbound_set(inbound_df)
        df = mark_inbound(df, inbound_set)
       
        # 生成输出文件名
        input_dir = os.path.dirname(input_file)
        input_name = os.path.splitext(os.path.basename(input_file))[0]
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_file = os.path.join(input_dir, f"{input_name}_处理完成_{timestamp}.xlsx")
       
        # 保存结果
        try:
            df.to_excel(output_file, index=False)
            
            # 自动学习提取的姓名
            learned_count = 0
            for name in df["解析姓名"].dropna().unique():
                if isinstance(name, str) and (re.match(r'^[\u4e00-\u9fa5]{1,4}$', name) or re.match(r'^[a-zA-Z\s]+$', name)):
                    name_learner.add_confirmed_name(name)
                    learned_count += 1
            
            # 保存确认的姓名
            name_learner.save_confirmed_names()
            
            return True, f"处理完成,结果已保存为:{output_file}", output_file
        except Exception as e:
            return False, f"保存文件时出错:{e}", None
    # -------------------- 5. 配置文件管理 --------------------
    def load_config():
        """加载配置文件"""
        config = configparser.ConfigParser()
        if os.path.exists('config.ini'):
            config.read('config.ini', encoding='utf-8')
        return config
    def save_config(config):
        """保存配置文件"""
        with open('config.ini', 'w', encoding='utf-8') as configfile:
            config.write(configfile)
    # -------------------- 6. GUI界面 --------------------
    class AddressParserApp:
        def __init__(self, root):
            self.root = root
            self.root.title("地址信息解析工具")
            self.root.geometry("600x450")
            
            # 文件路径变量
            self.input_file = tk.StringVar()
            self.code_file = tk.StringVar()
            self.inbound_file = tk.StringVar()
            self.address_col = tk.IntVar(value=2)  # 默认地址列索引为2
            
            # 加载配置文件
            self.config = load_config()
            if 'FILES' in self.config:
                if 'code_file' in self.config['FILES']:
                    self.code_file.set(self.config['FILES']['code_file'])
                if 'inbound_file' in self.config['FILES']:
                    self.inbound_file.set(self.config['FILES']['inbound_file'])
                if 'address_col' in self.config['FILES']:
                    self.address_col.set(int(self.config['FILES']['address_col']))
            
            # 最近处理完成的文件
            self.last_output_file = None
            
            # 创建界面
            self.create_widgets()
       
        def create_widgets(self):
            # 主框架
            main_frame = ttk.Frame(self.root, padding="10")
            main_frame.pack(fill=tk.BOTH, expand=True)
            
            # 输入文件选择
            ttk.Label(main_frame, text="数据文件:").grid(row=0, column=0, sticky=tk.W, pady=5)
            ttk.Entry(main_frame, textvariable=self.input_file, width=50).grid(row=0, column=1, padx=5)
            ttk.Button(main_frame, text="浏览", command=self.browse_input_file).grid(row=0, column=2)
            
            # 编码文件选择
            ttk.Label(main_frame, text="编码文件:").grid(row=1, column=0, sticky=tk.W, pady=5)
            ttk.Entry(main_frame, textvariable=self.code_file, width=50).grid(row=1, column=1, padx=5)
            ttk.Button(main_frame, text="浏览", command=self.browse_code_file).grid(row=1, column=2)
            
            # 入库文件选择
            ttk.Label(main_frame, text="入库文件:").grid(row=2, column=0, sticky=tk.W, pady=5)
            ttk.Entry(main_frame, textvariable=self.inbound_file, width=50).grid(row=2, column=1, padx=5)
            ttk.Button(main_frame, text="浏览", command=self.browse_inbound_file).grid(row=2, column=2)
            
            # 地址列设置
            ttk.Label(main_frame, text="地址列索引:").grid(row=3, column=0, sticky=tk.W, pady=5)
            ttk.Spinbox(main_frame, from_=0, to=20, textvariable=self.address_col, width=10).grid(row=3, column=1, sticky=tk.W, padx=5)
            ttk.Label(main_frame, text="(从0开始)").grid(row=3, column=1, sticky=tk.E, padx=5)
            
            # 进度条
            self.progress = ttk.Progressbar(main_frame, orient=tk.HORIZONTAL, length=500, mode='determinate')
            self.progress.grid(row=4, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
            
            # 状态标签
            self.status_label = ttk.Label(main_frame, text="准备就绪")
            self.status_label.grid(row=5, column=0, columnspan=3, pady=5)
            
            # 按钮框架
            button_frame = ttk.Frame(main_frame)
            button_frame.grid(row=6, column=0, columnspan=3, pady=10)
            
            ttk.Button(button_frame, text="开始处理", command=self.start_processing).pack(side=tk.LEFT, padx=5)
            ttk.Button(button_frame, text="打开已完成文件", command=self.open_output_file).pack(side=tk.LEFT, padx=5)
            ttk.Button(button_frame, text="退出", command=self.root.quit).pack(side=tk.LEFT, padx=5)
            
            # 配置网格权重
            main_frame.columnconfigure(1, weight=1)
       
        def browse_input_file(self):
            filename = filedialog.askopenfilename(title="选择数据文件", filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")])
            if filename:
                self.input_file.set(filename)
       
        def browse_code_file(self):
            filename = filedialog.askopenfilename(title="选择编码文件", filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")])
            if filename:
                self.code_file.set(filename)
                # 保存到配置文件
                if 'FILES' not in self.config:
                    self.config['FILES'] = {}
                self.config['FILES']['code_file'] = filename
                save_config(self.config)
       
        def browse_inbound_file(self):
            filename = filedialog.askopenfilename(title="选择入库文件", filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")])
            if filename:
                self.inbound_file.set(filename)
                # 保存到配置文件
                if 'FILES' not in self.config:
                    self.config['FILES'] = {}
                self.config['FILES']['inbound_file'] = filename
                save_config(self.config)
       
        def update_progress(self, value, message):
            self.progress['value'] = value
            self.status_label['text'] = message
            self.root.update_idletasks()
       
        def start_processing(self):
            # 验证输入
            if not all([self.input_file.get(), self.code_file.get(), self.inbound_file.get()]):
                messagebox.showerror("错误", "请选择所有必要的文件")
                return
            
            # 保存地址列索引到配置文件
            if 'FILES' not in self.config:
                self.config['FILES'] = {}
            self.config['FILES']['address_col'] = str(self.address_col.get())
            save_config(self.config)
            
            # 禁用按钮,防止重复点击
            self.progress['value'] = 0
            self.status_label['text'] = "开始处理..."
            
            # 在新线程中处理文件,避免界面卡死
            thread = threading.Thread(target=self.process_files_thread)
            thread.daemon = True
            thread.start()
       
        def process_files_thread(self):
            try:
                success, message, output_file = process_files(
                    self.input_file.get(),
                    self.code_file.get(),
                    self.inbound_file.get(),
                    self.address_col.get(),
                    self.update_progress
                )
                
                if success:
                    self.last_output_file = output_file
                    self.update_progress(100, message)
                    messagebox.showinfo("成功", message)
                else:
                    self.update_progress(0, "处理失败")
                    messagebox.showerror("错误", message)
                   
            except Exception as e:
                self.update_progress(0, "处理失败")
                messagebox.showerror("错误", f"处理过程中发生错误: {str(e)}")
       
        def open_output_file(self):
            """打开已完成文件"""
            if self.last_output_file and os.path.exists(self.last_output_file):
                try:
                    os.startfile(self.last_output_file)  # Windows
                except:
                    try:
                        # macOS
                        os.system(f'open "{self.last_output_file}"')
                    except:
                        try:
                            # Linux
                            os.system(f'xdg-open "{self.last_output_file}"')
                        except:
                            messagebox.showerror("错误", "无法打开文件,请手动打开")
            else:
                # 如果没有最近处理的文件,让用户选择要打开的文件
                filename = filedialog.askopenfilename(
                    title="选择要打开的文件",
                    filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")],
                    initialdir=os.path.dirname(self.input_file.get()) if self.input_file.get() else "."
                )
                if filename:
                    try:
                        os.startfile(filename)  # Windows
                    except:
                        try:
                            # macOS
                            os.system(f'open "{filename}"')
                        except:
                            try:
                                # Linux
                                os.system(f'xdg-open "{filename}"')
                            except:
                                messagebox.showerror("错误", "无法打开文件,请手动打开")
    # -------------------- 7. 主函数 --------------------
    def main():
        # 直接启动GUI模式
        root = tk.Tk()
        app = AddressParserApp(root)
        root.mainloop()
    if __name__ == "__main__":
        main()

    文件, 姓名

  • ovioni   

    精品区是发成品的地方,你需要编译一个成品传到网盘贴一下地址到帖子中。
    mmr700   

    公司是离线环境,不知道会影响正常使用吗? 谢谢
    mmr700   

    看标题还以为是提取抖音微信视频的真实下载地址呢
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部