2011-03-09 81 views
2

我是pyparsing的新手。
如何將類pyparsing.ParseResults的實例轉換回html字符串。將pyparsing.ParseResults轉換回html字符串

ex。

>>> type(gcdata) 
<type 'unicode'> 
>>> pat 
{<"div"> SkipTo:(</"div">) </"div">} 
>>> type(pat) 
<class 'pyparsing.And'> 
>>> 
>>> l = pat.searchString(gcdata ) 
>>> l[0] 
(['div', ([u'class', u'shoveler'], {}), ([u'id', u'purchaseShvl'], {}), False, u'<div class="shoveler-heading">\n <p>Customers Who Bought This Item Also Bought</p>\n \n', '</div>'], {'startDiv': [((['div', ([u'class', u'shoveler'], {}), ([u'id', u'purchaseShvl'], {}), False], {u'class': [(u'shoveler', 1)], 'empty': [(False, 3)], u'id': [(u'purchaseShvl', 2)]}), 0)], 'endDiv': [('</div>', 5)], u'class': [(u'shoveler', 1)], 'empty': [(False, 3)], u'id': [(u'purchaseShvl', 2)]}) 
>>> 
>>> type(l[0]) 
<class 'pyparsing.ParseResults'> 
>>> 
>>> divhtml = foo (l[0]) 

所以,我需要這個功能FOO
有什麼建議嗎?

回答

1

這與makeHTMLTags返回表達式的問題,即很多額外的分組和命名的推移,它會擋住你的方式,如果你只是想在標籤的文本。

Pyparsing包含方法originalTextFor以幫助解決此問題。建立在示例代碼從@samplebias:

start, end = makeHTMLTags('div') 
#anchor = start + SkipTo(end).setResultsName('body') + end 
anchor = originalTextFor(start + SkipTo(end).setResultsName('body') + end) 

通過originalTextFor包裝的表達,所有的標籤成其組成部分的解體被撤消,而你剛剛回來,從原來的字符串文本(也包括任何介入的空白)。默認的行爲是給你回這個字符串,它有不幸的副作用,失去所有的結果名稱,所以回到分析的屬性值可能是一個麻煩。當我寫originalTextFor時,我認爲字符串是想要的,我不能將結果名稱附加到字符串。因此,我添加了一個可選參數asStringoriginalTextFor,默認爲True,但如果作爲False傳遞,將返回包含整個匹配字符串加上所有匹配結果名稱的單個令牌的ParseResults。所以你仍然可以從結果中提取res.id,而res[0]會返回給你整個匹配的HTML。

一些其他意見:

<div>是一種很常見的標籤,並用剛剛makeHTMLTags返回的標籤錯誤一個容易匹配。它將匹配任意 div,並且可能很多你並不真正感興趣。如果可以指定某些也應該匹配的屬性,則可以減少不匹配的數量,使用withAttribute。你可以用做:

start.setParseAction(withAttribute(id="purchaseShvl")) 

start.setParseAction(withAttribute(**{"class":"shovelr"})) 

(使用「階級」作爲過濾屬性可能是你想要做的最常見的事情,但因爲「階級」也一個Python關鍵字,你可以使用命名參數的形式,就像我用id做的那樣,太糟糕了。)

最後,與<div>的共同性是嵌套的可能性。 divs經常是嵌套在divs中,只是普通的SkipTo不夠智能,不能將其考慮在內。我們看到這個重建的公佈結果時:

<div class='shovelr' id='purchaseShvl> 
<div class='shovelr-heading'> 
<p>Customers WhoBought This Item Also Bought</p> 
</div> 

的第一終止</div>結束比賽爲你的表達。我懷疑你可能需要擴展你的匹配表達式來考慮這些額外的div,而不是簡單的SkipTo(end)。

1

使用返回DOM的HTML解析器會更好,比如lxml.html,但我懷疑你是在學習Pyparsing。由於您沒有發佈源代碼片段,我採取了一些猜測,並使用pyparsing.makeHTMLTags進行了示例,如下所示。

import cgi 
from pyparsing import makeHTMLTags, SkipTo 

raw = """<body><div class="shoveler" id="purchaseShvl"> 
<p>Customers who bought this item also bought</p> 
<div class="foo"> 
    <span class="bar">Shovel cozy</span> 
    <span class="bar">Shovel rack</span> 
</div> 
</div></body>""" 

def foo(parseResult): 
    parts = [] 
    for token in parseResult: 
     st = '<div id="%s" class="%s">' % \ 
      (cgi.escape(getattr(token, 'id')), 
      cgi.escape(getattr(token, 'class'))) 
     parts.append(st + token.body + token.endDiv) 
    return '\n'.join(parts) 

start, end = makeHTMLTags('div') 
anchor = start + SkipTo(end).setResultsName('body') + end 
res = anchor.searchString(raw) 
print foo(res)