一、背景
问题:xpath
提取章节发现字体加密
待破解的 HTML
:
<dd class="col-sm-3">
<a href="/books/34/34652/18381474.html">
<i></i><i></i>章 醒
</a>
</dd>
二、破解
破解方案
- 正则提取章节部分,获取加密部分内容(
xpath
提取后是加密后的而不是原始数据,所以这里采用正则) - 下载字体文件,使用 百度字体编辑器 解析字体文件,获取对应关系
- 将字体文件转换为
xml
,解析xml
获取字体对应关系
正则提取
chapter_list = re.findall("<dd class=\"col-sm-3\"><a href=.*?>(.*?)</a>", html)
提取后的结果:
#  就是需要破解的、
[
'<i></i><i></i>章 醒',
'<i></i>二章 谁'
]
百度字体编辑器解密
f12
打开刷新浏览器获取 font.ttf
字体文件,上传到 百度字体编辑器 就会得到一个字体对应关系:
{'uniE800': '的', 'uniE801': '一', 'uniE802': '是', 'uniE803': '了',
'uniE804': '我', 'uniE805': '不', 'uniE806': '人', 'uniE807': '在',
'uniE808': '他', 'uniE809': '有', 'uniE80A': '这', 'uniE80B': '个',
'uniE80C': '上', 'uniE80D': '们', 'uniE80E': '来', 'uniE80F': '到',
'uniE810': '时', 'uniE811': '大', 'uniE812': '地', 'uniE813': '为',
'uniE814': '子', 'uniE815': '中', 'uniE816': '你', 'uniE817': '说',
'uniE818': '生', 'uniE819': '国', 'uniE81A': '年', 'uniE81B': '着',
'uniE81C': '就', 'uniE81D': '那', 'uniE81E': '和', 'uniE81F': '要',
'uniE820': '她', 'uniE821': '出', 'uniE822': '也', 'uniE823': '得',
'uniE824': '里', 'uniE825': '后', 'uniE826': '自', 'uniE827': '以',
'uniE828': '会', 'uniE829': '家', 'uniE82A': '可', 'uniE82B': '下',
'uniE82C': '而', 'uniE82D': '过', 'uniE82E': '天', 'uniE82F': '去',
'uniE830': '能', 'uniE831': '对', 'uniE832': '小', 'uniE833': '多',
'uniE834': '然', 'uniE835': '于', 'uniE836': '心', 'uniE837': '学',
'uniE838': '么', 'uniE839': '之', 'uniE83A': '都', 'uniE83B': '好',
'uniE83C': '看', 'uniE83D': '起', 'uniE83E': '发', 'uniE83F': '当',
'uniE840': '没', 'uniE841': '成', 'uniE842': '只', 'uniE843': '如',
'uniE844': '事', 'uniE845': '把', 'uniE846': '还', 'uniE847': '用',
'uniE848': '第', 'uniE849': '样', 'uniE84A': '道', 'uniE84B': '想',
'uniE84C': '作', 'uniE84D': '种', 'uniE84E': '开', 'uniE84F': '美',
'uniE850': '总', 'uniE851': '从', 'uniE852': '无', 'uniE853': '情',
'uniE854': '己', 'uniE855': '面', 'uniE856': '最', 'uniE857': '女',
'uniE858': '但', 'uniE859': '现', 'uniE85A': '前', 'uniE85B': '些',
'uniE85C': '所', 'uniE85D': '同', 'uniE85E': '日', 'uniE85F': '手',
'uniE860': '又', 'uniE861': '行', 'uniE862': '意', 'uniE863': '动'}
提取 xml
将 font.ttf
转换为 xml
文件,提取其中的字体对应关系:
# pip install fontTools
from fontTools.ttLib import TTFont
def process_font():
font = TTFont("fonteditor.ttf")
font.saveXML("fonteditor.xml")
font.xml
<!-- 提取其中关键部分 -->
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0xe800" name="uniE800"/><!-- ???? -->
<map code="0xe801" name="uniE801"/><!-- ???? -->
<map code="0xe802" name="uniE802"/><!-- ???? -->
<map code="0xe803" name="uniE803"/><!-- ???? -->
<map code="0xe804" name="uniE804"/><!-- ???? -->
<map code="0xe805" name="uniE805"/><!-- ???? -->
<map code="0xe806" name="uniE806"/><!-- ???? -->
....
</cmap_format_4>
</cmap>
解析:
def parse_xml():
from xml.dom.minidom import parse
import xml.dom.minidom
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("fonteditor.xml")
collection = DOMTree.documentElement
font_info_dict = {}
# 在集合中获取所有 cmap
cmap = collection.getElementsByTagName("cmap")
for item in cmap:
cmap_format_4 = item.getElementsByTagName("cmap_format_4")
for cmp_ in cmap_format_4:
if cmp_.getAttribute("platformID") == "0":
map_list = cmp_.getElementsByTagName("map")
for map in map_list:
code = map.getAttribute("code")
name = map.getAttribute("name")
# 0xe806 转换为 
code = f'{re.sub("0xe", "", code)};'
# print(code, name)
font_info_dict[code] = name
print(font_info_dict)
对应关系:
{'': 'uniE800', '': 'uniE801'...}
以上三步走完之后差不多就可以完整解析了,完整代码