Генерация HTML-документов в Python
В Python, какой самый элегантный способ создания HTML-документов. В настоящее время я вручную добавляю все теги в гигантскую строку и записываю это в файл. Есть ли более элегантный способ сделать это?
9 ответов
Я считаю, что яттаг - самый элегантный способ сделать это.
from yattag import Doc
doc, tag, text = Doc().tagtext()
with tag('html'):
with tag('body'):
with tag('p', id = 'main'):
text('some text')
with tag('a', href='/my-url'):
text('some link')
result = doc.getvalue()
Он читается как HTML, с дополнительным преимуществом, что вам не нужно закрывать теги.
Я бы предложил использовать один из многих языков шаблонов, доступных для python, например, встроенный в Django (вам не нужно использовать остальную часть Django, чтобы использовать его движок шаблонов) - запрос Google должен дать вам множество других альтернатив. Реализация шаблонов.
Я считаю, что изучение библиотеки шаблонов помогает во многих отношениях - когда вам нужно сгенерировать электронное письмо, HTML-страницу, текстовый файл или подобное, вы просто пишете шаблон, загружаете его в свою библиотеку шаблонов, а затем позволяете создавать код шаблона. готовый продукт.
Вот простой код для начала работы:
#!/usr/bin/env python
from django.template import Template, Context
from django.conf import settings
settings.configure() # We have to do this to use django templates standalone - see
# http://stackru.com/questions/98135/how-do-i-use-django-templates-without-the-rest-of-django
# Our template. Could just as easily be stored in a separate file
template = """
<html>
<head>
<title>Template {{ title }}</title>
</head>
<body>
Body with {{ mystring }}.
</body>
</html>
"""
t = Template(template)
c = Context({"title": "title from code",
"mystring":"string from code"})
print t.render(c)
Еще проще, если у вас есть шаблоны на диске - посмотрите на функцию render_to_string, которая может загружать шаблоны с диска из предварительно определенного списка путей поиска, заполнять данными из диктории и отображать в строку - все в одном вызове функции.
Если вы создаете документы HTML, я настоятельно рекомендую использовать систему шаблонов (например, jinja2), как предлагали другие. Если вам нужна генерация html-битов низкого уровня (возможно, в качестве входных данных для одного из ваших шаблонов), тогда пакет xml.etree является стандартным пакетом python и может хорошо соответствовать всем требованиям.
import sys
from xml.etree import ElementTree as ET
html = ET.Element('html')
body = ET.Element('body')
html.append(body)
div = ET.Element('div', attrib={'class': 'foo'})
body.append(div)
span = ET.Element('span', attrib={'class': 'bar'})
div.append(span)
span.text = "Hello World"
ET.ElementTree(html).write(sys.stdout, encoding='utf8',
method='html')
Печатает следующее:
<html><body><div class="foo"><span class="bar">Hello World</span></div></body></html>
Есть и хорошая современная альтернатива:
airium
: https://pypi.org/project/airium/
from airium import Airium
a = Airium()
a('<!DOCTYPE html>')
with a.html(lang="pl"):
with a.head():
a.meta(charset="utf-8")
a.title(_t="Airium example")
with a.body():
with a.h3(id="id23409231", klass='main_header'):
a("Hello World.")
html = str(a) # casting to string extracts the value
print(html)
Печатает такую строку:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8" />
<title>Airium example</title>
</head>
<body>
<h3 id="id23409231" class="main_header">
Hello World.
</h3>
</body>
</html>
Самое большое преимущество
airium
is - у него также есть обратный переводчик, который строит код python из строки html. Если вам интересно, как реализовать данный html-фрагмент - переводчик сразу даст вам ответ.
Например, его тесты содержат примеры страниц, автоматически переведенных с помощью airium:https://gitlab.com/kamichal/airium/-/tree/master/tests/documents
Я бы порекомендовал использовать xml.dom для этого.
http://docs.python.org/library/xml.dom.html
Прочтите эту страницу руководства, у нее есть методы для создания XML (и, следовательно, XHTML). Это значительно упрощает все задачи XML, включая добавление дочерних узлов, типов документов, добавление атрибутов, создание текстовых узлов. Это должно помочь вам в подавляющем большинстве вещей, которые вы будете делать для создания HTML.
Это также очень полезно для анализа и обработки существующих XML-документов.
Надеюсь это поможет
PS
Вот учебник, который должен помочь вам с применением синтаксиса
Я использую фрагмент кода, известный как throw_out_your_templates
для некоторых из моих собственных проектов:
https://github.com/tavisrudd/throw_out_your_templates
https://bitbucket.org/tavisrudd/throw-out-your-templates/src
К сожалению, для него нет пакета pypi, и он не является частью какого-либо дистрибутива, поскольку он предназначен только для проверки концепции. Я также не смог найти кого-то, кто взял код и начал поддерживать его как реальный проект. Тем не менее, я думаю, что стоит попробовать, даже если это означает, что вы должны отправить свою собственную копию throw_out_your_templates.py
с вашим кодом.
Аналогично предложению использовать yattag Джоном Смитом, необязательно, этот модуль не требует изучения какого-либо языка шаблонов, а также гарантирует, что вы никогда не забудете закрыть теги или заключить в кавычки специальные символы. Все остается написанным на Python. Вот пример того, как его использовать:
html(lang='en')[
head[title['An example'], meta(charset='UTF-8')],
body(onload='func_with_esc_args(1, "bar")')[
div['Escaped chars: ', '< ', u'>', '&'],
script(type='text/javascript')[
'var lt_not_escaped = (1 < 2);',
'\nvar escaped_cdata_close = "]]>";',
'\nvar unescaped_ampersand = "&";'
],
Comment('''
not escaped "< & >"
escaped: "-->"
'''),
div['some encoded bytes and the equivalent unicode:',
'你好', unicode('你好', 'utf-8')],
safe_unicode('<b>My surrounding b tags are not escaped</b>'),
]
]
Я пытаюсь сделать более простое решение под названием PyperText.
В котором вы можете делать такие вещи:
from PyperText.html import Script
from PyperText.htmlButton import Button
#from PyperText.html{WIDGET} import WIDGET; ex from PyperText.htmlEntry import Entry; variations shared in file
myScript=Script("myfile.html")
myButton=Button()
myButton.setText("This is a button")
myScript.addWidget(myButton)
myScript.createAndWrite()
Я написал простую оболочку для
lxml
модуль (должен нормально работать с
xml
а также), который создает теги для документов HTML / XML -esq.
На самом деле, мне понравился формат ответа Джона Смита, но я не хотел устанавливать ЕЩЕ ДРУГОЙ МОДУЛЬ для выполнения чего-то, что казалось таким простым.
Сначала пример, потом обертка.
Пример
from Tag import Tag
with Tag('html') as html:
with Tag('body'):
with Tag('div'):
with Tag('span', attrib={'id': 'foo'}) as span:
span.text = 'Hello, world!'
with Tag('span', attrib={'id': 'bar'}) as span:
span.text = 'This was an example!'
html.write('test_html.html')
Выход:
<html><body><div><span id="foo">Hello, world!</span><span id="bar">This was an example!</span></div></body></html>
Вывод после ручного форматирования:
<html>
<body>
<div>
<span id="foo">Hello, world!</span>
<span id="bar">This was an example!</span>
</div>
</body>
</html>
Обертка
from dataclasses import dataclass, field
from lxml import etree
PARENT_TAG = None
@dataclass
class Tag:
tag: str
attrib: dict = field(default_factory=dict)
parent: object = None
_text: str = None
@property
def text(self):
return self._text
@text.setter
def text(self, value):
self._text = value
self.element.text = value
def __post_init__(self):
self._make_element()
self._append_to_parent()
def write(self, filename):
etree.ElementTree(self.element).write(filename)
def _make_element(self):
self.element = etree.Element(self.tag, attrib=self.attrib)
def _append_to_parent(self):
if self.parent is not None:
self.parent.element.append(self.element)
def __enter__(self):
global PARENT_TAG
if PARENT_TAG is not None:
self.parent = PARENT_TAG
self._append_to_parent()
PARENT_TAG = self
return self
def __exit__(self, typ, value, traceback):
global PARENT_TAG
if PARENT_TAG is self:
PARENT_TAG = self.parent
Да, вы ищете файл.writelines
Последовательность обычно представляет собой список или массив. Поэтому поместите все свои строки в список или массив. И бросить их в функцию ниже.
Обязательно удалите все новые строковые константы из ваших строк, чтобы быть в безопасности
Документация по Python (поиск для file.writelines)
file.writelines (sequence) Записать последовательность строк в файл. Последовательность может быть любым итерируемым объектом, создающим строки, обычно списком строк. Нет возвращаемого значения. (Имя предназначено для соответствия readlines(); writelines() не добавляет разделители строк.)