一、字体反爬
1、什么是字体反爬?
开发者创作了一种字体(字体代号);网页中显示的就是这种字体代号。
字体反爬也叫CSS反爬,就是因为这个字体是隐藏在我们css文件当中的一个.ttf文件。
​2、如何解决字体反爬?(思路:先获取这些文本内容,然后在解决字体的问题)
(1)先找到.ttf文件,需并把它转换成xml文件;
(2)分析xml文件 + FontCreator(360应用市场搜索下载即可);
(3) 找出字体对应的映射关系,和真实的字体做替换。

3、案例
需求:爬取文字字体内容
思路:我们先获取这些文本内容,然后在解决字体的问题。

​目标url https://club.autohome.com.cn/bbs/thread/665330b6c7146767/80787515-1.html
第一步 页面分析
​(1)爬取要素是否在网页源码中:

(2)文本内容://div[@class=“tz-paragraph”]

第二步 实现步骤
(1)获取文本内容:

我们猜测:\uedb8 → 大 ;\ueca3 → 了
(2)解决字体问题:
右键查看网页源码,ctrl+f,搜索ttf,得到一个url连接(//k3.autoimg.cn/g1/M02/D0/99/wKgHFVsUz1eAH_VRAABj9PS-ubk57…ttf)

我们打开这个连接,下载得到ttf文件:

我们可以在FontCreator中打开这个ttf文件,如下图:(后面构建字体列表的顺序就是由此而来)

接着我们通过fontTools模块将ttf文件保存为xml文件,
并在sublime中打开查看该文件:

我们接下来:

  • 构建编码列表
  • 构建字体列表
  • 编码与字体一一对应做替换

    补充:
    python内置函数:eval()
    eval() 函数用来执行一个字符串表达式,并返回表达式的计算结果。
    语法:eval(expression[, globals[, locals]])
    参数
    expression – 表达式。
    globals – 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
    locals – 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。

完整代码:

import requests
from lxml import etree
from fontTools.ttLib import TTFont # pip install fontToolsurl = 'https://club.autohome.com.cn/bbs/thread/665330b6c7146767/80787515-1.html'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36'
}res = requests.get(url,headers=headers)
res_html = res.texthtml = etree.HTML(res_html)
content_list = html.xpath('//div[@class="tz-paragraph"]//text()')
content_str = ''.join(content_list)
# print(content_list)# 打开.ttf文件
font = TTFont('wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf')
# 保存为.xml文件
# font.saveXML('fonts.xml')# 构建编码列表
uniList = font.getGlyphOrder() #在font文件当中找到name所对应的值
uni_lst = []   # uniEDB8 -- > \uedb8
for i in uniList[1:]:r = eval(r"'\u" + i[3:] + "'")uni_lst.append(r)#构建字体列表
word_list = ['很', '五', '多', '远', '大', '十', '更', '了', '的', '矮', '不', '少', '九', '三', '八', '一', '右', '坏', '近', '着', '呢', '左', '是', '长', '六', '上', '短', '七', '高', '二', '得', '好', '下', '和', '四', '地', '小', '低']# 替换
for i in range(len(word_list)):content_str = content_str.replace(uni_lst[i],word_list[i])
print(content_str)

二、JS反爬
js反爬,它的分析流程和处理流程都是非常复杂和漫长

如何学习js反爬?
(1) 精通JS语言(你能够熟知js这门语言的基本语法)
(2)精通JS中常见的加密算法(并不一定都是算法)
(3)套路经验(调试JS代码)

