5

默认情况下,lxml 不理解 wbr 标签,用于在长词中添加分词。它将其<wbr></wbr>格式化为应该简单地格式化为<wbr>,类似于 br 标记。

如何将此行为添加到 lxml?

4

4 回答 4

10

实际上,修补 libxml2 并不难(本演练是在 Ubuntu 11.04 上使用 Python 2.7.3 完成的)

首先定义一个测试程序wbr_test.py

from lxml import etree
from cStringIO import StringIO

wbr_html = """\
<html>
  <head>
    <title>wbr test</title>
  </head>
<body>
  Test for a breakable<wbr>word implemenation change
</body>
</html>
"""

parser = etree.HTMLParser()
tree   = etree.parse(StringIO(wbr_html), parser)

result = etree.tostring(tree.getroot(),
                         pretty_print=True, method="html")
if result.split() != wbr_html.split(): # split, as we are not interested in whitespace differences
    print(result)
    print("not ok")
else:
    print("OK")

通过运行确保它失败python wbr_test.py。它应该插入一个<\wbr>before <\body>,并在最后打印not ok

下载、解压和编译libxml2

wget ftp://xmlsoft.org/libxml2/libxml2-2.8.0.tar.gz
tar xvf libxml2-2.8.0.tar.gz 
cd libxml2-2.8.0/
./configure --prefix=/usr
make -j8  # adjust number to match your number of cores

安装并安装 python libxml2 绑定:

sudo make install
cd to_python_bindings
sudo python setup.py install

再次测试你的wbr_test.py,以确保它在最新的 libxml2 版本中失败。

HTMLparser.c首先制作一个例如 in的副本/var/tmp

现在在 libxml2 源代码的顶层编辑文件 HTMLparser.c。搜索单词forced(仅出现一次)。您将处于<br>标签定义处。复制从刚刚找到的行开始的三行。最合适的插入点就在结尾之前(在 的定义之后<var>)。要在表格中正确使用最后一个逗号,请在带有 的一行之前插入三行,而'}'不是带有 的一行'};'

在新插入的代码中替换brwbr并更改DECL clear_attrsNULL(假设新标签没有不推荐使用的属性)。

结果应与/var/tmp( diff -u HTMLparser.c /var/tmp) 中的版本不同,如下所示:

@@ -1039,6 +1039,9 @@
 },
 { "var",   0, 0, 0, 0, 0, 0, 1, "instance of a variable or program argument",
DECL html_inline, NULL, DECL html_attrs, NULL, NULL
+},
+{ "wbr",   0, 2, 2, 1, 0, 0, 1, "possible line break ",
+   EMPTY , NULL , DECL core_attrs, NULL , NULL
 }
 };

制作和安装:

make && sudo make install

wbr_test.py再次测试你的。应该显示OK

于 2012-05-28T07:04:59.170 回答
5

好消息!这是完全不可能的。HTML 标记名称直接烘焙到libxml2.

lxml.html.html5parser包含几个严重的错误,其修复尚未发布。

但见鬼,让我们在本地修复它们,看看会发生什么。

>>> lxml.html.tostring(lxml.html.html5parser.fromstring('<p>hello<wbr>world!</p>'), encoding=unicode)
u'<html:p xmlns:html="http://www.w3.org/1999/xhtml">hello<html:wbr></html:wbr>world!</html:p>'

如此接近,却又如此遥远。至少结构是正确的。

再试一次:

>>> lxml.html.tostring(lxml.html.html5parser.fromstring('<p>hello<wbr>world!</p>', parser=lxml.html.html5parser.HTMLParser(namespaceHTMLElements=False)), encoding=unicode)
u'<p>hello<wbr></wbr>world!</p>'

韦尔普。

至少没有错。

我想我可能会针对 lxml 和 libxml2 提交一些错误。

于 2012-05-23T22:04:30.587 回答
3

由于<wbr>仅存在于 HTML5 中,我怀疑正确的做法是使用lxml.html.html5parser.

除此之外,空标签列表是在常规 Python 代码中定义的,因此您总是可以对其进行猴子补丁;见lxml.html.defs.empty_tags。补丁是受欢迎的,我敢肯定。:)

于 2012-04-26T22:19:43.827 回答
1

作为一个快速修复,为什么不使用replace字符串的方法来删除关闭标签呢?

>>> t = 'Thisisa<wbr></wbr>test'
>>> t.replace('</wbr>', '')
'Thisisa<wbr>test'
于 2012-05-29T19:57:23.310 回答