Python对Google Fonts字体文件执行base64编码结果异常问题求助
问题原因
- URL参数拼接错误:代码中拼接URL时错误使用了HTML转义符
&代替&,导致Google Fonts无法识别text参数,返回的是完整字体文件,和你浏览器中访问的子集化字体文件本身内容就不同 - 请求UA不匹配导致字体格式不一致:Google Fonts会根据请求的User-Agent返回适配的字体格式(woff2/woff/ttf等),你代码用urllib2默认UA拿到的字体格式,和你用浏览器访问下载的字体格式可能完全不同,自然base64编码结果不一致
- Windows文本模式写入破坏内容:Python2在Windows环境下用
'w'模式打开文件时,会自动将字符串中的\n替换为\r\n,而base64.b64encode默认会每76个字符插入一个\n换行符,替换后多余的\r字符会导致base64编码结果错误 - MIME类型硬编码错误:你代码里固定写死
data:font/ttf,如果请求拿到的是woff/woff2格式的字体,MIME类型不匹配也会导致字体无法正常加载
解决方案
修改后可直接运行的代码如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- import base64 import urllib2 font_names = ['Lobster', 'Pacifico', 'Acme'] base_url = 'https://fonts.googleapis.com/css?family=' # 模拟桌面Chrome UA,保证拿到和浏览器访问一致的字体格式 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } # 字体格式对应MIME类型映射 mime_map = { 'woff2': 'font/woff2', 'woff': 'font/woff', 'truetype': 'font/ttf', 'opentype': 'font/otf' } def get_url(url_string): return url_string.split('url(')[1].split(')')[0] def get_format(url_string): format_str = url_string.split('format(')[1].strip('\'"); \r\n') return format_str, ' format(' + url_string.split('format(')[1] font_lines = [] for font in font_names: # 修正参数拼接错误,用&代替HTML转义的& font_url = base_url + font + '&text=' + font req = urllib2.Request(font_url, headers=headers) for line in urllib2.urlopen(req): if 'src:' in line: url = get_url(line) font_format, format_suffix = get_format(line) # 拉取字体二进制内容 font_req = urllib2.Request(url, headers=headers) font_binary = urllib2.urlopen(font_req).read() # 编码base64并去掉默认插入的换行符 base64_font = base64.b64encode(font_binary).replace('\n', '') # 动态设置MIME类型,去掉base64前多余的空格 font_lines.append('src: url(data:%s;base64,%s)%s' % (mime_map.get(font_format, 'font/ttf'), base64_font, format_suffix)) else: font_lines.append(line) # 用二进制模式写入文件,避免Windows下自动转换换行符 with open('fonts.css', 'wb') as font_file: for line in font_lines: font_file.write(line)
内容的提问来源于stack exchange,提问作者Stephen Miller
相关产品推荐
相关产品推荐

