Python的Imaplib中解析括号的清单
题
我正在寻找简单的方法来将IMAP响应的括号列表拆分为Python列表或元组。我想去
'(BODYSTRUCTURE ("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 1207 50 NIL NIL NIL NIL))'
至
(BODYSTRUCTURE, ("text", "plain", ("charset", "ISO-8859-1"), None, None, "quoted-printable", 1207, 50, None, None, None, None))
解决方案
默认情况下,PyparSing的NestedExpR解析器函数嵌套括号:
from pyparsing import nestedExpr
text = '(BODYSTRUCTURE ("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quotedprintable" 1207 50 NIL NIL NIL NIL))'
print nestedExpr().parseString(text)
印刷:
[['BODYSTRUCTURE', ['"text"', '"plain"', ['"charset"', '"ISO-8859-1"'], 'NIL', 'NIL', '"quoted printable"', '1207', '50', 'NIL', 'NIL', 'NIL', 'NIL']]]
这是一个稍微修改的解析器,它可以将整数字符串从“ nil”到无,并从引用字符串中剥离引号:
from pyparsing import (nestedExpr, Literal, Word, alphanums,
quotedString, replaceWith, nums, removeQuotes)
NIL = Literal("NIL").setParseAction(replaceWith(None))
integer = Word(nums).setParseAction(lambda t:int(t[0]))
quotedString.setParseAction(removeQuotes)
content = (NIL | integer | Word(alphanums))
print nestedExpr(content=content, ignoreExpr=quotedString).parseString(text)
印刷:
[['BODYSTRUCTURE', ['text', 'plain', ['charset', 'ISO-8859-1'], None, None, 'quoted-printable', 1207, 50, None, None, None, None]]]
其他提示
仅取出服务器的内部部分答案,其中包含实际的身体结构:
struct = ('(((("TEXT" "PLAIN" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 16 2)'
'("TEXT" "HTML" ("CHARSET" "ISO-8859-1") NIL NIL "QUOTED-PRINTABLE"'
' 392 6) "ALTERNATIVE")("IMAGE" "GIF" ("NAME" "538.gif") '
'"<538@goomoji.gmail>" NIL "BASE64" 172)("IMAGE" "PNG" ("NAME" '
'"4F4.png") "<gtalk.4F4@goomoji.gmail>" NIL "BASE64" 754) "RELATED")'
'("IMAGE" "JPEG" ("NAME" "avatar_airbender.jpg") NIL NIL "BASE64"'
' 157924) "MIXED")')
下一步是替换一些代币,将prepair字符串转换为python类型:
struct = struct.replace(' ', ',').replace(')(', '),(')
使用内置模块 编译器 解析我们的结构:
import compiler
expr = compiler.parse(struct.replace(' ', ',').replace(')(', '),('), 'eval')
执行简单的递归函数转换表达:
def transform(expression):
if isinstance(expression, compiler.transformer.Expression):
return transform(expression.node)
elif isinstance(expression, compiler.transformer.Tuple):
return tuple(transform(item) for item in expression.nodes)
elif isinstance(expression, compiler.transformer.Const):
return expression.value
elif isinstance(expression, compiler.transformer.Name):
return None if expression.name == 'NIL' else expression.name
最后,我们得到了所需的结果作为嵌套的python元素:
result = transform(expr)
print result
(((('TEXT', 'PLAIN', ('CHARSET', 'ISO-8859-1'), None, None, '7BIT', 16, 2), ('TEXT', 'HTML', ('CHARSET', 'ISO-8859-1'), None, None, 'QUOTED-PRINTABLE', 392, 6), 'ALTERNATIVE'), ('IMAGE', 'GIF', ('NAME', '538.gif'), '<538@goomoji.gmail>', None, 'BASE64', 172), ('IMAGE', 'PNG', ('NAME', '4F4.png'), '<gtalk.4F4@goomoji.gmail>', None, 'BASE64', 754), 'RELATED'), ('IMAGE', 'JPEG', ('NAME', 'avatar_airbender.jpg'), None, None, 'BASE64', 157924), 'MIXED')
从那里我们可以识别身体结构的不同标头:
text, attachments = (result[0], result[1:])
有嵌套的元素使这一事实使得正则是不可能的。当您不在括号中时,您必须写一个解析器来表示。
你可以尝试
tuple('(BODYSTRUCTURE ("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 1207 50 NIL NIL NIL NIL))'.replace("NIL", "None").split(' '))
编辑:好吧,我得到了与您的示例一起使用的东西,不确定这是您想要的。
身体结构需要在某个地方定义。
eval(",".join([a for a in '(BODYSTRUCTURE ("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 1207 50 NIL NIL NIL NIL))'.replace("NIL", "None").split(' ')]))
不隶属于 StackOverflow