推荐文章:Python3爬取今日头条文章视频数据
优采云 发布时间: 2022-10-24 16:16推荐文章:Python3爬取今日头条文章视频数据
前言
任何爬虫工程师都会在爬取网站数据之前分析网站并进行逆向(js)破解(加密),所以我们在爬取文章和今日头条的视频数据之前,也需要分析今日头条的反爬机制和反向(js)破解(加密)。
QQ群聊
855262907
最新版本的
Python3爬取今日头条文章视频数据,完美解决as、cp、_signature的加密方式(2020-6-29版本)
Python3爬取今日头条文章视频数据,完美解决_signature的加密方式(2020-10-16版)
分析今日头条
今日头条用户链接:#mid=3413306633
我们将对今天的头条链接进行详细分析。以下是分析步骤:
1.分析网站信息是否为静态数据
按F12弹出开发者界面,选择Network区域,你会发现有很多请求链接,将鼠标移到最上方,然后看到一个与网站同URL的链接,点击。
从这里看,今日头条网站的数据并不是静态数据,所以我们需要进行下一个分析。
2.分析网站信息是否是AJAX请求的
AJAX请求是网站通过js脚本发起的请求连接。目的是在不刷新网页的情况下实时更新网页的内容,让你感觉跟网页的源代码是拼接的。
让我们从许多链接中过滤。由于AJAX的类型是XHR,我们可以在开发者模式下选择XHR,可以看到只剩下几个链接,然后从这些链接中找出相关链接。网站一个与内容完美匹配的链接就足够了。
这样网站的内容主要是通过AJAX请求的数据来展示的。
3.分析请求链接
知道了这个链接之后,我们就会去请求这个链接,从而在里面得到我们想要的数据,这样我们就可以拿到数据了。
我们来看看开发者工具中 Network 区域的 Headers 区域。两次刷新网页后,你会发现两个请求中的参数发生了变化,Request Headers的参数也发生了变化。见图。
第一个请求:
第二个请求:
赖载要求:
解释(百度百科):在Web应用中,系统的瓶颈往往是系统的响应速度。如果系统响应速度太慢,用户就会抱怨,系统的价值也会大打折扣。因此,提高系统响应速度非常重要。
Web 应用程序所做的最多的就是与后端数据库交互,而查询数据库是一个耗时的过程。当数据库中的记录太多时,查询优化就显得尤为重要。为了解决这个问题,有人提出了缓存的概念。缓存是将用户经常使用的数据存储在内存中,以便快速访问。用户执行查询操作后,查询记录将被放入缓存中。当用户再次查询时,系统会先从缓存中读取,如果没有缓存再查询数据库。缓存技术在一定程度上提高了系统性能,但是当数据量过大时,缓存就不适合了。因为内存容量是有限的,在内存中放太多数据会影响电脑的性能。另一种技术,
从上图中,我们可以看到链接的参数和请求头的参数都发生了变化。
改变参数的效果:
参数角色加密
page_type
获取的数据类型是文章还是video,video为0,文章为1
不
用户身份
获取该用户的数据,获取用户链接中的user_id:3410443345/#mid=3413306633
不
max_behot_time
不断获取用户数据进行加载,第一个值默认为0,后面的值为最后返回数据中max_behot_time的值
不
数数
一次返回的最大数据量,默认值为20
不
作为
每个请求的链接是否是最近的时间
是的
cp
和上面一样
是的
_签名
用于判断user_id和max_behot_time的值是否等于links和headers的参数值
是的
Request Headers中cookies需要注意的参数(解决方法:手动获取这些参数的值):
参数动作变化加密
tt_webid
未知
根据我的观察,它每天变化一次
是的
WEATHER_CITY
旗城
不变
是(网址代码)
tt_webid
未知
和上面的 tt_webid 一样
是的
csrftoken
对于 csrf
同上
是的
这样整个网站就分析完了,下面开始实战。
抓取今日头条
知道了这些加密参数后,开始破解加密参数
1.破解as和cp
首先,我们已经知道每个访问参数都在变化,所以我们需要找出这些参数的加密代码,也就是js代码。
在js文件中搜索带有as或cp或_signature字符的文件,然后分析代码是如何组成的。
搜索方法:
进入后按Ctrl+F再次搜索_signature,可以看到参数的加密方式。
这样你就可以找到这串加密的代码。
function n() {
var e, i = ascp.getHoney(), t = "";
return window.TAC && (t = TAC.sign(userInfo.id + "" + d.params.max_behot_time)),
e = _.extend({}, d.params, {
as: i.as,
cp: i.cp,
_signature: t
})
}
其中i.as和i.cp分别对应as和cp,而i是由代码ascp.getHoney()返回的,所以我们继续找ascp.getHoney,继续寻找getHoney函数。
i.getHoney = function() {
var e = Math.floor((new Date).getTime() / 1e3)
, i = e.toString(16).toUpperCase()
, t = md5(e).toString().toUpperCase();
if (8 != i.length)
return {
as: "479BB4B7254C150",
cp: "7E0AC8874BB0985"
};
for (var o = t.slice(0, 5), n = t.slice(-5), a = "", s = 0; 5 > s; s++)
a += o[s] + i[s];
for (var r = "", l = 0; 5 > l; l++)
r += i[l + 3] + n[l];
return {
as: "A1" + a + i.slice(-3),
cp: i.slice(0, 3) + r + "E1"
}
}
根据这串JS代码,转换成Python代码,得到as和cp的值。Python代码如下:
import math,time,hashlib
def getHoney():
e = math.floor(int(str(time.time() * 1000).split('.')[0]) / 1e3) #获取13位毫秒数然后除于1e3再向下取整
i = str('%X' % e) #转换e为16进制
m5 = hashlib.md5()
m5.update(str(e).encode('utf-8'))
t = str(m5.hexdigest()).upper() #进行md5加密
if 8 != len(i):
return {'as':'479BB4B7254C150','cp':'7E0AC8874BB0985'}
o = t[0:5]
n = t[-5:]
a = ""
r = ""
for x in range(5): #交换字符串
a += o[x] + i[x]
r += i[x + 3] + n[x]
return {'as':"A1" + a + i[-3:],'cp':i[0:3] + r + "E1"}
if __name__ == '__main__':
print(getHoney())
2.破解_signature
根据上面破解as和cp时的截图,我们可以看到生成_signature的值为t,生成t的方法是TAC.sign(userInfo.id + "" + d.params.max_behot_time),所以我们必须搜索 TAC .sign() 方法。
搜索完成后发现是用混淆加密的方式实现的一大串TAC。看代码破解要花很多时间,所以为了方便,我直接用execjs直接执行这串代码。
js源代码:
<p>Function(function(e) {
return 'e(e,a,r){(b[e]||(b[e]=t("x,y","x "+e+" y")(r,a)}a(e,a,r){(k[r]||(k[r]=t("x,y","new x[y]("+Array(r+1).join(",x[y]")(1)+")")(e,a)}r(e,a,r){n,t,s={},b=s.d=r?r.d+1:0;for(s["$"+b]=s,t=0;ts!0s%yA0s"l"l!r&lengthb>b|s!o!l q"10o!],l!& s/yIo!o!].q"13o!],o!]*Jd>>b|&o!]+l &+ s0l-l!&l-l!i\'1z141z4b/@d&l!l Bd>&+l!l &+l!l 6d>&+l!l &+ s,y=o!o!]/q"13o!l q"10o!],l 2d>& s.{s-yMo!o!]0q"13o!]*Ld>>b|s!o!l q"10o!],l!& s/yIo!o!].q"13o!],o!]*Jd>>b|&o!]+l &+ s0l-l!&l-l!i\'1z141z4b/@d&l!l Bd>&+l!l &+l!l 6d>&+l!l &+ s,y=o!o!]/q"13o!l q"10o!],l 2d>& s.{s-yMo!o!]0q"13o!]*Ld>>b|s!o!l q"10o!],l!& s/yIo!o!].q"13o!],o!]*Jd>>b|&o!]+l &+ s0l-l!&l-l!i\'1z141z4b/@d