Python 使用lxml删除中文HTML文件中的额外空格
我有一堆格式不正确的中文html文件。它们包含不必要的空格和换行符,这些空格和换行符将在浏览器中显示为额外空格。我已经使用lxml编写了一个脚本来修改html文件。它在简单的标记上工作得很好,但我在嵌套的标记上卡住了。例如:Python 使用lxml删除中文HTML文件中的额外空格,python,html,lxml,Python,Html,Lxml,我有一堆格式不正确的中文html文件。它们包含不必要的空格和换行符,这些空格和换行符将在浏览器中显示为额外空格。我已经使用lxml编写了一个脚本来修改html文件。它在简单的标记上工作得很好,但我在嵌套的标记上卡住了。例如: <p>祝你<span>19</span>岁 生日快乐。</p> 注意额外的空间。这就是需要删除的内容。结果html应如下所示: <p>祝你<span>19</span>岁生日快乐。
<p>祝你<span>19</span>岁
生日快乐。</p>
注意额外的空间。这就是需要删除的内容。结果html应如下所示:
<p>祝你<span>19</span>岁生日快乐。</p>
祝你19岁生日快乐。
我该怎么做
注意嵌套(比如SpAG标签)可以是任意的,但是我不需要考虑嵌套元素中的内容,它们应该保留它们。只有外部元素中的文本需要格式化
这就是我得到的:# -*- 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?
#-*-编码:utf-8-*-
导入lxml.html
进口稀土
s1=u“”祝你19岁
生日快乐。 “”“
p1=lxml.html.fragment\u fromstring(s1)
打印p1.text#我得到整行。
p1.text=re.sub(“\s+”,“”,p1.text)
打印p1.tostring()#删除空格。
s2=u“”祝你19岁
生日快乐。 “”“
p2=lxml.html.fragment\u fromstring(s2)
打印p2.text#我得到“祝你"
打印p2.tail#我一个也没有
i=p2.itertext()
打印i.next()#我得到“祝你"
打印i.next()#我从
print i.next()#我得到了有尾的文本,但如何将它们重新组合?
打印p2.text_content()#整个文本,但如何放回?
有争议的是,考虑到这似乎是由换行引起的,我想知道这是否可能在不使用HTML/XML解析器的情况下完成
借助此解决方案,我构建了一个正则表达式来查找中文文本之间的空白:
我不知道是否捕获字符之间的所有任何空格,或者更具体的[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)
#-*-编码:utf-8-*-
进口稀土
#中文HTML中的空白
##使用此解决方案创建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\u4fc3\u900-\ufa2d\ufa30-\ufa60-\ufad9\U00020000-\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\u4fc3\u900-\ufa2d\ufa30-\ufa60\ufa60-\ufad9\U00020000-\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)
样本=u'\u795d\u4f6019\u5c81\n\u751f\u65e5\u5feb\u4e50\u3002'
fixwhitespace.sub(“”,示例)
屈服
<html><body><p>祝你19日快乐。</p></body></html>
祝你19日快乐。
但是,以下是使用解析器和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)
#-*-编码:utf-8-*-
从lxml导入etree
进口稀土
fixwhitespace=re.compile(u'[\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u3005\u3007\u3021-\u3029\u3038-\u303a\u303b\u3400-\u4db5\u4fc3\u900-\ufa2d\ufa30-\ufa60\ufa60-\ufad9\U00020000-\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)
样本=u'\u795d\u4f6019\u5c81\n\u751f\u65e5\u5feb\u4e50\u3002'
doc=etree.HTML(示例)
对于doc.xpath中的t(“//text()[包含(,'\n')]”):
如果t.是_tail:
t、 getparent().tail=fixwhitespace.sub(“”,t)
elif t.is_文本:
t、 getparent().text=fixwhitespace.sub(“”,t)
打印etree.tostring(文档)
收益率:
<html><body><p>祝你19日快乐。</p></body></html>
&31069;&20320;19&26085;&24555;&20048;&12290
我很好奇与您的工作数据最匹配的是什么。>root=etree.fromstring('祝你19岁\N生日快乐。 ")
>>> root = etree.fromstring('<p>祝你<span>19</span>岁\n生日快乐。</p>')
>>> etree.tostring(root)
b'<p>祝你<span>19</span>岁\n生日快乐。</p>'
>>> for e in root.xpath('/p/*'):
... if e.tail:
... e.tail = e.tail.replace('\n', '')
...
>>> etree.tostring(root)
b'<p>祝你<span>19</span>岁生日快乐。</p>'
>>>etree.tostring(根目录)
b'&&31069;&20320;19&23681;\n&29983;&26085;&24555;&20048;&12290;'
>>>对于root.xpath('/p/*')中的e:
…如果e.tail:
…e.tail=e.tail.replace('\n','')
...
>>>etree.tostring(根目录)
b'&&31069;&20320;19&&23681;&29983;&26085;&24555;&20048;&12290;'
这项任务的哪一部分让你感到困惑?你尝试了什么?@Marcin code example补充道。希望现在已经足够清楚了。好问题-我没有一个头脑中的答案,但我最好的猜测是你必须按照树结构走(递归或迭代,根据你的喜好),删除多余的空格。谢谢!纯正则表达式对某些内容不起作用,但xpath+regex效果很好。纯正则表达式对某些内容不起作用-我想这验证了所有关于正则表达式和HTML/XML的警告和警告!我很高兴其中一种方法在整个数据集都有效。谢谢。我应该更多地了解xpath。我接受马特的答案,因为它更全面。
>>> root = etree.fromstring('<p>祝你<span>19</span>岁\n生日快乐。</p>')
>>> etree.tostring(root)
b'<p>祝你<span>19</span>岁\n生日快乐。</p>'
>>> for e in root.xpath('/p/*'):
... if e.tail:
... e.tail = e.tail.replace('\n', '')
...
>>> etree.tostring(root)
b'<p>祝你<span>19</span>岁生日快乐。</p>'