注意: 不同页面的字体反爬也不同, 看能不能适用 这里有大佬教程,非常详细:
转载:https://blog.csdn.net/bestyellow/article/details/119801785
# -*- coding: utf-8 -*- import re import requests from html import unescape from fontTools.ttLib import TTFont from bs4 import BeautifulSoup class Car_Family(object): def __init__(self, url): self.head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36', } self.url = url # 目标帖子地址 self.main() def Get_html(self): 源网页请求 with requests.get(self.url, headers=self.head) as res: self.html=res.content.decode('gb2312') self.html = re.sub('\s', '', self.html) # 去空格 self.content = BeautifulSoup(res.text, 'lxml') def TTF_parse(self): '字体的分析处理' TTF_link=re.findall(",url\('(.*?)'\)format\('woff\)",self.html,re.S)[0] #提取贴子字体链接
print(TTF_link)
css = self.content.select('style')
for i in range(len(css)):
TTFObj = re.findall(",url\('(.*?)'\) format\('woff'\)", css[i].string, re.S) # 提取贴子字体链接
if len(TTFObj) > 0:
TTF_link = TTFObj[0]
break
b = requests.get('http:' + TTF_link, headers=self.head).content # 字体链接请求
with open('汽车之家2.ttf', 'wb')as f: # 保存到本地
f.write(b)
font1 = TTFont('汽车之家1.ttf') # 本地预先下载的字体文件
u_list = font1.getGlyphOrder()[1:] # 获取字体的编码
# 汽车之家1.ttf
word_list = '盘光下副雨过内量当二动一保硬远着坐地无耗小里右更中冷不开多泥坏四上自软矮七得问孩九皮灯响路短比门八级少十真高油和电' \
'性味控六启档的音很只空了五排外三机加好是来左近手呢长公有大身实低养' # 字体编码对应的汉字
be_p1 = [] # 保存38个字符的(x,y)信息
for uni in u_list:
p1 = [] # 保存一个字符的(x,y)信息
p = font1['glyf'][uni].coordinates # 获取对象的x,y信息,返回的是一个GlyphCoordinates对象,可以当作列表操作,每个元素是(x,y)元组
for f in p: # 把GlyphCoordinates对象改成一个列表
p1.append(f)
be_p1.append(p1)
font2 = TTFont('汽车之家2.ttf') # 网络刚下载的字体文件,用于参考1.ttf比较后映射对应文字
uni_list2 = font2.getGlyphOrder()[1:]
# 获取的字体内容中显示的都是 \uec66 \uecc8 等格式 非  eval转\u时前面要加eval("u'\uec66'")
self.utf8List = [eval('u\'\\u' + uni[3:].lower() + '\'') for uni in uni_list2]
on_p1 = []
for i in uni_list2:
pp1 = []
p = font2['glyf'][i].coordinates
for f in p:
pp1.append(f)
on_p1.append(pp1)
n2 = 0 # uni下标计数
self.x_list = []
for d in on_p1:
n2 += 1
n1 = 0
for a in be_p1:
n1 += 1
if self.comp(a, d):
self.x_list.append(word_list[n1 - 1])
print(self.x_list)
def comp(self, l1, l2): # 定义一个比较函数,比较两个列表的坐标信息是否相同
if len(l1) != len(l2): # 两数据的数目不等
return False # 判断结束
else: # 数据相同
mark = 1 # 成功标志:1代表True,0代表False
for i in range(len(l1)):
if abs(l1[i][0] - l2[i][0]) < 40 and abs(l1[i][1] - l2[i][1]) < 40:
pass
else:
mark = 0
break
return mark
def Content_parse(self):
tes = self.content.find_all('div', attrs={
'class', 'text-con'})
for k in tes:
te = k.text
if te == "":
pass
# print(te)
for i in range(len(self.utf8List)): # 替换加密文字
te = te.replace(self.utf8List[i].lower(), self.x_list[i])
word = re.sub('<.*?>', '', unescape(te)) # 提取文字
print(word) # 打印处理后的内容
def main(self):
self.Get_html() # 网页请求
self.TTF_parse() # 字体动态映射构建
self.Content_parse() # 贴子文字替换与提取
if __name__ == '__main__':
# 这两个链接都可以适用但是需要替换字体1和word_list
# url='https://club.autohome.com.cn/bbs/thread/1f05b4da4448439b/76044817-1.html#%23%23' #论坛帖子地址
url = 'https://k.autohome.com.cn/detail/view_01fve1ynmc6grk6chh60sg0000.html' # 论坛帖子地址
example = Car_Family(url)