codeaftercode 发表于 2023-5-4 09:49

通讯录vcf文件转csv

本帖最后由 codeaftercode 于 2023-5-4 09:55 编辑

从手机导出通讯录,是一个vcf格式的文件,无法直接导入excel进行处理,所以我用python转换成csv格式

预处理
但是这段代码并不完善,比如vcf文件中有时会出现跨行的数据,我的代码就不能处理,需要提前手动将换行数据合并为一行,并删除行末行首连接处中间多余的等号

上图就是有跨行数据,要先手动合并成一行,然后中间有两个等号==,删掉一个留下一个,变成这样:


转换过程
转换过程中会自动识别vcf文件中的所有字段,把每个字段转换成csv的一列
如果vcf的一个字段包含多条数据,则转换为csv的一列时,多条数据合并为一条,中间用分号分隔,如:
TEL;CELL:13012345678
TEL;CELL:13112345678
将被转换为csv中的一列,列名为tel,单元格的内容为13012345678;13112345678

后续处理
转换结束后会生成一个csv文件,因为代码中字符集没有处理好,所以如果通过双击csv文件的方式打开excel,有时显示乱码,可以先打开excel软件,点击数据-来自文件-选中csv文件。注意分隔符选择逗号。


最后,上代码:

import os
import vobject
import csv

# 读取vcf文件,输出csv文件

def work(inputFile, outputFile):
    # Reading the vcf file
    with open(inputFile, 'r', encoding='gbk') as f:
      contacts = f.read()

    # 读取1条记录
    # vcard = vobject.readOne(contacts)
    # print(vcard)
    # print(vcard.behavior)
    # print(vcard.contents['tel'])
    # print(type(vcard.contents))
    # keys = vcard.contents.keys()
    # print(keys)

    try:
      # 获取所有vcard的keys
      index = 0
      allKeys = []
      vcards = vobject.readComponents(contacts)
      for vcard in vcards:
            index += 1
            # print('==========')
            # print(index)
            # 取出所有的key
            keys = vcard.contents.keys()
            # print(keys)
            for key in keys:
                if key not in allKeys:
                  allKeys.append(key)
                # valueCount = len(vcard.contents)
                # if valueCount > 1:
                #   print(f'key:{key},value:{vcard.contents},type:{type(vcard.contents)},count:{valueCount}')# 全是list类型
      print(f'allKeys:{allKeys}')

      # 再次遍历,按keys提取数据,写入csv
      with open(outputFile, 'w', newline='', encoding='gbk') as f:
            writer = csv.writer(f)
            writer.writerow(allKeys)
            vcards = vobject.readComponents(contacts)
            for vcard in vcards:
                row = []
                for key in allKeys:
                  if key in vcard.contents.keys():
                        content = vcard.contents#每个content都是list类型
                        tmp = ''
                        for item in content:
                            if item.value is not None:
                              tmp += str(item.value) + ';'
                        row.append(tmp[:-1])
                        # row.append(tmp)
                  else:
                        row.append('')
                print(row)
                writer.writerow(row)

    except Exception as e:
      print("An error occurred:", e)

if '__main__' == __name__:
   
    # Set the working directory to the current file's directory
    os.chdir(os.path.dirname(os.path.abspath(__file__)))

    inputFile = 'contacts.vcf'
    outputFile = 'output.csv'
    work(inputFile, outputFile)


尽管代码很粗糙,我还是发上来了,请大佬们帮我改进一下,比如跨行问题、字符集问题,或其他问题,不胜感激{:1_893:}

zky666 发表于 2023-5-4 11:50

我是直接改后缀名,就可以修改了。

jasper212 发表于 2023-5-4 12:00

應該還能再完善,謝謝分享

刘统宝 发表于 2023-5-4 12:14

期待更完善的版本

52pojie2018 发表于 2023-5-4 13:01

期待楼主完善, 一直想在电脑上直接查看通讯录文件

kissfox 发表于 2023-5-4 13:30

zky666 发表于 2023-5-4 11:50
我是直接改后缀名,就可以修改了。

根据多次测试发现,并不是所有的vcf导出数据无法使用excel修改,需要看手机品牌的,比如华为的导出通过excel改了后苹果不能导入,能导入也是乱码。

hushxh 发表于 2023-5-4 14:08

不懂,帮顶

weiyanli 发表于 2023-5-4 14:11

感谢大佬分享

ilovei 发表于 2023-5-4 14:24

期待更完善的版本

tslace 发表于 2023-5-4 14:42

早几年出来就好了。。。我之前都是用邮箱转- -#。老费劲了。
页: [1] 2
查看完整版本: 通讯录vcf文件转csv