-2

我有以下输入。我想将其解析为 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
4

2 回答 2

1

根据评论,与正则表达式解决方案相比,这种输入数据更适合状态解析方法。某些行表明解析状态应该更改以捕获一组新数据。

理想情况下,首先您会看到这个数据源是否以 JSON 格式提供,而不是我认为的 HTML 网页抓取。拥有 JSON 源将使这个过程变得微不足道,因为数据已经是对象格式。

如果您唯一的选择是使用此逐行源代码,则最好使用pyparsing 之类的东西,或者如果认为这对您的需求来说太过分了,您可以遍历这些行并检查每一行以查看是否您应该开始或停止收集一种数据,直到下一个令牌。

作为最后的手段,您可以在整个输入上运行多个正则表达式模式。您必须在整个输入上运行它的原因是因为您的数据跨行。用于捕获 SKU/产品/数量的基本正则表达式可能是:

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',)

您可以看到您只需要为每一位数据构建单独的正则表达式。

于 2012-07-15T15:25:53.387 回答
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,利用页面结构来识别他想要的字段。

于 2012-07-15T20:45:51.363 回答