我正在用 python + lxml 处理一些 HTML 文件。其中一些已经用 MS Word 编辑过,我们有 <p>标记为 <o:p> </o:p>例如。 IE 和 Firefox 不会将这些 MS 标签解释为真实的 <p>标签,<o:p>前后不显示换行符标签,这就是原始编辑器格式化文件的方式,例如nbsp 周围没有空格。
另一方面,lxml 是整洁的,在处理 HTML 文件后,我们看到所有 <o:p>标签已更改为正确的 <p>标签。不幸的是,在整理之后,两个浏览器现在都会在所有 nbsp 周围显示换行符,这会破坏原始格式。
所以,我的想法是浏览所有这些 <o:p>标签并删除它们或将它们的 .text 属性添加到父 .text 属性,即删除 <o:p>标签标记。
from lxml import etree
import lxml.html
from StringIO import StringIO
s='<p>somepara</p> <o:p>msoffice_para</o:p>'
parser = lxml.html.HTMLParser()
html=lxml.html.parse( StringIO( s), parser)
for t in html.xpath( "//p"):
print "tag: " + t.tag + ", text: '" + t.text + "'"
结果是:
tag: p, text: 'somepara'
tag: p, text: 'msoffice_para'
因此,lxlm 从标签标记中删除命名空间名称。有没有办法知道哪个<p>标签来自哪个命名空间,所以我只删除带有 <o:p> 的标签?
谢谢。
请您参考如下方法:
来自 HTML 规范:“The HTML syntax does not support namespace declarations”。 所以我认为 lxml.html.HTMLParser 删除/忽略了命名空间。
但是,BeautifulSoup 以不同的方式解析 HTML,因此我认为它可能值得一试。如果您还安装了 BeautifulSoup,则可以像这样将 BeautifulSoup 解析器与 lxml 一起使用:
import lxml.html.soupparser as soupparser
import lxml.html
import io
s='<p>somepara</p> <o:p>msoffice_para</o:p>'
html=soupparser.parse(io.BytesIO(s))
BeautifulSoup 不会删除命名空间,但它也不会识别命名空间本身。相反,它只是标签名称的一部分。
也就是说,
html.xpath('//o:p',namespaces={'o':'foo'})
不起作用。但是这个解决方法/黑客
for t in html.xpath('//*[name()="o:p"]'):
print "tag: " + t.tag + ", text: '" + t.text + "'"
产量
tag: o:p, text: 'msoffice_para'
