You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.0 KiB

Weasyprint

In [2]:
from weasyprint import HTML, CSS
from weasyprint.fonts import FontConfiguration
In [3]:
# If you use @font-face in your stylesheet, you would need Weasyprint's FontConfiguration()
font_config = FontConfiguration()

HTML

In [4]:
# small example HTML object
html = HTML(string='<h1>hello</h1>')

or in this case let's use python + nltk to make a custom HTML page with parts of speech used as CSS classes...

In [42]:
import nltk

txt = open('txt/language.txt').read()
words = nltk.word_tokenize(txt)
tagged_words = nltk.pos_tag(words)
In [23]:
content = ''
content += '<h1>Language and Software Studies, by Florian Cramer</h1>'

for word, tag in tagged_words:
    content += f'<span class="{tag}">{ word }</span> '

with open("txt/language.html", "w") as f:
    f.write(f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="language.css">
    <title></title>
</head>
<body>
{content}
</body>
""")

html = HTML("txt/language.html")

Saved to language.html. Fun fact: jupyter filters HTML pages that are displayed in the notebook. To see the HTML unfiltered, use an iframe (as below), or right-click and select Open in New Tab in the file list.

Maybe useful evt. https://stackoverflow.com/questions/23358444/how-can-i-use-word-tokenize-in-nltk-and-keep-the-spaces

NB: The above HTML refers to the stylesheet language.css (notice that the path is relative to the HTML page, so no need to say txt in the link).

In [34]:
from IPython.display import IFrame
IFrame("txt/language.html", width=1024, height=600)
Out[34]:

Generating the PDF!

Now let's let weasyprint do it's stuff! Write_pdf actually calculates the layout, behaving like a web browser to render the HTML visibly and following the CSS guidelines for page media (notice the special rules in the CSS that weasy print recognizes and uses that the browser does not). Notice that the CSS file gets mentioned again explicitly (and here we need to refer to its path relative to this folder).

In [39]:
## If we had not linked the CSS in the HTML, you could specify it in this way
# css = CSS("txt/language.css", font_config=font_config)
# html.write_pdf('txt/language.pdf', stylesheets=[css], font_config=font_config)
In [40]:
html.write_pdf('txt/language.pdf', font_config=font_config)
In [41]:
from IPython.display import IFrame
IFrame("txt/language.pdf", width=1024, height=600)
Out[41]:
In [ ]:
 
In [ ]: