python爬虫进阶-汽车之家贴吧信息(字体反爬-动态映射)

目的

获取汽车之家贴吧的内容信息

详细需求

汽车之家贴吧
在这里插入图片描述

思路解析

一、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
汽车之家的字体反爬解决方案来自此处

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jia666666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值