使用python和re库读取vcf文件数据

使用python和re库读取vcf文件数据,python,vcf-vcard,Python,Vcf Vcard,下面是.vcf文件数据中的内容 BEGIN:VCARD VERSION:4.0 N:Muller;CCCIsabella;;; FN:Muller ORG:Bubba Gump Shrimp Co. TITLE:Shrimp Man PHOTO;MEDIATYPE=image/gif:http://www.example.com/dir_photos/my_photo.gif TEL;TYPE=work,voice;VALUE=uri:tel:+16829185770 REV:20080424T

下面是.vcf文件数据中的内容

BEGIN:VCARD
VERSION:4.0
N:Muller;CCCIsabella;;;
FN:Muller
ORG:Bubba Gump Shrimp Co.
TITLE:Shrimp Man
PHOTO;MEDIATYPE=image/gif:http://www.example.com/dir_photos/my_photo.gif
TEL;TYPE=work,voice;VALUE=uri:tel:+16829185770
REV:20080424T195243Z
END:VCARD

BEGIN:VCARD
VERSION:4.0
N:Mraz;CCCEdwardo;;;
FN:Mraz
ORG:Bubba Gump Shrimp Co.
TITLE:Shrimp Man
PHOTO;MEDIATYPE=image/gif:http://www.example.com/dir_photos/my_photo.gif
TEL;TYPE=work,voice;VALUE=uri:tel:+18083155095
REV:20080424T195243Z
END:VCARD

BEGIN:VCARD
VERSION:4.0
N:Reynolds;CCCBrant;;;
FN:Reynolds
ORG:Bubba Gump Shrimp Co.
TITLE:Shrimp Man
PHOTO;MEDIATYPE=image/gif:http://www.example.com/dir_photos/my_photo.gif
TEL;TYPE=work,voice;VALUE=uri:tel:+15089473508
REV:20080424T195243Z
END:VCARD
我希望我的数据如下所示

data = [{'name': 'Muller','phone': '+16829185770'}, {'name': 'Mraz', 'phone': '+18083155095'}, {'name': 'Reynolds','phone': '+15089473508'}]
但我没有得到上述数据。请帮我解决这个问题。这里我使用re-python包来解决这个问题

import re
file = open('contacts.vcf', 'r')
contacts = []
for line in file:
    name = re.findall('FN:(.*)', line)
    tel = re.findall('tel:(.*)', line)
    nm = ''.join(name)
    tel = ''.join(tel)
    if len(nm) == 0 and len(tel) == 0:
        continue
    data = {'name' : nm, 'phone' : tel}
    contacts.append(data)
print(contacts)
下面的结果显示姓名和电话的添加方式不同

[{'name': 'Muller', 'phone': ''}, {'name': '', 'phone': '+16829185770'}, {'name': 'Mraz', 'phone': ''}, {'name': '', 'phone': '+18083155095'}, {'name': 'Reynolds', 'phone': ''}, {'name': '', 'phone': '+15089473508'}]

通常在调试时,在不同的位置使用
print
来找出代码哪里出错是很有用的。例如,如果在
tel=''之后插入
print(“>”,nm,tel)
。加入(tel)
,则应获得以下输出:

>  
>  
>  
> Muller 
>  
>  
>  
>  +16829185770
>  
>  
>  
>  
>  
>  
> Mraz 
>  
[... continued...]
显然,这是因为您的
for
循环在文件中的每一行而不是每一张卡上运行(技术上,您甚至承认这一点:
for line in file:

您可能有兴趣使用一个模块来解析这个文件(谷歌快速推出了
vobject
包),这样就不需要
re
。如果您有雄心壮志,您可以手动解析它(不太熟悉格式,所以这里有一个现成的示例)

CARDMATCHER=re.compile(r”“”
^##行首匹配(多行标志)
BEGIN:VCARD##精确匹配字符串“BEGIN:VCARD”
$##匹配行尾(多行标志)
*?##匹配字符(.)任意次数(*),
##尽可能少的次数(?),包括新行(Dotall标志)
^##行首匹配(多行标志)
END:VCARD##精确匹配字符串“END:VCARD”
$##匹配行尾(多行标志)
“”,re.MULTILINE | re.DOTALL | re.VERBOSE)
VALUERE=re.compile(“”)
^(?P[A-Z]+)##在行首匹配大写Ascii字符
(?P:|)匹配冒号或分号
(?P.*)##匹配剩余的所有其他字符
“”,re.VERBOSE)
类MyVCard():
def uuu init uuu(self,cardstring):
self.info=defaultdict(列表)
##像刚才那样在卡片上迭代
对于cardstring.split(“\n”)中的行:
##分线键
匹配=估值器。匹配(行)
如果匹配:
vtype=match.group(“类型”)
##行值用分号分隔
values=match.group(“值”).split(;)
##带有冒号的行似乎是唯一的值
如果匹配。组(“sep”)==:“:
##如果只有一个值,我们不需要列表
如果len(值)==1:
self.info[vtype]=值[0]
其他:
self.info[vtype]=值
##否则(分号sep),该值可能不唯一
其他:
##分号sep似乎也有多个键
##所以我们将使用dict
out={}
对于值中的val:
##获取键,每个值的值
k、 v=val.split(“=”,maxslit=1)
out[k]=v
##确保我们有一个附加的列表
self.info[vtype].append(out)
def获取一个def编号(自身):
“获取数字的简单方法”
如果self.info中的“电话”:
number=self.info[“TEL”][0][“VALUE”]
编号=关于findall(“电话:(.+)”,编号)
如果是数字:
返回号码[0]
一无所获
def get_vcards(文件):
“”“使用正则表达式将vCard解析为dict。”“”
打开(文件,'r')作为f:
finput=f.read()
cards=CARDMATCHER.findall(finput)
返回[卡中卡的MyVCard(卡)]
打印([{“fn”:card.info['fn'],“tel”:card.get_a_number()}用于get_vcards(文件)]中的卡)

同样,我对这段代码不做任何保证,因为我不打算查找
vcf
格式的所有规范,建议使用专门为此设计的模块。

您可以尝试下面的代码

import re
file = open('vcards-2.vcf', 'r')
contacts = []
phone = []
for line in file:
    name = re.findall('FN:(.*)', line)
    nm = ''.join(name)
    if len(nm) == 0:
        continue

    data = {'name' : nm.strip()}
    for lin in file:
        tel = re.findall('pref:(.*)', lin)
        tel = ''.join(tel)

        if len(tel) == 0:
            continue

        tel = tel.strip()
        tel = ''.join(e for e in tel if e.isalnum())
        data['phone'] = tel
        break
    contacts.append(data)

print(contacts)
你将得到以下结果

[{'name': 'Muller','phone': '+16829185770'}, {'name': 'Mraz', 'phone': '+18083155095'}, {'name': 'Reynolds','phone': '+15089473508'}]

棒极了,简单明了。谢谢对于任何在这个问题上遇到障碍的人,我建议遵循里德·巴拉德的建议,使用一个专用模块来解析VCF文件,比如or,它最适合我的需要
[{'name': 'Muller','phone': '+16829185770'}, {'name': 'Mraz', 'phone': '+18083155095'}, {'name': 'Reynolds','phone': '+15089473508'}]