Удаление лишних пробелов в китайских HTML-файлах с использованием lxml - PullRequest
1 голос
/ 19 марта 2012

У меня есть куча неправильно отформатированных китайских 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 ]

2 голосов
/ 19 марта 2012
>>> 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 голос
/ 19 марта 2012

Спорно, интересно, возможно ли это, чтобы завершить без использования HTML / XML парсер, принимая во внимание, что, как представляется, быть причиной переноса строк.

1002 * Я построил регулярное выражение, чтобы искать пробелы между китайским текстомс помощью этого решения здесь: 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>

Мне любопытно, как лучше всего подходят ваши рабочие данные.

...