问题描述
|
我正在使用lxml解析html并对其进行编辑以生成新文档。从本质上讲,我正在尝试像javascript DOM一样使用它-我知道这并不是真正的预期用途,但是到目前为止,它的大部分工作都很好。
当前,我使用iterdescendants()获取可迭代的元素列表,然后依次处理每个元素。
但是,如果元素在迭代过程中被删除,则仍会考虑其子元素,因为删除不会像您期望的那样影响迭代。为了获得我想要的结果,此骇客作品:
from lxml.html import fromstring,tostring
import urllib2
import re
html = \'\'\'
<html>
<head>
</head>
<body>
<div>
<p class=\"unwanted\">This content should go</p>
<p class=\"fine\">This content should stay</p>
</div>
<div id = \"second\" class=\"unwanted\">
<p class = \"alreadydead\">This content should not be looked at</p>
<p class = \"alreadydead\">nor should this</>
<div class=\"alreadydead\">
<p class=\"alreadydead\">Still dead</p>
</div>
</div>
<div>
<p class=\"yeswanted\">This content should also stay</p>
</div>
</body>
for element in allElements:
s = \"%s%s\" % (element.get(\'class\',\'\'),element.get(\'id\',\'\'))
if re.compile(\'unwanted\').search(s):
for i in range(len(element.findall(\'.//*\'))):
allElements.next()
element.drop_tree()
print tostring(page.body)
输出:
<body>
<div>
<p class=\"yeswanted\">This content should stay</p>
</div>
<div>
<p class=\"yeswanted\">This content should also stay</p>
</div>
</body>
感觉就像一个讨厌的黑客-是否有更明智的方式使用该库来实现这一目标?
解决方法
为简化起见,您可以在XPath中使用lxml \对正则表达式的支持来查找并杀死不需要的节点,而无需遍历所有后代。
这将产生与脚本相同的结果:
EXSLT_NS = \'http://exslt.org/regular-expressions\'
XPATH = r\"//*[re:test(@class,\'\\bunwanted\\b\') or re:test(@id,\'\\bunwanted\\b\')]\"
tree = lxml.html.fromstring(html)
for node in tree.xpath(XPATH,namespaces={\'re\': EXSLT_NS}):
node.drop_tree()
print lxml.html.tostring(tree.body)