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)

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

<div class="cinema-cell">
        <div class="cinema-info">
          <a href="/cinema/17275?poi=156641511" class="cinema-name" data-act="cinema-name-click" data-bid="b_4tkpau4m" data-val="{city_id: 30, cinema_id: 17275}">华夏星越影城(杜比全景声·民治万盛店)</a>
          <p class="cinema-address">地址:龙华区民治街道民治大道万众城万盛百货四楼</p>
        </div>

        <div class="buy-btn">
          <a href="/cinema/17275?poi=156641511" data-act="buy-btn-click" data-val="{city_id: 30, cinema_id: 17275}" data-bid="b_4tkpau4m">选座购票</a>
        </div>
        
        <div class="price">
            <span class="rmb red">¥</span>
            <span class="price-num red"><span class="stonefont">&#xf2dd;&#xf43f;.&#xeef4;</span></span>
            <span>起</span>
        </div>
      </div>
  1. 在源代码中搜索 stonefont 得到字体文件地址为:
    http://vfile.meituan.net/colorstone/2b72be2a972359c0de8bac4681d75ecc2080.woff
  <style>
    @font-face {
      font-family: stonefont;
      src: url('//vfile.meituan.net/colorstone/29640a4087c9cd8e7fc41e261d35f3e03168.eot');
      src: url('//vfile.meituan.net/colorstone/29640a4087c9cd8e7fc41e261d35f3e03168.eot?#iefix') format('embedded-opentype'),
           url('//vfile.meituan.net/colorstone/2b72be2a972359c0de8bac4681d75ecc2080.woff') format('woff');
    }

    .stonefont {
      font-family: stonefont;
    }
  </style>
  1. 将字体文件下载下来并上传到 http://fontstore.baidu.com/static/editor/index.html 进行解析
    字体文件解析

    可以看到源代码中的票价 &#xf2dd;&#xf43f;.&#xeef4 中每一个的后四位对应于字体文字名称的后四位,如 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')

保存的文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.43">

  <GlyphOrder>
    <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
    <GlyphID id="0" name="glyph00000"/>
    <GlyphID id="1" name="x"/>
    <GlyphID id="2" name="uniEEF4"/>
    <GlyphID id="3" name="uniF54E"/>
    <GlyphID id="4" name="uniF5C7"/>
    <GlyphID id="5" name="uniEFEA"/>
    <GlyphID id="6" name="uniE9C0"/>
    <GlyphID id="7" name="uniE1FA"/>
    <GlyphID id="8" name="uniEBC9"/>
    <GlyphID id="9" name="uniF43F"/>
    <GlyphID id="10" name="uniEF28"/>
    <GlyphID id="11" name="uniF2DD"/>
  </GlyphOrder>

<TTGlyph name="uniE1FA" xMin="0" yMin="-12" xMax="508" yMax="719">
      <contour>
        <pt x="42" y="353" on="1"/>
        <pt x="42" y="483" on="0"/>
        <pt x="67" y="557" on="1"/>
        <pt x="93" y="635" on="0"/>
        <pt x="197" y="719" on="0"/>
        <pt x="275" y="719" on="1"/>
        <pt x="389" y="719" on="0"/>
        <pt x="448" y="628" on="1"/>
        <pt x="476" y="586" on="0"/>
        <pt x="492" y="522" on="1"/>
        <pt x="508" y="462" on="0"/>
        <pt x="508" y="353" on="1"/>
        <pt x="508" y="290" on="0"/>
        <pt x="496" y="188" on="0"/>
        <pt x="482" y="149" on="1"/>
        <pt x="455" y="71" on="0"/>
        <pt x="354" y="-12" on="0"/>
        <pt x="275" y="-12" on="1"/>
        <pt x="172" y="-12" on="0"/>
        <pt x="112" y="62" on="1"/>
        <pt x="42" y="150" on="0"/>
      </contour>
      <contour>
        <pt x="132" y="353" on="1"/>
        <pt x="132" y="176" on="0"/>
        <pt x="213" y="60" on="0"/>
        <pt x="335" y="60" on="0"/>
        <pt x="418" y="177" on="0"/>
        <pt x="418" y="529" on="0"/>
        <pt x="376" y="588" on="1"/>
        <pt x="336" y="646" on="0"/>
        <pt x="213" y="646" on="0"/>
        <pt x="177" y="595" on="1"/>
        <pt x="132" y="529" on="0"/>
      </contour>
      <instructions/>
    </TTGlyph>
....下面还有很多代码

可以看到有 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,135评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,317评论 3 397
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,596评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,481评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,492评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,153评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,737评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,657评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,193评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,276评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,420评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,093评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,783评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,262评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,787评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,427评论 2 359

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,512评论 1 45
  • 猫眼电影的字体加密还是很折磨人的(最后会附上源码,中间讲解部分就用截图代替) 准备部分 猫眼电影主要在于字体加密,...
    煎炼阅读 2,935评论 0 5
  • 文/侯亦萱 2018年3月24日 晴 星期六 早上上班路上,微风徐徐,阳光洋洋洒洒大片大片穿过高楼投射到大地上,一...
    侯亦萱阅读 295评论 0 7
  • 为了推进财商教育在湖南的普及,让更多人学习财商,训练财商,实践财商智慧,在生活中真正成为一个理性明白的经济人,逐步...
    568cacf68373阅读 1,770评论 0 0
  • 自从区块链游戏出现爆款之后,无数大中小型团队都纷纷试水进入区块链游戏的大坑中。 今天我就将为大家分析一下最近刚刚上...
    joy_2519阅读 224评论 0 0