字体映射反爬

网站链接:http://www.porters.vip/confusion/movie.html

本文涉及

import requests
import re
import hashlib
from parsel import Selector
from fontTools.ttLib import TTFont

网站的关键数据由其他字符替代

 F12里面无法显示可以从网页源码里找,如图

先把其他常规内容搞上,

url = 'http://www.porters.vip/confusion/movie.html'
resp = requests.get(url)
sel = Selector(resp.text)

# 获取其他未加密的电影介绍
movie_data = sel.css("div.movie-brief-container").css("::text").extract()
for i in movie_data:
    if "".join(i.split()):    
        print("".join(i.split()))

 在试过css,xpath和bs4后,

发现"\u"型的数据只能用re才能提取

code_re = re.compile('<span class="stonefont">(.*?)</span>')
font_data = code_re.findall(resp.text)


# ['&#xe624.&#xe9c7',
# '&#xf593&#xe9c7&#xe9c7.&#xe624万',
# '&#xea16&#xe339.&#xefd4&#xf19a']

接就是解决 字体映射问题

在network里面找到一个font类型数据,

woff(Web Open Font Format)文件

目前最主要的几种网络字体(web font)格式包括WOFF,SVG,EOT,OTF/TTF。

 从启动器里看,要先获取movie.css文件,才能提取woff文件

 

url = 'http://www.porters.vip/confusion/movie.html'
resp = requests.get(url)
sel = Selector(resp.text)

# 提取页面加载的所有css文件路径
css_path = sel.css('link[rel=stylesheet]::attr(href)').extract()
woffs = []

# 拼接movie.css链接,请求获取、拼接woff链接
for c in css_path:
    # 拼接css链接
    css_url = parse.urljoin(url, c)
    css_resp = requests.get(css_url)

    # 匹配需要的woff链接
    woff_path = re.findall("src:url\('..(.*.woff)'\) format\('woff'\);", css_resp.text)
    # 路径存在则执行
    if woff_path:
        woffs += woff_path

# 请求、下载woff文件
woff_url = 'http://www.porters.vip/confusion' + woffs.pop()
woff = requests.get(woff_url)
with open('movie.woff', 'wb') as f:
    f.write(woff.content)

woff文件在线打开方式:FontEditor

使用fontTools库在py中打开

'&#xe624.&#xe9c7'  

可以发现字体编码和woff文件的区别 :" &#x",其它字母为大写

 安装方式: pip install fontTools

from fontTools.ttLib import TTFont

# 加载字体文件
font = TTFont('movie.woff')

# 转换文件格式为:xml格式(可以通过浏览器打开)
font.saveXML('maoyan.xml')

# 通过字体编码获取字形数据
font['glyf'].glyphs.get(uni_name).data

通过FontEditor手动构建字体编码和所知字体的映射,通过fontTools获取字形数据并md5加密(方便对比,是否为相同字体)

words = font['glyf'].glyphs.get(uni_name).data
md5_code = hashlib.md5(words).hexdigest()
data_dict['hex'] = md5_code

#  效果

base_font = [{"name": "uniEE76", "value": "0", "hex": "fc170db1563e66547e9100cf7784951f"},
             {"name": "uniF57B", "value": "1", "hex": "251357942c5160a003eec31c68a06f64"},
             {"name": "uniE7DF", "value": "2", "hex": "8a3ab2e9ca7db2b13ce198521010bde4"},
             {"name": "uniF19A", "value": "3", "hex": "712e4b5abd0ba2b09aff19be89e75146"},
             {"name": "uniF593", "value": "4", "hex": "e5764c45cf9de7f0a4ada6b0370b81a1"},
             {"name": "uniEA16", "value": "5", "hex": "c631abb5e408146eb1a17db4113f878f"},
             {"name": "uniE339", "value": "6", "hex": "0833d3b4f61f02258217421b4e4bde24"},
             {"name": "uniE9C7", "value": "7", "hex": "4aa5ac9a6741107dca4c5dd05176ec4c"},
             {"name": "uniEFD4", "value": "8", "hex": "c37e95c05e0dd147b47f3cb1e5ac60d7"},
             {"name": "uniE624", "value": "9", "hex": "704362b6e0feb6cd0b1303f10c000f95"}]

 代码如下

font_list = []

# 将字体编码串分离,并替换为woff文件一样的字体名称
for i in range(len(font_data)):

    # 用字符串将分离的文字重新链接
    words = ''
    for x in font_data[i].upper().split("&#X"):
        
        for y in x.split("."):
            if y:
                if chi_re.search(y):

                # translate()自定义的解密函数

                    words+=translate("uni"+y[:-1])
                else:
                    words+=translate("uni"+y)

    # 将解密后的字体添加进列表
    font_list.append(words)

解密函数的代码

# 解密函数
def translate(code):
        for i in base_font:

            # 获取字形数据
            code_glyf = font["glyf"].glyphs.get(code).data
            
            # 使用hashlib进行md5加密
            code_md5 = hashlib.md5(code_glyf).hexdigest()

            if code == i.get("name") and code_md5 == i.get("hex"):
                return i.get("value")

 最终结果

还可以参考这篇文章的思路,

使用selenium截取指定标签位置的数据,配合OCR来识别提取内容

 源码:

https://github.com/thinkloading/CSDN-/blob/316650c1fed5918d84ec07f2642c8958b004c30f/%E5%AD%97%E4%BD%93%E5%8F%8D%E7%88%AC.py

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值