平常在浏览网页时会发现有很多网页的文字是无法直接复制的,例如这个:中国供应商网
最新采购-采购中心-中国供应商
其实这就是一种网站自定义的字体,
@font-face{
font-family:
src:
其中font-family就是你自定义的字体名称,而src则是存放字体的路径。
这个网站其实我们可以很清楚的看到是ttf形式的文件,并且采用了base64加密。而后面的那一长串就是经过加密后的文件。所以我们第一步采用base64解码。
bs = base64.b64decode()
将解码后的文件命名并保存
with open("filename.ttf", mode="wb") as f:
f.write()
因为文件是ttf形式的,所以我们需要打开文件并保存为xml形式,
font = TTFont('filename.ttf')
font.saveXML('filename.xml')
第一步就完成了,
我们打开所得到的xml文件后会发现这样一个字段:CharString name="uni1005b",uni1005b会不会就是我们所需要的unicode与字符的对应关系呢。其中有两个字符串引起了我的注意,rlineto和rmoveto。这可能是一种坐标的表示,我们导入reportlab和fontTools.pens来画一下
from fontTools.pens.basePen import BasePen
from reportlab.graphics.shapes import Path
from reportlab.lib import colors
from reportlab.graphics import renderPM
from reportlab.graphics.shapes import Group, Drawing, scale
import base64
fontTools是python的一个对字体进行解析的第三方库,Pen是一个用于标准化的”画”出轮廓的对象,或者是数据和实际轮廓间的媒介。具体来说,Pen对象的子类包含将上述两种轮廓数据转化为画线、移动等模拟实际轮廓的方法。在fontTools的pen库中包含将轮廓数据转化为qt、reportLab等第三方库中实例的Pen子类。总体的思路就是先定义rlineto和rmoveto两种方法,根据坐标画出所有的图,再将画出的图像利用tesseract-ocr识别,就可以找到所有unicode和字符的对应关系了。
class ReportLabPen(BasePen):
"""A pen for drawing onto a reportlab.graphics.shapes.Path object."""
def __init__(self, glyphSet, path=None):
BasePen.__init__(self, glyphSet)
if path is None:
path = Path()
self.path = path
def _moveTo(self, p):
(x, y) = p
self.path.moveTo(x, y)
def _lineTo(self, p):
(x, y) = p
self.path.lineTo(x, y)
def _curveToOne(self, p1, p2, p3):
(x1, y1) = p1
(x2, y2) = p2
(x3, y3) = p3
self.path.curveTo(x1, y1, x2, y2, x3, y3)
def _closePath(self):
self.path.closePath()
def ttfToImage(fontName, imagePath, fmt="png"):
font = TTFont(fontName)
gs = font.getGlyphSet()
glyphNames = font.getGlyphNames()
for i in glyphNames:
if i[0] == '.': # 跳过'.notdef', '.null'
continue
g = gs[i]
pen = ReportLabPen(gs)
g.draw(pen)
w, h = g.width, g.width + 500
g = Group(pen.path)
g.translate(0, 200)
d = Drawing(w, h)
d.add(g)
print(d)
imageFile = imagePath + "/" + i + ".png"
renderPM.drawToFile(d, imageFile, fmt)
值得一提的是tesseract-ocr是一个很强大的图片识别工具,安装和使用方法可以自行了解。