Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

275
Vistas
¿Cómo puedo convertir una cadena Markdown en un DocX en Python?

Obtengo un texto de descuento de mi API como este:

 { name:'Onur', surname:'Gule', biography:'## Computers I like **computers** so much. I wanna *be* a computer.', membership:1 }

la columna de biografía incluye una cadena de descuento como la anterior.

 ## Computers I like **computers** so much. I wanna *be* a computer.

Quiero tomar este texto de descuento y convertirlo en una cadena docx para mis informes.

En mi plantilla docx:

 {{markdownText|mark2html}} {{simpleText}}

Estoy usando el paquete python3 docxtpl para crear docx y funciona para textos simples.

  • Probé BeautifulSoup para convertir Markdown a texto docx pero no funciona para estilos (negrita, cursiva, etc.).
  • Probé pandoc y funcionó, pero solo creó un archivo docx, quiero agregar el texto de reducción renderizado al docx existente (durante la creación).

Mi código actual:

 import docx from docxtpl import DocxTemplate, RichText import markdown import jinja2 import markupsafe from bs4 import BeautifulSoup import pypandoc def safe_markdown(text): return markupsafe.Markup(markdown.markdown(text)) def mark2html(value): html = markdown.markdown(value) soup = BeautifulSoup(html, features='html.parser') output = pypandoc.convert_text(value,'rtf',format='md') return RichText(value) #tried soup and pandoc.. def from_template(template): template = DocxTemplate(template) context = { 'simpleText':'Simple text test.', 'markdownText':'Markdown **text** test.' } jenv = jinja2.Environment() jenv.filters['markdown'] = safe_markdown jenv.filters["mark2html"] = mark2html template.render(context,jenv) template.save('new_report.docx')

Entonces, ¿cómo puedo agregar una reducción renderizada a un docx existente o durante la creación, tal vez con un filtro jinja2?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

He seguido una estrategia perezosa, no muy eficiente, pero útil. Dado que tratar con docx es menos flexible que html , primero convertí el md de descuento a html , luego pasé de html a docx de esta manera:

 from jinja2 import FileSystemLoader, Environment from pypandoc import convert_file, convert_text def md2html(md): return convert_text(md, 'html', format='md') def html2docx(file): return convert_file(f'{file}.html', 'docx', format='html', outputfile=f'{file}.docx') def from_template(template_file, f_out): context = { 'simpleText': 'Simple text test.', 'markdownText': 'Markdown **text** test.' } ldr = FileSystemLoader(searchpath='./') jenv = Environment(loader=ldr) jenv.filters["md2html"] = md2html template = jenv.get_template(template_file) html = template.render(context) print(html) with open(f'{f_out}.html', 'w') as fout: fout.write(html) fout.close() html2docx(f_out) if __name__ == '__main__': from_template('template.html.jinja', 'new_report')

en cuanto al contenido de la plantilla, debe tomarse de una basada en html como esta:

 <!DOCTYPE html> <html xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml" lang="en-US"> <head></head> <body> {{markdownText|md2html}} {{simpleText}} </body> </html>

Lo guardé como template.html.jinja .

Tuve la tentación de investigar la contribución de @Mahrkeenerh, la API referida parece ser un proyecto bastante grande para aprender y comprender.

over 4 years ago · Santiago Trujillo Denunciar

0

Lo resolví sin ningún atajo. Paso el descuento a html con beautifulSoup y luego proceso cada párrafo comprobando los nombres de sus etiquetas.

En mi plantilla de word:

 {% if markdownText != None %} {% for mt in markdownText|mark2html %} {{mt}} {% endfor %} {% endif %}

Mi etiqueta de plantilla:

 def mark2html(value): if value == None: return '-' html = markdown.markdown(value) soup = BeautifulSoup(html, features='html.parser') paragraphs = [] global doc for tag in soup.findAll(True): if tag.name in ('p','h1','h2','h3','h4','h5','h6'): paragraphs.extend(parseHtmlToDoc(tag)) return paragraphs

Mi código para insertar docx:

 def parseHtmlToDoc(org_tag): contents = org_tag.contents pars= [] for con in contents: if str(type(con)) == "<class 'bs4.element.Tag'>": tag = con if tag.name in ('strong',"h1","h2","h3","h4","h5","h6"): source = RichText("") if len(pars) > 0 and str(type(pars[len(pars)-1])) == "<class 'docxtpl.richtext.RichText'>": source = pars[len(pars)-1] source.add(con.contents[0], bold=True) else: source.add(con.contents[0], bold=True) pars.append(source) elif tag.name == 'img': source = tag['src'] imagen = InlineImage(doc, settings.MEDIA_ROOT+source) pars.append(imagen) elif tag.name == 'em': source = RichText("") source.add(con.contents[0], italic=True) pars.append(source) else: source = RichText("") if len(pars) > 0 and str(type(pars[len(pars)-1])) == "<class 'docxtpl.richtext.RichText'>": source = pars[len(pars)-1] pars.add(con) else: if org_tag.name == 'h2': source.add(con,bold=True,size=40) else: source.add(con) pars.append(source) # her zaman append? return pars

Procesa etiquetas html como b, i, img, encabezados. Puede agregar más etiquetas para procesar. Lo resolví así y no necesita ninguna transformación de archivo adicional como html2docx, etc.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda