吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8980|回复: 24
上一主题 下一主题
收起左侧

[Python 原创] 字体反爬解决方案——突破抖音字体反爬机制

  [复制链接]
跳转到指定楼层
楼主
Samuel2h3 发表于 2020-2-21 09:46 回帖奖励
本帖最后由 Samuel2h3 于 2020-2-21 09:51 编辑

字体反爬案例

爬取一些网站的信息时,偶尔会碰到这样一种情况:网页浏览显示是正常的,用 python 爬取下来是乱码,F12用开发者模式查看网页源代码也是乱码。这种一般是网站设置了字体反爬。

1.  准备url

网址:  https://www.iesdouyin.com/share/user/88445518961

2. 获取数据 分析字体加密方式

任务:爬取个人信息展示页中的关注、粉丝人数和点赞数据,页面内容如图 下 所示。

在编写代码之前,我们需要确定目标数据的元素定位。定位时,我们在 HTML 中发现了一些奇怪的符号,HTML 代码如下:

页面中重要的数据都是一些奇怪的字符,本应该显示数字的地方在 HTML 中显示的是""。

要注意的是,Chrome 开发者工具的元素面板中显示的内容不一定是相应正文的原文,要想知道 "" 符号是什么,还需要到网页源代码中确认。对应的网页源代码如下:

</span><span class="follower block">
  <span class="num">    
    <i class="icon iconfont follow-num">  </i>
    <i class="icon iconfont follow-num">  </i>
    <i class="icon iconfont follow-num">  </i>
    <i class="icon iconfont follow-num">  </i>.
    <i class="icon iconfont follow-num">  </i>w 
  </span>
  <span class="text">粉丝</span> 
</span>

抖音将这些数字的数据都做了字体进行映射,用了他们自己的字体,那我们可以看看开发者工具的 network 查看他所用的字体,一般都是 wolf 或者 ttf 结尾的,可以看到:  

我们多刷新几次,发现一直访问的是这个字体文件:  

https://s3.pstatp.com/ies/resource/falcon/douyin_falcon/static/font/iconfont_9eb9a50.woff

我们先把这个文件下载下来,font creator软件打开,也可以使用在线工具 https://font.qqe2.com/

看到这个图片我们就明白了字体与数字的关系

这个时候,需要大家安装pip install fontTools,使用fontTool打开ttf文件转化成xml文件

采用以下代码

from fontTools.ttLib import TTFont
font_1 = TTFont('douyin.ttf')
font_1.saveXML('font_1.xml')

这个就是我们需要找的映射,配合上面在 字体和数字的对应,一起用,这个就破解了。

3. 代码实现字体映射关系

关系映射表

regex_list = [
        {'name': ['0xe602', '0xe60e', '0xe618'], 'value': '1'},
        {'name': ['0xe603', '0xe60d', '0xe616'], 'value': '0'},
        {'name': ['0xe604', '0xe611', '0xe61a'], 'value': '3'},
        {'name': ['0xe605', '0xe610', '0xe617'], 'value': '2'},
        {'name': ['0xe606', '0xe60c', '0xe619'], 'value': '4'},
        {'name': ['0xe607', '0xe60f', '0xe61b'], 'value': '5'},
        {'name': ['0xe608', '0xe612', '0xe61f'], 'value': '6'},
        {'name': ['0xe609', '0xe615', '0xe61e'], 'value': '9'},
        {'name': ['0xe60a', '0xe613', '0xe61c'], 'value': '7'},
        {'name': ['0xe60b', '0xe614', '0xe61d'], 'value': '8'}
    ]
4. 完整代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import requests
from lxml import etree

start_url = ' https://www.iesdouyin.com/share/user/88445518961'

