目的
获取汽车之家贴吧的内容信息
详细需求
思路解析
一、F12获取目标信息-进行分析
二、字体反爬解析-根据上一篇的文章,直接搜索关键词就好
三 根据其后的链接,保存为ttf在本地,查看TTF字体映射
字体工具:FontCreatorPortable,自行百度下载安装
在线工具:http://fontstore.baidu.com/static/editor/index.html
分析:
汽车之家字体反爬:
1.字体编码与文字皆为动态变换
2.文字为固定数目
3.每个贴子均有不同的加密TTF
4.对应的字体绘制坐标存在细微差别
解决方法:
1.先在本地保存一个TTF文件为模板,构建动态映射,使其一一对应
2.保存编码以及每个汉字所对应的一套坐标,这个坐标是用来绘制汉字的
3.获取网页源码所带的TTF链接,下载保存本地
4.提取刚下载的TTF文件的编码与每个编码所对应的一套坐标
5.与模板进行坐标比较,若在误差允许范围内,则判定为同一汉字
6.使刚下载的TTF文件实现一一映射的目标
大众点评字体反爬
1.编码动态变化但字体顺序固定不变
2.文字数目固定
3.具有规律性
解决方法:字体顺序不变,为每个编码一一映射汉字即可
图解
四,整体思路
1.获取网页源码
2.提取字体链接并下载保存
3.与模板字体进行坐标比较,实现编码与汉字一一映射
4.提取文章内容
5.对文章内容的加密字体进行解密
6.打印文章内容
源码实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jia666
# @Time : 2020/10/09 9:08
import re
import requests
from html import unescape
from fontTools.ttLib import TTFont
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.text
self.html = re.sub('\s', '', self.html) # 去空格
def TTF_parse(self):
'字体的分析处理'
TTF_link=re.findall(",url\('(.*?)'\)format\('woff'\)",self.html,re.S)[0] #提取贴子字体链接
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:] #获取字体的编码
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:]
self.utf8List = ['&#x' + uni[3:] 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):
# print(uni_list2[n2 - 1], word_list[n1 - 1])
self.x_list.append(word_list[n1 - 1])
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):
te = re.findall('<divclass="rconten">(.*?)]<\/div>', self.html, re.S)[0]#贴吧内容提取
# print(te)
for i in range(len(self.utf8List)): #替换加密文字
# print(self.utf8List[i].lower(), self.x_list[i])
# # if self.utf8List[i] in te:
te = te.replace(self.utf8List[i].lower()+';', self.x_list[i])
word = re.sub('<.*?>', '', unescape(te))#提取文字
word=word.replace('。', '\n') #换行替换
print(word) #打印处理后的内容
def main(self):
self.Get_html() #网页请求
self.TTF_parse() #字体动态映射构建
self.Content_parse()#贴子文字替换与提取
if __name__ == '__main__':
url='https://club.autohome.com.cn/bbs/thread/1f05b4da4448439b/76044817-1.html#%23%23' #论坛帖子地址
example=Car_Family(url)
注意:源码不能直接用,需要根据实际情况,下载一个作为模板并改写1.ttf的映射关系
实现效果
参考文章:
作者:Mars_DD
https://blog.csdn.net/xing851483876/article/details/82928607
汽车之家的字体反爬解决方案来自此处