经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Ruby » 查看文章
字体反爬-动态字库
来源:cnblogs  作者:神一样了  时间:2019/4/16 8:58:52  对本文有异议

这次是动态字体库的字体反爬 

猫眼电影榜单国内票房榜,地址:https://maoyan.com/board/1

可以看出又是字体反爬,需要获得字体文件,定位字体文件的url,在页面或css里搜@font-face或font-famil

在network选font标签刷新页面几次发现每次用的字体都不一,加密用的字体库是动态的,手动建立关系表然后全局替换的方法不管用了。

 

解决方案

建立字符和动态字体库unicode的联系

原理

首先要了解字体文件内部有很多表,上篇用到记录unicode索引和字形关系的cmap表就在里面,

这此要用到glyf表,这个表里记录了具体的字形数据,表里只记录了字形数据,没有表头索引。

有专门的表loca按顺序记录glyf里每个字形的位置,在使用字体时通过loca表来找到具体字形。

所以反爬不是改变字形的话可以利用字形数据来找到自定义字体unicode与真实字符的联系。

这部分详细资料见 https://www.cnblogs.com/shenyiyangle/p/10700156.html 中的glyf表。

找关联的思路如图:

 

1.下载一个网站字体做为基准,建立基准字体unicode和真实字符关系。

2.在页面刷新网页字体库变化,重新下载字体,记为网站字体2,通过比较网站字体1和网站字体2的字形找到unicode和新unicode联系。

3.再通过相同的unicode来建立真实字符和变化字体库unicode的联系,最后全局将新unicode替换成真实字符。

 代码

  1. headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"}
  2. r=requests.get("https://maoyan.com/board/1",headers=headers)
  3. font1_url="http:"+re.findall("url\(\'(\/\/.*?woff)\'\)",r.text,re.M)[0]
    #创建font目录保存基准字体
  4. if not os.path.exists("font"):
  5. font1=requests.get(font1_url,headers=headers)
  6. os.mkdir("font")
  7. with open("./font/base.woff","wb")as f:
  8. f.write(font1.content)

下载一次基准字体并保存到font目录

  1. base_font = TTFont('./font/base.woff')
  2. base_dict=[]
  3. for i in range(len(baseFont.getGlyphOrder()[2:])):
  4. print(f"对应的数字{i+1}:")
  5. w=input()
  6. base_dict.append({"code":baseFont.getGlyphOrder()[2:][i],"num":w})

建立基准字体的unicode和真实字符的关系,看字体可以用FontCreator

 

上面的代码只需要执行一次,已经跳过前两项直接按顺序输入数字即可

 

  1. new_font_url="http:"+re.findall("url\(\'(\/\/.*?woff)\'\)",r.text,re.M)[0]
  2. font=requests.get(new_font_url,headers=headers)
  3. with open("new_font.woff","wb")as f:
  4. f.write(font.content)
  5. new_font = TTFont('new_font.woff')
  6. new_font_code_list=new_font.getGlyphOrder()[2:]

页面改变后的字体下载,获取unicode列表

 

  1. replace_dic=[]
  2. for i in range(10):
  3. news = new_font['glyf'][new_font_code_list[i]]
  4. for j in range(10):
  5. bases = base_font['glyf'][base_dict[j]["code"]]
  6. if news == bases:
  7. unicode=new_font_code_list[i].lower().replace("uni","&#x")+";"
  8. num= base_dict[j]["num"]
  9. replace_dic.append({"code":unicode,"num":num})

建立新unicode和字符的关系

 

  1. org_data=r.text
  2. for i in range(len(replace_dic)):
  3. new_data=new_data.replace(replace_dic[i]["code"],replace_dic[i]["num"])

全局替换unicode成字符

 

  1. tree=etree.HTML(org_data)
  2. dds=tree.xpath('//dl[@class="board-wrapper"]/dd')
  3. info=[]
  4. for dd in dds:
  5. title=dd.xpath('.//p[@class="name"]/a/@title')[0]
  6. star=dd.xpath('.//p[@class="star"]/text()')[0].replace("主演:","")
  7. time=dd.xpath('.//p[@class="releasetime"]/text()')[0].replace("上映时间:","")
  8. realticket=dd.xpath('.//p[@class="realtime"]//text()')[1]+dd.xpath('.//p[@class="realtime"]//text()')[2].strip()
  9. totalticket=dd.xpath('.//p[@class="total-boxoffice"]//text()')[1]+dd.xpath('.//p[@class="total-boxoffice"]//text()')[2].strip()
  10. info.append({"标题":title,"主演":star,"上映时间":time,"实时票房":realticket,"总票房":totalticket})

抓一些信息,下面是结果

 json保存成csv

  1. import csv
  2. csv_file = open("1325.csv", 'w', newline='')
  3. keys = []
  4. writer = csv.writer(csv_file)
  5. keys = info[1].keys()
  6. writer.writerow(keys)
  7. for dic in info:
  8. for key in keys:
  9. if key not in dic:
  10. dic[key ] = ''
  11. writer.writerow(dic.values())
  12. csv_file.close()

结果

引入的库

 

以上是全部代码

 

原文链接:http://www.cnblogs.com/shenyiyangle/p/10711065.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号