Skip to content

Instantly share code, notes, and snippets.

@rock3r

rock3r/gfonts.py

Last active Oct 19, 2016
Embed
What would you like to do?
Rip fonts from Google Fonts for self-hosting, EZ
#!/usr/bin/python
#coding: utf-8
import argparse, os, tinycss, requests
def parse_cli_arguments():
parser = argparse.ArgumentParser(description='Downlads all available variants of a font from Google Fonts')
parser.add_argument('fontname', type=str, help='The name of the font. E.g., "Roboto", "Product Sans"')
return parser.parse_args()
def download_css(font):
url = 'https://fonts.googleapis.com/css?family={font}:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'.format(font = font)
# This useragent tricks Google Fonts into delivering us a TTF version
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16' }
r = requests.get(url, headers = headers)
print "CSS downloaded: "
print r.text
return r.text
def font_name(font_face):
if font_face.style == 'normal':
return font_face.family_name + '.ttf'
else:
return font_face.family_name + '-' + font_face.style + '.ttf'
def download_font_file(font_face):
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16' }
r = requests.get(font_face.url, headers)
file_name = font_name(font_face)
with open(file_name, "w") as font_file:
font_file.write(r.content)
return os.path.abspath(file_name)
def extract_family_name(values):
for value in values:
try:
if value.function_name == 'local':
return value.content[0].value
except AttributeError as e:
continue
def extract_url(values):
for value in values:
if value.type == 'URI':
return value.value
def parse_font_face(rule):
if rule.at_keyword != '@font-face':
raise Exception("Not a @font-face rule")
font_face = FontFace()
for declaration in rule.declarations:
if declaration.name == 'font-style':
font_face.style = declaration.value[0].value
elif declaration.name == 'src':
font_face.family_name = extract_family_name(declaration.value)
font_face.url = extract_url(declaration.value)
print " Rule parsed: {}".format(vars(font_face))
return font_face
class FontFace(object):
__attrs__ = [
'family_name', 'style', 'url'
]
def __init__(self, family_name, style, url):
super(FontFace, self).__init__()
self.family_name = family_name
self.style = style
self.url = url
def __init__(self):
super(FontFace, self).__init__()
pass
###############################################################################################
###############################################################################################
args = parse_cli_arguments()
css = download_css(args.fontname)
print 'Parsing CSS...'
parser = tinycss.make_parser('fonts3')
css = parser.parse_stylesheet(css)
for rule in css.rules:
print " > @font-face rule found at {line}:{column}".format(line = rule.line, column = rule.column)
try:
font_face = parse_font_face(rule)
except Exception as e:
print " Skipping rule, parsing error"
continue
print " Downloading font..."
output_path = download_font_file(font_face)
print u" Font downloaded to {}! ✨".format(output_path)
print u"All done yay 🎉"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.