Python实现获取手机通讯录文件并导出为excel

 更新时间:2026年01月06日 09:49:53   作者:高山莫衣  
这篇文章主要为大家详细介绍了如何通过Python实现获取手机通讯录文件并导出为excel表格,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下

核心功能与解决的实际问题

这段代码的核心功能是解析从手机导出的VCF格式通讯录文件,并将其中的联系人信息(如姓名、电话号码、邮箱等)转换并保存为结构清晰、易于编辑的Excel表格。它专门解决了VCF文件(vCard格式)用文本编辑器查看杂乱无章、无法直接筛选或批量编辑的痛点,使得备份的通讯录数据变得可读、可管理。

完整的联系人信息提取与导出流程

程序能够系统性地遍历VCF文件,识别每个以"BEGIN:VCARD"开始、“END:VCARD"结束的联系人数据块,并从中提取关键字段。解析出的信息会结构化地存入数据集合,最后利用pandas库生成包含"姓名”、“电话”、"邮箱"等列的Excel文件(.xlsx格式),确保所有联系信息一目了然,方便后续的查找、编辑或导入其他设备。

实现代码

import vobject
import chardet
import pandas as pd
import os

def debug_vcf_file(file_path):
    """
    调试VCF文件:检查编码、文件结构和内容
    """
    print("=== 开始调试VCF文件 ===")
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"错误:文件 '{file_path}' 不存在")
        return False
    
    # 检查文件大小
    file_size = os.path.getsize(file_path)
    print(f"文件大小: {file_size} 字节")
    
    if file_size == 0:
        print("错误:文件为空")
        return False
    
    # 读取原始字节数据
    with open(file_path, 'rb') as f:
        raw_data = f.read()
    
    # 检测编码
    encoding_result = chardet.detect(raw_data)
    detected_encoding = encoding_result['encoding']
    confidence = encoding_result['confidence']
    
    print(f"检测到的编码: {detected_encoding} (置信度: {confidence:.2f})")
    
    # 尝试不同编码
    encodings_to_try = [detected_encoding, 'gbk', 'gb2312', 'utf-8', 'iso-8859-1']
    
    for encoding in encodings_to_try:
        if not encoding:
            continue
        try:
            content = raw_data.decode(encoding)
            print(f"✓ 成功使用 {encoding} 编码解码")
            
            # 检查VCF基本结构
            if 'BEGIN:VCARD' in content and 'END:VCARD' in content:
                vcard_count = content.count('BEGIN:VCARD')
                print(f"找到 {vcard_count} 个联系人卡片")
                
                # 显示前500个字符作为样本
                sample = content[:500]
                print("文件内容样本:")
                print("---" + sample + "---")
                
                return True, content, encoding
            else:
                print(f"× 使用 {encoding} 解码但未找到VCARD结构")
                
        except UnicodeDecodeError as e:
            print(f"× {encoding} 编码解码失败: {e}")
        except Exception as e:
            print(f"× {encoding} 处理过程中出错: {e}")
    
    # 最后尝试忽略错误模式
    try:
        content = raw_data.decode('utf-8', errors='ignore')
        print("最后尝试:使用UTF-8忽略错误模式解码")
        return True, content, 'utf-8 (errors ignored)'
    except Exception as e:
        print(f"最终解码失败: {e}")
        return False, None, None

def parse_vcf_with_debug(file_path):
    """
    解析VCF文件并生成Excel表格
    """
    # 调试文件
    debug_result, vcf_content, used_encoding = debug_vcf_file(file_path)
    
    if not debug_result:
        print("文件调试失败,无法继续解析")
        return []
    
    contacts = []
    print(f"\n=== 开始解析VCF内容(使用编码: {used_encoding})===")
    
    try:
        # 分割vCard块
        vcard_blocks = vcf_content.split('BEGIN:VCARD')
        
        for i, block in enumerate(vcard_blocks):
            if not block.strip() or 'END:VCARD' not in block:
                continue
                
            # 重新构建完整的vCard
            vcard_text = 'BEGIN:VCARD' + block
            
            try:
                vcard = vobject.readOne(vcard_text)
                contact_info = {'序号': i}
                
                # 提取姓名
                if hasattr(vcard, 'fn') and vcard.fn:
                    contact_info['姓名'] = str(vcard.fn.value)
                    print(f"联系人 {i}: 找到姓名 - {vcard.fn.value}")
                else:
                    contact_info['姓名'] = '未知'
                    print(f"联系人 {i}: 未找到姓名字段")
                
                # 提取电话
                contact_info['电话'] = ''
                if hasattr(vcard, 'tel'):
                    phones = []
                    if isinstance(vcard.tel, list):
                        for tel in vcard.tel:
                            if hasattr(tel, 'value') and tel.value:
                                phones.append(str(tel.value))
                    elif hasattr(vcard.tel, 'value') and vcard.tel.value:
                        phones.append(str(vcard.tel.value))
                    
                    if phones:
                        contact_info['电话'] = '; '.join(phones)
                        print(f"联系人 {i}: 找到电话 - {phones}")
                    else:
                        print(f"联系人 {i}: 找到TEL字段但值为空")
                
                # 提取其他信息
                if hasattr(vcard, 'email'):
                    emails = []
                    if isinstance(vcard.email, list):
                        for email in vcard.email:
                            if email.value:
                                emails.append(str(email.value))
                    elif vcard.email.value:
                        emails.append(str(vcard.email.value))
                    contact_info['邮箱'] = '; '.join(emails) if emails else ''
                
                contacts.append(contact_info)
                print(f"✓ 成功解析联系人 {i}: {contact_info['姓名']}")
                
            except Exception as e:
                print(f"× 解析联系人 {i} 时出错: {e}")
                # 打印出错的vCard内容前200字符用于调试
                print(f"错误vCard样本: {vcard_text[:200]}")
                continue
                
    except Exception as e:
        print(f"解析过程中出现严重错误: {e}")
    
    return contacts

def save_contacts_to_excel(contacts, output_file='contacts.xlsx'):
    """
    将联系人保存到Excel文件
    """
    if not contacts:
        print("没有联系人数据可保存")
        return False
    
    try:
        # 创建DataFrame
        df = pd.DataFrame(contacts)
        
        # 重新排列列顺序
        columns_order = ['序号', '姓名', '电话', '邮箱']
        existing_columns = [col for col in columns_order if col in df.columns]
        df = df[existing_columns]
        
        # 保存到Excel
        df.to_excel(output_file, index=False, engine='openpyxl')
        print(f"✓ 成功生成Excel文件: {output_file}")
        print(f"✓ 共保存 {len(contacts)} 个联系人")
        
        # 显示前几行作为预览
        print("\n前5个联系人预览:")
        print(df.head())
        
        return True
        
    except Exception as e:
        print(f"× 生成Excel文件时出错: {e}")
        return False

# 主执行函数
def main():
    vcf_file_path = "你的通讯录.vcf"  # 请替换为您的VCF文件路径
    
    print("手机VCF联系人解析工具")
    print("=" * 50)
    
    # 解析VCF文件
    contacts_list = parse_vcf_with_debug(vcf_file_path)
    
    if contacts_list:
        # 生成Excel文件
        save_contacts_to_excel(contacts_list)
        
        print(f"\n解析完成!成功处理 {len(contacts_list)} 个联系人")
    else:
        print("\n解析失败,未找到有效联系人")

if __name__ == "__main__":
    main()

效果如下:

以上就是Python实现获取手机通讯录文件并导出为excel的详细内容,更多关于Python获取手机通讯录的资料请关注脚本之家其它相关文章!

相关文章

  • Pandas中case_when()方法使用小结

    Pandas中case_when()方法使用小结

    本文主要介绍了Pandas中case_when()方法使用小结,它可以用于条件性地创建新的列,类似于 SQL 中的 CASE WHEN 语句,下面就来介绍一下,感兴趣的可以了解一下
    2025-05-05
  • Python实现购物车程序

    Python实现购物车程序

    这篇文章主要为大家详细介绍了Python实现购物车程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • Python基于pillow判断图片完整性的方法

    Python基于pillow判断图片完整性的方法

    这篇文章主要介绍了Python基于pillow判断图片完整性的方法,结合实例形式简单分析了pillow的安装及图片完整性判断的相关操作技巧,需要的朋友可以参考下
    2016-09-09
  • python中__slots__用法实例

    python中__slots__用法实例

    这篇文章主要介绍了python中__slots__用法,实例分析了__slots__的功能与相关使用技巧,需要的朋友可以参考下
    2015-06-06
  • Gradio机器学习模型快速部署工具接口状态

    Gradio机器学习模型快速部署工具接口状态

    这篇文章主要为大家介绍了Gradio机器学习模型快速部署工具接口状态的原文翻译,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 基于Python开发一个小说图片PDF生成器

    基于Python开发一个小说图片PDF生成器

    本项目是一个基于 wxPython 开发的桌面应用程序,用于将图片和文字描述组合生成精美的 PDF 小说,它解决了创作者需要将图文内容快速整理成电子书的需求,特别适合绘本、图文小说、摄影作品集等场景,需要的朋友可以参考下
    2025-10-10
  • 基于tkinter中ttk控件的width-height设置方式

    基于tkinter中ttk控件的width-height设置方式

    这篇文章主要介绍了基于tkinter中ttk控件的width-height设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Python中的闭包装饰器和深浅拷贝案例演示

    Python中的闭包装饰器和深浅拷贝案例演示

    本文给大家介绍Python中的闭包装饰器和深浅拷贝,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-09-09
  • playwright日期控件的具体使用

    playwright日期控件的具体使用

    本文主要介绍了playwright日期控件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-01-01
  • python读取图片并修改格式与大小的方法

    python读取图片并修改格式与大小的方法

    这篇文章主要为大家详细介绍了python读取图片并修改格式与大小的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07

最新评论