如何在lxml iterwalk循环中用文字替换HTML标签
我正在用lxml的iterwalk遍历一个HTML树,我想把所有在<pre></pre>
标签里的<br>
标签替换成换行符。到目前为止,我有这样的代码:
root = lxml.html.fromstring(text)
for action, el in etree.iterwalk(root):
if el.tag == 'pre':
for br in el.xpath('br'):
# replace this <br> tag with "\n"
如果可以的话,这个替换操作最好是在这个循环里面完成,因为我们本来就需要这个循环,把这个步骤放进去可能是最有效的方式。
在StackOverflow上有一个类似的问题和回答,但并没有帮助我解决这个问题: 如何在lxml中用文本替换一个元素?
2 个回答
3
我知道你需要用到 lxml
,但是用 BeautifulSoup
来解析和修改 HTML
其实要简单得多,而且更有趣。如果速度真的很重要的话,你可以把 lxml
当作一个 底层解析器 来使用:
from bs4 import BeautifulSoup
text = """
<div>
<pre>
<br>
test
<br>
</pre>
<br>
</div>
"""
soup = BeautifulSoup(text, "lxml")
for pre in soup.find_all('pre'):
for br in pre.find_all('br'):
br.replace_with('\n')
print soup.prettify()
输出结果是:
<html>
<body>
<div>
<pre>
test
</pre>
<br/>
</div>
</body>
</html>
5
drop_tree()
方法正是你需要的:
.drop_tree():
这个方法会删除这个元素以及它的所有子元素。和 el.getparent().remove(el) 不同的是,这个方法不会删除尾部文本;使用 drop_tree 的话,尾部文本会和前一个元素合并在一起。
找到所有在 pre
标签里的 br
标签,把 tail
设置为 \n
然后删除这个元素:
from lxml import etree
import lxml.html
text = """
<div>
<pre>
<br>
test
<br>
</pre>
<br>
</div>
"""
root = lxml.html.fromstring(text)
for action, el in etree.iterwalk(root):
if el.tag == 'pre':
for br in el.xpath('br'):
br.tail = '\n' + br.tail
br.drop_tree()
print etree.tostring(root)
输出结果:
<div>
<pre>
test
</pre>
<br/>
</div>