def get_real_num(content):
    content = content.replace(' &#', '0').replace('; ', '')
    regex_list = [
        {'name': ['0xe602', '0xe60e', '0xe618'], 'value': '1'},
        {'name': ['0xe603', '0xe60d', '0xe616'], 'value': '0'},
        {'name': ['0xe604', '0xe611', '0xe61a'], 'value': '3'},
        {'name': ['0xe605', '0xe610', '0xe617'], 'value': '2'},
        {'name': ['0xe606', '0xe60c', '0xe619'], 'value': '4'},
        {'name': ['0xe607', '0xe60f', '0xe61b'], 'value': '5'},
        {'name': ['0xe608', '0xe612', '0xe61f'], 'value': '6'},
        {'name': ['0xe609', '0xe615', '0xe61e'], 'value': '9'},
        {'name': ['0xe60a', '0xe613', '0xe61c'], 'value': '7'},
        {'name': ['0xe60b', '0xe614', '0xe61d'], 'value': '8'}
    ]

    for i1 in regex_list:
        for font_code in i1['name']:
            content = re.sub(font_code, str(i1['value']), content)

    html = etree.HTML(content)
    douyin_info = {}
    # 获取抖音ID
    douyin_id = ''.join(html.xpath("//div[@class='personal-card']/div[@class='info1']/p[@class='shortid']/text()"))
    douyin_id = douyin_id.replace('抖音ID:', '').replace(' ', '')
    i_id = ''.join(html.xpath("//div[@class='personal-card']/div[@class='info1']/p[@class='shortid']/i/text()"))
    douyin_info['douyin_id'] = str(douyin_id) + str(i_id)

    # 关注
    douyin_info['follow_count'] = ''.join(html.xpath(
        "//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='focus block']//i/text()"))
    # 粉丝
    fans_value = ''.join(html.xpath(
        "//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='follower block']//i[@class='icon iconfont follow-num']/text()"))

    unit = html.xpath(
        "//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='follower block']/span[@class='num']/text()")
    if unit[-1].strip() == 'w':
        douyin_info['fans'] = str(float(fans_value) / 10) + 'w'
        fans_count = douyin_info['fans'][:-1]
        fans_count = float(fans_count)
        fans_count = fans_count * 10000
        douyin_info['fans_count'] = fans_count
    else:
        douyin_info['fans'] = fans_value
        douyin_info['fans_count'] = fans_value
    # 点赞
    like = ''.join(html.xpath(
        "//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='liked-num block']//i[@class='icon iconfont follow-num']/text()"))
    unit = html.xpath(
        "//div[@class='personal-card']/div[@class='info2']/p[@class='follow-info']//span[@class='liked-num block']/span[@class='num']/text()")
    if unit[-1].strip() == 'w':
        douyin_info['like'] = str(float(like) / 10) + 'w'
        like_count = douyin_info['like'][:-1]
        like_count = float(like_count)
        like_count = like_count * 10000
        douyin_info['like_count'] = like_count
    else:
        douyin_info['like'] = like
        douyin_info['like_count'] = like

    # 作品
    worko_count = ''.join(html.xpath("//div[@class='video-tab']/div/div[1]//i/text()"))
    douyin_info['work_count'] = worko_count
    return douyin_info

def get_html():
    header = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36'
    }
    response = requests.get(url=start_url, headers=header, verify=False)
    return response.text

def run():
    content = get_html()
    info = get_real_num(content)
    print(info)

if __name__ == '__main__':
    run()
5.  结果

免费评分

参与人数 17吾爱币 +23 热心值 +13 收起 理由
gzq830510 + 1 + 1 用心讨论,共获提升!
无心鱼 + 1 + 1 我觉得可以
lande + 1 + 1 谢谢@Thanks!
ghy_37854 + 1 谢谢@Thanks!
天空宫阙 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lene + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
12021049 + 1 用心讨论,共获提升!
苏紫方璇 + 6 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Monitor + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
evayang + 1 + 1 用心讨论,共获提升!
蚯蚓翔龙 + 1 + 1 用心讨论,共获提升!
飞龙project + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
98km6 + 1 + 1 技术大佬,威武霸气
zxy20014 + 1 鼓励转贴优秀软件安全工具和文档!
仓佑加错 + 1 + 1 我很赞同!
田田爱崽崽 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| Samuel2h3 发表于 2020-2-23 10:42 |楼主
倾情 发表于 2020-2-23 10:00
厉害了,敢问尊者,何以发现此音用此字体,无意间或者学过这方面知识呢,可否告知

通过浏览器F12抓包,你会发现,它在发起网络请求的时候,请求的有woff的字体文件。
推荐
 楼主| Samuel2h3 发表于 2020-4-8 09:37 |楼主
DarkeraiF 发表于 2020-4-7 18:37
您好,请问下在网页源代码中显示的也是乱码,无法进行替换怎么解决?谢谢

乱码是什么样的吗?是这个网址吗?
沙发
田田爱崽崽 发表于 2020-2-21 09:50
老铁,感谢你分享教程。但是你的图片貌似加载有问题,是图床不行吗?
3#
 楼主| Samuel2h3 发表于 2020-2-21 09:52 |楼主
田田爱崽崽 发表于 2020-2-21 09:50
老铁,感谢你分享教程。但是你的图片貌似加载有问题,是图床不行吗?

已经修改过了,刚刚没有设置好
4#
田田爱崽崽 发表于 2020-2-21 09:54
Samuel2h3 发表于 2020-2-21 09:52
已经修改过了,刚刚没有设置好

好的,感谢分享好的技术类文档
5#
夜泉 发表于 2020-2-21 10:08
其实并不是反扒,只能说是官方网站使用了自己的字体,一不小心就变成了反扒了
6#
在线小学生 发表于 2020-2-21 10:25
666  老铁  谢谢分享
7#
_知鱼之乐 发表于 2020-2-21 10:31
支持一下
8#
wolaileo 发表于 2020-2-21 10:47
很好的学习资料。谢谢
9#
FenLin 发表于 2020-2-21 10:50
特别溜。交流催进技术发展。
头像被屏蔽
10#
pengpost 发表于 2020-2-21 12:30
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 23:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表