使用lxml删除中文HTML文件中的额外空格

时间:2012-03-19 09:30:03

标签: python html lxml

我有一堆格式不正确的中文html文件。它们包含不必要的空格和换行符,它们将在浏览器中显示为额外的空格。我用lxml编写了一个脚本来修改html文件。它适用于简单的标签,但我坚持使用嵌套的标签。例如:

<p>祝你<span>19</span>岁
    生日快乐。</p>

将显示为浏览器:

祝你19岁 生日快乐。

注意额外的空间。这是需要删除的内容。结果html应该是这样的:

<p>祝你<span>19</span>岁生日快乐。</p>

我该怎么做?

请注意,嵌套(如span标记)可以是任意的,但我不需要考虑嵌套元素中的内容,它们应该按原样保留。只有外部元素中的文本需要格式化。

这就是我所拥有的:

# -*- coding: utf-8 -*-

import lxml.html
import re

s1 = u"""<p>祝你19岁
    生日快乐。</p>"""
p1 = lxml.html.fragment_fromstring(s1)
print p1.text         # I get the whole line.
p1.text = re.sub("\s+", "", p1.text)
print p1.tostring()   # spaces are removed.

s2 = u"""<p>祝你<span>19</span>岁
    生日快乐。</p>"""
p2 = lxml.html.fragment_fromstring(s2)
print p2.text     # I get "祝你"
print p2.tail     # I get None
i = p2.itertext()
print i.next()   # I get "祝你"
print i.next()   # I get "19" from <span>
print i.next()   # I get the tailed text, but how do I assemble them back?
print p2.text_content()  # The whole text, but how do I put <span> back?

2 个答案:

答案 0 :(得分:2)

>>> root = etree.fromstring('<p>祝你<span>19</span>岁\n生日快乐。</p>')
>>> etree.tostring(root)
b'<p>&#31069;&#20320;<span>19</span>&#23681;\n&#29983;&#26085;&#24555;&#20048;&#12290;</p>'

>>> for e in root.xpath('/p/*'):
...   if e.tail:
...     e.tail = e.tail.replace('\n', '')
...

>>> etree.tostring(root)
b'<p>&#31069;&#20320;<span>19</span>&#23681;&#29983;&#26085;&#24555;&#20048;&#12290;</p>'

答案 1 :(得分:1)

有争议的是,我想知道这是否可以在不使用HTML / XML解析器的情况下完成,因为它似乎是由换行引起的。

我在这里使用此解决方案构建了一个正则表达式来查找中文文本之间的空格:https://stackoverflow.com/a/2718268/267781

我不知道字符之间是否存在任何空格,或者更具体的[char]\n\s*[char]是否最适合您的问题。

# -*- coding: utf-8 -*-
import re

# Whitespace in Chinese HTML
## Used this solution to create regexp: https://stackoverflow.com/a/2718268/267781
## \s+
fixwhitespace2 = re.compile(u'[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d](\s+)[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d]',re.M)
## \n\s*
fixwhitespace = re.compile(u'[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d](\n\s*)[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d]',re.M)

sample = u'<html><body><p>\u795d\u4f6019\u5c81\n    \u751f\u65e5\u5feb\u4e50\u3002</p></body></html>'

fixwhitespace.sub('',sample)

屈服

<html><body><p>祝你19日快乐。</p></body></html>

但是,以下是使用解析器和xpath查找换行符的方法:

# -*- coding: utf-8 -*-
from lxml import etree
import re

fixwhitespace = re.compile(u'[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d](\n\s*)[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4e00-\u9fc3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\U00020000-\U0002a6d6\U0002f800-\U0002fa1d]',re.M)
sample = u'<html><body><p>\u795d\u4f6019\u5c81\n    \u751f\u65e5\u5feb\u4e50\u3002</p></body></html>'

doc = etree.HTML(sample)
for t in doc.xpath("//text()[contains(.,'\n')]"):
  if t.is_tail:
    t.getparent().tail = fixwhitespace.sub('',t)
  elif t.is_text:
    t.getparent().text = fixwhitespace.sub('',t)

print etree.tostring(doc)

收率:

<html><body><p>&#31069;&#20320;19&#26085;&#24555;&#20048;&#12290;</p></body></html>

我很好奇与您的工作数据最匹配的是什么。

相关问题