Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用lxml删除中文HTML文件中的额外空格_Python_Html_Lxml - Fatal编程技术网

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

Python 使用lxml删除中文HTML文件中的额外空格,python,html,lxml,Python,Html,Lxml,我有一堆格式不正确的中文html文件。它们包含不必要的空格和换行符,这些空格和换行符将在浏览器中显示为额外空格。我已经使用lxml编写了一个脚本来修改html文件。它在简单的标记上工作得很好,但我在嵌套的标记上卡住了。例如: <p>祝你<span>19</span>岁 生日快乐。</p> 注意额外的空间。这就是需要删除的内容。结果html应如下所示: <p>祝你<span>19</span>岁生日快乐。

我有一堆格式不正确的中文html文件。它们包含不必要的空格和换行符,这些空格和换行符将在浏览器中显示为额外空格。我已经使用lxml编写了一个脚本来修改html文件。它在简单的标记上工作得很好,但我在嵌套的标记上卡住了。例如:

<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>&#31069;&#20320;19&#26085;&#24555;&#20048;&#12290;</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>&#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>'
>>>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>&#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>'