博客搬家系列(六)-爬取今日头条文章
一.前情回顾
博客搬家系列(一)-简介:https://blog.csdn.net/rico_zhou/article/details/83619152
博客搬家系列(二)-爬取CSDN博客:https://blog.csdn.net/rico_zhou/article/details/83619509
博客搬家系列(三)-爬取博客园博客:https://blog.csdn.net/rico_zhou/article/details/83619525
博客搬家系列(四)-爬取简书文章:https://blog.csdn.net/rico_zhou/article/details/83619538
博客搬家系列(五)-爬取开源中国博客:https://blog.csdn.net/rico_zhou/article/details/83619561
博客搬家系列(七)-本地WORD文档转HTML:https://blog.csdn.net/rico_zhou/article/details/83619573
博客搬家系列(八)-总结:https://blog.csdn.net/rico_zhou/article/details/83619599
二.开干(获取文章URL集合)
爬取今日头条的文章算是本系列中比较难的,不像其他如CSDN等网站,基本信息可以直接使用htmlunit就能爬取,但是当用同样的方法爬取今日头条时,则不行,很简单,我们随便找一多文章的博主,如https://www.toutiao.com/c/user/101528687217/ 打开主页,右击查看源码,我们发现源码中并不包含文章列表等信息,说明文章列表是js动态加载的,于是还是老规矩,先审查元素,查看一下都进行了哪些请求再说
发现这个get请求正是我想要的,preview查看一下不难发现这里的数据即是文章列表,但是我却并没有在url中发现跟页数相关的参数,只是滚动会发现另一个请求,而且最后的三个参数as,cp,_signature是不一样的,当max_behot_time=0时,即第一页信息,随便更改这三个参数均能得到正确数据
但是当不等于0的时候,即第2,3...页信息,则后面的三个参数就起了作用,不能随便了,其实想想也知道,这肯定是签名算法,防的就是我们现在的这个行为,哈哈,好吧,先说结果,目前我还没有找到有效的办法,但是可以将过程同大家分享一下,共同学习。
首先,这三个参数的加密算法是什么需要找到,然后才能**,我们分析一下这条url
三.开干(获取文章具体信息)
前面的参数其实不用管如page_type,count,但是user_id和max_behot_time是变化的,user_id是已知的,那么max_behot_time是哪来的呢?
当我们首页信息时max_behot_time是0,下拉时变成了1539352612,这个过程中没有其他的请求发生,那么就是在第一次请求时返回的信息或者通过js计算的数据,首先检查一下首次返回的数据:
发现果然如此,这个参数我们是可以依次获取的,解决,那么as,cp,_signature这三个参数呢?刚刚分析,可能是js计算而来,那我们就把这几个关键字在所有的js文件中搜索一下,找到相关的js代码先
经搜索发现,我们找到了相关的js,即文件index_34154e5.js,将其下载下来分析,我们找到了as,cp这两个参数的算法
分析发现,这两个参数只是根据当前的时间经过md5加密生成的字符串,并没有用到user_id和max_behot_time参数,我们网上百度个md5算法或者引入md5js文件,简单写个html获取这两个参数试试看,
<html>
<head>
<title>页面</title>
</head>
<body>
<p>。</p>
<p>。</p>
</body>
<script>
console.log(getHoney(0,1539352612));
function getHoney(userInfoId,max_behot_time){
var i = Math.floor((new Date).getTime() / 1e3)
, e = i.toString(16).toUpperCase()
, t = md5(i).toString().toUpperCase();
if (8 != e.length)
return {
as: "479BB4B7254C150",
cp: "7E0AC8874BB0985"
};
for (var n = t.slice(0, 5), o = t.slice(-5), s = "", a = 0; 5 > a; a++)
s += n[a] + e[a];
for (var l = "", r = 0; 5 > r; r++)
l += e[r + 3] + o[r];
return {
as: "A1" + s + e.slice(-3),
cp: e.slice(0, 3) + l + "E1"
}
}
function md5(string) {
....
}
</script>
</html>
经测试,这两个参数是可用的,那问题的关键就在于_signature这个参数了,同样搜索文件发现了算法
可以看出_signature这个值是需要参数user_id和max_behot_time作为参数经过方法TAC.sign签名之后获取的,那么现在就有两条路了
第一条路是**这个_signature签名的算法,其实js中都有,我只要改成java实现,或者直接使用java执行js即可
第二条路是使用htmlunit动态的执行js方法TAC.sign()然后得到结果
先尝试第二种貌似比较简单的实现方法