Python 字体爬虫应对

思路:
爬取网页 -> 提取信息及字体文件地址 -> 字体下载 -> 字体解析为 XML 文档 -> 将 XML 文档中的字的坐标与自己摸索规律得到的数据库做比对 -> 得到相应信息
进阶:
如果字体坐标加入每次加上随机值,可以检测坐标区间
杀手锏:
将坐标画出来,图片经由深度学习进行训练,此方法正确率及稳定性高,但模型构建与训练需要一定时间,过几日补上我的模型地址。

下面以 猫眼深圳 的影院信息为例:

网址:https://maoyan.com/cinemas?offset=12

字体乱码显示

可以看到网页返回的不是真实数字,而是由 stonefont 字体渲染得到的。
所以我们接下来的方向就是发出请求,得到字体文件并进行解析:

  1. 发出请求
import requests

url = 'https://maoyan.com/cinemas?offset=12'
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0',
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
    print(response.content.decode('utf-8'))
else:
    print(response.status_code)

可以看到第一个电影院 「华夏星越影城」 的信息如下:

华夏星越影城(杜比全景声·民治万盛店)

地址:龙华区民治街道民治大道万众城万盛百货四楼

.
  1. 在源代码中搜索 stonefont 得到字体文件地址为:
    http://vfile.meituan.net/colorstone/2b72be2a972359c0de8bac4681d75ecc2080.woff
  
  1. 将字体文件下载下来并上传到 http://fontstore.baidu.com/static/editor/index.html 进行解析
    字体文件解析

    可以看到源代码中的票价 . 中每一个的后四位对应于字体文字名称的后四位,如 f2dd对应于 2,f43f对应于 4,eef4对应于 9,即总的数字为 24.9,与我们在网页看到的数字一致。
电影价格为 24.9

需要注意的是每次发送请求,猫眼所用的字体文件是不一样的,也就是说这次 f2dd 对应数字 2,但下次就不是 f2dd,所以我们要想办法得到不同字体文件之间的内在规律。

我们利用 Python 的 fonttools 第三方库来将我们的字体文件转为 XML 格式。

from fontTools.ttLib import TTFont

font = TTFont('./2b72be2a972359c0de8bac4681d75ecc2080.woff')
font.saveXML('2b72be2a972359c0de8bac4681d75ecc2080.xml')

保存的文件内容如下:




  
    
    
    
    
    
    
    
    
    
    
    
    
    
  


      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
      
      
    
....下面还有很多代码

可以看到有 11个 id,他们的值就是我们刚刚看到的百度在线解析得到的字体文件名后4位。下面的 TTGlyph 我的理解是 x, y 分别代表点的横纵坐标,0, 1 代表不同的点(可能是连线的方向)。我从字体文件中取了数字 7 对应的 x, y 值并在 matplotlib 中将这些点绘制出来

数字 7 的绘制

可以看到的是基本轮廓就是数字 7,这也验证了我们的猜想。多观察几个字体文件可以发现,每个字体文件中同一个数字的名称虽然不一样,但是其 TTGlyph 节点下的数据是一样的。所以我们只需要先请求几次,把每个数字对应的所有点的坐标值与该数字一一对应。当有新的响应时,从响应中提取字体文件,将其转化为 XML 后的坐标值与库进行比对,得到每个数字的代码,然后用这个代码去替换我们得到的乱码的数字。

参考资料:

https://cuiqingcai.com/6431.html
https://www.cnblogs.com/gl1573/p/9994286.html
http://fontstore.baidu.com/static/editor/index.html

你可能感兴趣的:(Python 字体爬虫应对)