我有以下输入。我想将其解析为CSV分隔的字符串。我可以通过正则表达式模式获得SKU,但由于我是正则表达式解析的新手,我不知道复杂的模式。如果有人能帮我解决这个问题会很好。
谢谢!
charset="iso-8859-1"
BODY {
}
TD {
}
TH {
}
H1 {
}
TABLE,IMG,A {
}
**PO Number:** 35102
**Ship To:**
Georgie Clements
6902 Stonegate Drive
Odessa, TX 79765
432-363-8459
SKU
Product
Qty
JJ-Rug-Zebra-PK
Zebra Pink Rug
1
JJ-Zebra-PK-Twin-4
Zebra Pink 4 Piece Twin Comforter Set
1
JJ-TwinSheets-Zebra-PK
Zebra Pink 3 Piece Twin Sheet Set
1
JJ-Memo-Zebra-PK
Zebra Pink Memory Board
1
我希望它的格式如下:
PONumber, Shipping info, SKU, Product, Qty
'35102', '[ShipToAddress]', 'JJ-Rug-Zebra-PK', 'Zebra Pink Rug', '1'
'35102', '[ShipToAddress]', 'JJ-Zebra-PK-Twin-4', 'Zebra Pink 4 Piece Twin Comforter Set', '1'
'35102', '[ShipToAddress]', 'JJ-TwinSheets-Zebra-PK', 'Zebra Pink 3 Piece Twin Sheet Set', '1'
'35102', '[ShipToAddress]', 'JJ-Memo-Zebra-PK', 'Zebra Pink Memory Board', '1'
目前的代码如下:
pattern = re.compile(r'(\b\w*JJ-\S*)')
pos = 0
while True:
match = pattern.search(msgStr, pos)
if not match:
break
a = match.start()
e = match.end()
print ' %2d : %2d = %s' % (a, e-1, msgStr[a:e])
pos = e
答案 0 :(得分:1)
根据评论,这种输入数据更适合于有状态解析方法而不是正则表达式解决方案。某些行指示解析状态应该更改以捕获新的数据集。
理想情况下,首先你会看到这个数据源是否在JSON中可用,而不是我认为是HTML的网页编写。拥有JSON源将使此过程变得微不足道,因为数据已经是对象格式。
如果您唯一的选择是使用这种逐行来源,那么最好使用类似pyparsing之类的东西,或者根据您的需要将其视为过度杀戮,您可以循环使用并检查每一个,看看你是否应该开始或停止收集一种数据直到下一个令牌。
作为最后的手段,您可以在整个输入上运行多个正则表达式模式。您必须在整个输入上运行它的原因是因为您的数据跨越了行。捕获SKU / Product / Qty的基本正则表达式可能是:
re.findall(r'(JJ-[\w-]+)\n+(.*?)\n+(\d+)\n', dataStr)
#[('JJ-Rug-Zebra-PK', 'Zebra Pink Rug', '1'),
# ('JJ-Zebra-PK-Twin-4', 'Zebra Pink 4 Piece Twin Comforter Set', '1'),
# ('JJ-TwinSheets-Zebra-PK', 'Zebra Pink 3 Piece Twin Sheet Set', '1'),
# ('JJ-Memo-Zebra-PK', 'Zebra Pink Memory Board', '1')]
这将找到包含这些模式的每3行并返回元组列表。我真的不推荐正则表达式方法,但它是一个选项。
其他正则表达方式:
re.search(r'\*{2}PO Number:\*{2}\s(\d+)\n', dataStr)
#('35102',)
re.search(r'\*{2}Ship To:\*{2}\s+(.*?)\s+SKU', dataStr, re.DOTALL)
#('John Doe\n6902 Stonegate Drive\nOdessa, TX 79\n000-000-0000',)
您可以看到如何为每个数据位构建单独的正则表达式。
答案 1 :(得分:1)
这是另一种解决方案,不使用正则表达式:
s = "(your data as a single multiline string)"
datalines = lambda s: [ln for ln in (line.strip() for line in s.splitlines()) if ln]
_, _, po_number, _, rem = s.split('**')
shipto, data = rem.split('SKU', 1)
po_number = datalines(po_number)[0]
shipto = '\n'.join(datalines(shipto))
data = datalines(data)[2:]
res = [[po_number, shipto, sku, prod, qty] for sku,prod,qty in zip(*([iter(data)]*3))]
给出最终结果
[
['35102', 'Georgie Clements\n6902 Stonegate Drive\nOdessa, TX 79765\n432-363-8459', 'JJ-Rug-Zebra-PK', 'Zebra Pink Rug', '1'],
['35102', 'Georgie Clements\n6902 Stonegate Drive\nOdessa, TX 79765\n432-363-8459', 'JJ-Zebra-PK-Twin-4', 'Zebra Pink 4 Piece Twin Comforter Set', '1'],
['35102', 'Georgie Clements\n6902 Stonegate Drive\nOdessa, TX 79765\n432-363-8459', 'JJ-TwinSheets-Zebra-PK', 'Zebra Pink 3 Piece Twin Sheet Set', '1'],
['35102', 'Georgie Clements\n6902 Stonegate Drive\nOdessa, TX 79765\n432-363-8459', 'JJ-Memo-Zebra-PK', 'Zebra Pink Memory Board', '1']
编辑:第二个数据文件返回
[
['35104', 'Angelica Alvarado\n669 66th St.\nSpringfield, OR 97478\n5412322525', 'JJ-CribSheet-Cheetah-PK-PRT', 'Cheetah Pink Print Microsuede Crib Sheet', '1']
]
哪次检查似乎是正确的?
最终摘要:我发现他使用html2text将html电子邮件转换为文本,然后尝试解析它。解决方案是使用BeautifulSoup直接解析html,利用页面结构来识别他想要的字段。