1、 环境搭建
(1)node.js开发环境(在https://nodejs.org/en/download/下载)
(2) 准备js调试工具 (发条js调试工具)
(3)安装一个PyeXECjs模块: pip install PyeXECjs

2、 JS中常见的算法(自己拓展)
(1)md5加密算法 线性散列算法 可以产出一个128位的散列值 用于确保信息传输完整的一致性
经过md5加密后产生的是一个固定长度的数据(32位、16位)

(2) DES/AES加密
统称为 对称加密 : 加密运算和解密运算使用的是同样的密钥
密钥:一组随机的字符串
对称的意思可以理解成:锁门和开门的都是同一把钥匙

AES/DES的区别

  • 加密后的密文长度不同
    DES加密后的密文长度是8的整数倍
    AES加密后端密文长度是16的整数倍
  • 应用场景不同
    一般的企业用DES足够
    需求更高可以使用AES
    留意字眼:encrypt() 加密、 decrypt()解密

    (3)RSA加密
    非对称加密:有2个密钥
  • 公开密钥(publickey 公钥)
  • 私有密钥(privatekey 私钥)
    公钥和私钥是一对 ,如果用对应的公钥进行加密只有用对应的私钥才可以进行解密

    留意字眼:setPublickey() 、setPrivateKey()



第三个 案例
微信公众平台js算法逆向
问题描述:

实际我们输入的是123456,而pwd却是一串由字母和数字组成的32位‘密文’

那么,我们要怎样逆向的把这串密文解析得到123456呢?也就是如何解决: 密码js逆向的问题。
答案是:我们要结合断点,来进行一些相关的测试以及调试

步骤:
(1)经过分析我们要找的关键字是pwd (不要全局搜索,因为全局搜索不可以打断点)

通过点击 search选项 搜索关键字pwd 我们发现了一个loginpagexxx.js数据
(2)点击上图蓝色数据,并点击{}进行格式化

然后ctrl+f继续搜索关键字pwd,得到有20个这样的字段:

(3)打断点
我们浏览上述20个字段,有可疑的我们就打断点(即点击该行)

备注:记住,js逆向中看到get/set,什么作用都没有,不需要在这里打断点。
(4)再次点击登录,发现断点停留在1269行,如下图:

所以,该行的u函数,就是实现密码加密的。
(5)点击进入到u函数,如下图,直接就跳转到了黄色部分,

我们又看到一个函数function(t,e,n),其返回的就是我们的密文。
也就是说,我们执行函数function就能得到对应的密文。

(6)复制整个function函数,标志是花括号{}(js中对函数的定义的标志是花括号)

(7)点击上图左下角的加载代码,发现报错:n未定义

也就相当于没有定义变量,为此,我们在调试工具的首行加上一句代码: var n = {}
再加载代码。

(8)在调试工具中修改代码,并调用得到结果:

补充:
(9)如何在python中实现js逆向的逻辑,即execjs模块的使用:
①首先将调试工具中的代码完整的复制粘贴到js文件中(也就是保存文件时,后缀是.js),如下图:

②和上述js文件同目录下新建一个py文件,具体内容如下:

(10)eval() 函数的作用:

总结:
1 经过分析我们要找的关键字是pwd (不要全局搜索,因为全局搜索不可以打断点)
逐个js文件分析,关注 login字眼

2 分析调试Js代码
可以把怀疑的代码打断点 进行测试
通过断点测试 定位出相应的可能做了Js加密的逻辑

3 点击看一下它的内部实现
经过分析 测试我们需要哪些 Js逻辑代码

4 通过Js代码调试工具 不断的尝试 保证js语法没有错误

附:

import execjsnode = execjs.get()
ctx = node.compile(open('wechat.js',encoding='utf-8').read())funcName = 'getPwd("123456")'
pwd = ctx.eval(funcName)
print(pwd)

var n = {}
function l(t, e) {
var n = (65535 & t) + (65535 & e);
return (t >> 16) + (e >> 16) + (n >> 16) << 16 | 65535 & n
}
function a(t, e, n, o, r, i) {
return l((s = l(l(e, t), l(o, i))) << (a = r) | s >>> 32 - a, n);
var s, a
}
function f(t, e, n, o, r, i, s) {
return a(e & n | ~e & o, t, e, r, i, s)
}
function d(t, e, n, o, r, i, s) {
return a(e & o | n & ~o, t, e, r, i, s)
}
function h(t, e, n, o, r, i, s) {
return a(e ^ n ^ o, t, e, r, i, s)
}
function m(t, e, n, o, r, i, s) {
return a(n ^ (e | ~o), t, e, r, i, s)
}
function c(t, e) {
t[e >> 5] |= 128 << e % 32,
t[14 + (e + 64 >>> 9 << 4)] = e;
var n, o, r, i, s, a = 1732584193,
c = -271733879,
u = -1732584194,
p = 271733878;
for (n = 0; n < t.length; n += 16) a = f(o = a, r = c, i = u, s = p, t[n], 7, -680876936),
p = f(p, a, c, u, t[n + 1], 12, -389564586),
u = f(u, p, a, c, t[n + 2], 17, 606105819),
c = f(c, u, p, a, t[n + 3], 22, -1044525330),
a = f(a, c, u, p, t[n + 4], 7, -176418897),
p = f(p, a, c, u, t[n + 5], 12, 1200080426),
u = f(u, p, a, c, t[n + 6], 17, -1473231341),
c = f(c, u, p, a, t[n + 7], 22, -45705983),
a = f(a, c, u, p, t[n + 8], 7, 1770035416),
p = f(p, a, c, u, t[n + 9], 12, -1958414417),
u = f(u, p, a, c, t[n + 10], 17, -42063),
c = f(c, u, p, a, t[n + 11], 22, -1990404162),
a = f(a, c, u, p, t[n + 12], 7, 1804603682),
p = f(p, a, c, u, t[n + 13], 12, -40341101),
u = f(u, p, a, c, t[n + 14], 17, -1502002290),
a = d(a, c = f(c, u, p, a, t[n + 15], 22, 1236535329), u, p, t[n + 1], 5, -165796510),
p = d(p, a, c, u, t[n + 6], 9, -1069501632),
u = d(u, p, a, c, t[n + 11], 14, 643717713),
c = d(c, u, p, a, t[n], 20, -373897302),
a = d(a, c, u, p, t[n + 5], 5, -701558691),
p = d(p, a, c, u, t[n + 10], 9, 38016083),
u = d(u, p, a, c, t[n + 15], 14, -660478335),
c = d(c, u, p, a, t[n + 4], 20, -405537848),
a = d(a, c, u, p, t[n + 9], 5, 568446438),
p = d(p, a, c, u, t[n + 14], 9, -1019803690),
u = d(u, p, a, c, t[n + 3], 14, -187363961),
c = d(c, u, p, a, t[n + 8], 20, 1163531501),
a = d(a, c, u, p, t[n + 13], 5, -1444681467),
p = d(p, a, c, u, t[n + 2], 9, -51403784),
u = d(u, p, a, c, t[n + 7], 14, 1735328473),
a = h(a, c = d(c, u, p, a, t[n + 12], 20, -1926607734), u, p, t[n + 5], 4, -378558),
p = h(p, a, c, u, t[n + 8], 11, -2022574463),
u = h(u, p, a, c, t[n + 11], 16, 1839030562),
c = h(c, u, p, a, t[n + 14], 23, -35309556),
a = h(a, c, u, p, t[n + 1], 4, -1530992060),
p = h(p, a, c, u, t[n + 4], 11, 1272893353),
u = h(u, p, a, c, t[n + 7], 16, -155497632),
c = h(c, u, p, a, t[n + 10], 23, -1094730640),
a = h(a, c, u, p, t[n + 13], 4, 681279174),
p = h(p, a, c, u, t[n], 11, -358537222),
u = h(u, p, a, c, t[n + 3], 16, -722521979),
c = h(c, u, p, a, t[n + 6], 23, 76029189),
a = h(a, c, u, p, t[n + 9], 4, -640364487),
p = h(p, a, c, u, t[n + 12], 11, -421815835),
u = h(u, p, a, c, t[n + 15], 16, 530742520),
a = m(a, c = h(c, u, p, a, t[n + 2], 23, -995338651), u, p, t[n], 6, -198630844),
p = m(p, a, c, u, t[n + 7], 10, 1126891415),
u = m(u, p, a, c, t[n + 14], 15, -1416354905),
c = m(c, u, p, a, t[n + 5], 21, -57434055),
a = m(a, c, u, p, t[n + 12], 6, 1700485571),
p = m(p, a, c, u, t[n + 3], 10, -1894986606),
u = m(u, p, a, c, t[n + 10], 15, -1051523),
c = m(c, u, p, a, t[n + 1], 21, -2054922799),
a = m(a, c, u, p, t[n + 8], 6, 1873313359),
p = m(p, a, c, u, t[n + 15], 10, -30611744),
u = m(u, p, a, c, t[n + 6], 15, -1560198380),
c = m(c, u, p, a, t[n + 13], 21, 1309151649),
a = m(a, c, u, p, t[n + 4], 6, -145523070),
p = m(p, a, c, u, t[n + 11], 10, -1120210379),
u = m(u, p, a, c, t[n + 2], 15, 718787259),
c = m(c, u, p, a, t[n + 9], 21, -343485551),
a = l(a, o),
c = l(c, r),
u = l(u, i),
p = l(p, s);
return [a, c, u, p]
}
function u(t) {
var e, n = "";
for (e = 0; e < 32 * t.length; e += 8) n += String.fromCharCode(t[e >> 5] >>> e % 32 & 255);
return n
}
function p(t) {
var e, n = [];
for (n[(t.length >> 2) - 1] = void 0, e = 0; e < n.length; e += 1) n[e] = 0;
for (e = 0; e < 8 * t.length; e += 8) n[e >> 5] |= (255 & t.charCodeAt(e / 8)) << e % 32;
return n
}
function o(t) {
var e, n, o = "0123456789abcdef",
r = "";
for (n = 0; n < t.length; n += 1) e = t.charCodeAt(n),
r += o.charAt(e >>> 4 & 15) + o.charAt(15 & e);
return r
}
function r(t) {
return unescape(encodeURIComponent(t))
}
function i(t) {
return u(c(p(e = r(t)), 8 * e.length));
var e
}
function s(t, e) {
return function(t, e) {var n, o, r = p(t),i = [],s = [];for (i[15] = s[15] = void 0, 16 < r.length && (r = c(r, 8 * t.length)), n = 0; n < 16; n += 1) i[n] = 909522486 ^ r[n],s[n] = 1549556828 ^ r[n];return o = c(i.concat(p(e)), 512 + 8 * e.length),u(c(s.concat(o), 640))
} (r(t), r(e))
}
function getPwd(t, e, n) {
return e ? n ? s(e, t) : o(s(e, t)) : n ? i(t) : o(i(t))
}

爬虫笔记41之反爬系列四:字体反爬、JS反爬相关推荐

  1. Python反反爬系列(四)----前端JS进行AES加密,Python解密

    将6位或者7位数字加密成22位数字字母大小写的加密方法. 采集数据时,遇到对Url进行加密的网站,大致加密情形如下 1.编译加密前的url 在列表页的url如下 2.加密后的Url 除了端口这块没了, ...

  2. js input复选框选中父级同时子级也选中_突破百度JS反爬获取百度文库数据下载...

    毕业,是一首离别的歌 前言 炎炎夏季,又快到了我们该说毕业的时候.都说分开是为了更好的相聚,让我们彼此珍惜! 在这个炎热的空档期,对于技术渴望的宅男腐女们我们该做点什么呢?那最好的方式就是用编程来填补 ...

  3. python爬虫笔记五:汽车之家贴吧信息(字体反爬-动态映射)

    学习网址: https://jia666666.blog.csdn.net/article/details/108974149 ----------------------------------- ...

  4. python网络爬虫系列(八)——常见的反爬手段和解决方法

    常见的反爬手段和解决思路 学习目标 了解 服务器反爬的原因 了解 服务器常反什么样的爬虫 了解 反爬虫领域常见的一些概念 了解 反爬的三个方向 了解 常见基于身份识别进行反爬 了解 常见基于爬虫行为进 ...

  5. CSDN爬虫(四)——博客专家(所有)爬取+数据分析

    CSDN爬虫(四)--博客专家(所有)爬取+数据分析 说明 开发环境:jdk1.7+myeclipse10.7+win74bit+mysql5.5+webmagic0.5.2+jsoup1.7.2 爬 ...

  6. 【反编译系列】四、反编译so文件(IDA_Pro)

    概述 安卓应用程序的开发语言是java,但是由于java层的代码很容易被反编译,而反编译c/c++程序的难度比较大,所以现在很多安卓应用程序的核心部分都使用NDK进行开发.使用NDK开发能够编译c/c ...

  7. 爬虫笔记——东方财富科创板数据爬取(requests方法)

    爬虫笔记--东方财富科创板数据爬取(requests方法) 网页观察 网页源代码分析 具体代码 上篇文章:爬虫笔记--东方财富科创板数据爬取(selenium方法)介绍了selenium爬取东方财富科 ...

  8. 爬虫笔记——东方财富科创板数据爬取(selenium方法)

    爬虫笔记--东方财富科创板数据爬取(selenium方法) 网站观察 网站分析 公司详情页面 具体代码 selenium方式爬取 优点:无需观察网站去查找数据来源 缺点:速度较requests方法更慢 ...

  9. Python爬虫笔记(3)- 爬取丁香园留言

    Python爬虫笔记(3)- 爬取丁香园留言 爬取丁香园留言:主要用到了模拟登录 爬取丁香园留言:主要用到了模拟登录 import requests, json, re, random,time fr ...

最新文章

  1. Navicat 12连接PostgreSQL11.3数据库服务器
  2. 设计模式-Decorator模式
  3. eclipse+adt下开发android微信红包自动抢(AccessibilityService类)
  4. mint ui datetimepicker 手机端jquery datetimepicker 总结应用
  5. GDCM:gdcm::PDBHeader的测试程序
  6. 纪中C组模拟赛总结(2019.7.9)
  7. MySQL 面试题汇总
  8. Ajax get请求示例
  9. Nginx (Install)
  10. WPF中作用MEF报错The export Xyz is not assignable to type IXyz是设计器问题
  11. HTML基础学习(二)—CSS
  12. 恒生电子offer含金量_收获8个Offer,来给大家分享备战和面试经验
  13. 【更新】VMware虚拟机黑群晖7.1.1 RC(懒人包)
  14. 使用Clip Converter网站下载Yotube视频
  15. 模块Datetime
  16. VirtualBox Guest Additions
  17. CreateProcess的用法
  18. PWA (Progressive Web App)
  19. 极验验证--滑块验证
  20. Javascript - 实现Javascript控制ScrollBar(滚动条) - 学习/实践

热门文章

  1. E1. Divisible Numbers (easy version)(数学)
  2. 解决FFMPEG错误:height not divisible by 2 / width not divisible by 2
  3. MySQL数据库面试题(超详细)
  4. LeetCode 37. 解数独 Sudoku Solver
  5. python实现微信hook_GitHub - zhouxionger/wechathook: 借助微信hook,拦截修改某些call,填充进我们的Python代码,进行微信公众号文章的爬取...
  6. ipa 安装包不用市场如果扫码下载安装 免费IOS安装API
  7. 服务器要删除文件访问被拒绝,删除文件提示:文件夹访问被拒绝 需要来自administrator权限执行操作...
  8. X64dbg-插件开发-字符编码-常用插件函数-回调结构
  9. 关于ORACLE (AMERICAN_AMERICA.US7ASCII)字符集
  10. 【javaScript】原生实现窗口拖动效果