打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
第一个参数:min_behot_time

以下为今日第一个参数的头 条代          码

'refresh' === t ? (i = this.list.length > 0 ? this.list[0].behot_time : 0, this.url += 'min_behot_time=' + i) : (i = this.list.length > 0 ? this.list[this.list.length - 1].behot_time : 0, this.url += 'max_behot_time=' + i);

代码整理后逻辑如下

// t = 'refresh'; // 刷新页面时载第一页 t的值// t = 'loadmore'; // 下拉加载下一页 t 的值// this.list = [] // 刷新页面时载第一页 this.list 的值// this.list = [{...},{...},...] // 下拉加载下一页 this.list 的值,里面有16 个元素var i = 0;if (t == 'refresh') {    // this.list = [];    if (this.list.length > 0) {        i = this.list[0].behot_time    } else {        i = 0,this.url += 'min_behot_time=' + i        // this.url = /api/pc/feed/?min_behot_time=0    }}if (t == 'loadmore') {    if (this.list.length > 0) {        // this.list.length = 16        i = this.list[this.list.length - 1].behot_time;        // /api/pc/feed/?max_behot_time=1548149528    } else {        i = 0,this.url += 'max_behot_time=' + i;    }}

逻辑看起来是取返回的数据中,behot_time 字段的值。 this.list 为所有的新闻数据数组,每加载一页就会往这个数组中push.
所以,加载第一页,min_behot_time=0 ; 加载下一页,max_behot_time = this.list[this.list.length - 1].behot_time; 返回数据中的最后一条,behot_time 的值。

先前猜测这个值是直接取的时间戳,调试验证后才知道真相,实践出真理。

第二个参数:category: all

看这个单词很好猜测,分类的意思,加载下一页时没有变动,所以不用修改,可直接使用。

第三个参数:utm_source: toutiao

看起来像来源,toutiao(头条)? 加载下一页时没有变动,所以不用修改,可直接使用。

第四个参数:widen: 1

加载下一页时没有变动,所以不用修改,可直接使用。

第五个参数:tadrequire: false

在调试期间,有时候为false, 有时候为true. 影响不是很大,先不做处理,直接用true 或者false.

第六、七个参数 as、cp

这个比较特殊

as: A1057CA4A68E6CC
cp: 5C469E465C4CAE1

可以将js直接提取出来,然后运行就能获取到。

今日头条as,cp 获取测试代码

第八个参数:_signature:

这个参数看起来有点故事。调试看看。

var n = (0, g.sign)(i + '');(0, a.default)(this.params, { as: e.as, cp: e.cp, _signature: n})

由上代码可以看出_signature: n; 而 n 是 使用 i 处理后生成的。g.sign 做了什么生出了 n ???

_signature:

经过调试到这..... _signature的值就来自这些字符串,没有思路了,打算采用其他方式爬虫。并考虑到这些字符串可能来自后端生成,然后在进行加密的,如果今日头条不断的进行更新,就会导致今天也许爬虫成功了,过一段时间就不行了。搜索了下,发现有很多这种情况。

Function(function(t) {        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;t<b;t�)s[n='$'+t]=r[n];for(t=0,b=s�=a�;t<b;t�)s[t]=a[t];�c(e,0,s)}�c(t,b,k){�u(e){v[x�]=e}�f�{�g=�,t�ing(b�g)}�l�{try{y=c(t,b,k)}catch(e){h=e,y=l}}for(�h,y,d,g,v=[],x=0;;)switch(g=�){case 1:u(!�)�4:�f��5:u(�(e){�a=0,r=e�;���{�c=a<r;�c&&u(e[a�]),c}}(���6:y=�,u(�(y��8:if(g=�,l��g,g=�,y===c)b+=g;else if(y!==l)�y�9:�c�10:u(s(���11:y=�,u(�+y)�12:for(y=f�,d=[],g=0;g<y�;g�)d[g]=y.charCodeAt(g)^g+y�;u(String.fromCharCode.apply(null,d��13:y=�,h=delete �[y]�14:���59:u((g=�)?(y=x,v.slice(x-=g,y�:[])�61:u(�[�])�62:g=�,k[0]=65599*k[0]+k[1].charCodeAt(g)>>>0�65:h=�,y=�,�[y]=h�66:u(e(t[b�],�,���67:y=�,d=�,u((g=�).x===c?r(g.y,y,k):g.apply(d,y��68:u(e((g=t[b�])<'<'?(b--,f�):g+g,�,���70:u(!1)�71:�n�72:�+f��73:u(parseInt(f�,36��75:if(�){b��case 74:g=�<<16>>16�g�76:u(k[�])�77:y=�,u(�[y])�78:g=�,u(a(v,x-=g+1,g��79:g=�,u(k['$'+g])�81:h=�,�[f�]=h�82:u(�[f�])�83:h=�,k[�]=h�84:�!0�85:�void 0�86:u(v[x-1])�88:h=�,y=�,�h,�y�89:u(��{�e�{�r(e.y,arguments,k)}�e.y=f�,e.x=c,e}�)�90:�null�91:�h�93:h=��0:��;default:u((g<<16>>16)-16)}}�n=this,t=n.Function,s=Object.keys||�(e){�a={},r=0;for(�c in e)a[r�]=c;�a�=r,a},b={},k={};�r'.replace(/[�-�]/g, function(e) {            return t[15 & e.charCodeAt(0)]        })    }('v[x++]=�v[--x]�t.charCodeAt(b++)-32�function �return �))�++�.substr�var �.length�()�,b+=�;break;case �;break}'.split('�')))()('gr$Daten Иb/s!l y͒yĹg,(lfi~ah`{mv,-n|jqewVxp{rvmmx,&eff�kx[!cs'l'.Pq%widthl'@q&heightl'vr*getContextx$'2d[!cs#l#,*;?|u.|uc{uq$fontl#vr(fillTextx$$龘ฑภ경2<[#c}l#2q*shadowBlurl#1q-shadowOffsetXl#$$limeq+shadowColorl#vr#arcx88802[%c}l#vr&strokex[ c}l'v,)}eOmyoZB]mx[ cs!0s$l$Pb<k7l l!r&lengthb%^l$1+s$j�l  s#i$1ek1s$gr#tack4)zgr#tac$! +0o![#cj?o ]!l$b%s'o ]!l'l$b*b^0d#>>>s!0s%yA0s'l'l!r&lengthb<k+l'^l'1+s'j�l  s&l&z0l!$ +['cs\'(0l#i\'1ps9wxb&s() &{s)/s(gr&Stringr,fromCharCodes)0s*yWl ._b&s o!])l l Jb<k$.aj;l .Tb<k$.gj/l .^b<k&i'-4j!�+& s+yPo!]+s!l!l Hd>&l!l Bd>&+l!l <d>&+l!l 6d>&+l!l &+ s,y=o!o!]/q'13o!l q'10o!],l 2d>& s.{s-yMo!o!]0q'13o!]*Ld<l 4d#>>>b|s!o!l q'10o!],l!& s/yIo!o!].q'13o!],o!]*Jd<l 6d#>>>b|&o!]+l &+ s0l-l!&l-l!i\'1z141z4b/@d<l'b|&+l-l(l!b^&+l-l&zl\'g,)gk}ejo{�cm,)|yn~Lij~em['cl$b%@d<l&zl\'l $ +['cl$b%b|&+l-l%8d<@b|l!b^&+ q$sign ', [Object.defineProperty(e, '__esModule', {        value: !0    })])

最终解决方案

使用 puppeteer 进行爬虫,高级解决方案,可爬取任何网站,不管这个网站如何加密,只要能访问这个网站,就能爬取。

直接上代码: 爬取今日头条首页新闻,滚动加载5 页数据,并将数据转为json,写入到json文件。

const puppeteer = require('puppeteer');const fs = require('fs');let news = [];(async() => { var pageN = 1; var sleep = function(time) { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(); }, time); }) }; const browser = await puppeteer.launch(); // const browser = await browser1.createIncognitoBrowserContext(); const page = await browser.newPage(); page.on('response', res => { let mathStr = res._url.indexOf('www.toutiao.com/api/pc/feed/'); if (mathStr > -1) { console.log(res._url); res.json().then(json => { let data = json.data; data.forEach(v => { news.push(v); }) }) } }) await page.goto('https://www.toutiao.com/'); console.log('document loaded success'); await sleep(3000); await page.evaluate(_ => { window.scrollBy(0, document.body.scrollHeight); }); console.log('1 one page loaded success' + new Date()); await sleep(3000); await page.evaluate(_ => { window.scrollBy(0, document.body.scrollHeight); }); console.log('2 one page loaded success' + new Date()); await sleep(3000); await page.evaluate(_ => { window.scrollBy(0, document.body.scrollHeight); }); console.log('3 one page loaded success' + new Date()); await sleep(3000); await page.evaluate(_ => { window.scrollBy(0, document.body.scrollHeight); }); console.log('4 one page loaded success' + new Date()); await sleep(3000); await page.evaluate(_ => { window.scrollBy(0, document.body.scrollHeight); }); console.log('5 one page loaded success' + new Date()); await sleep(3000); let fileDate = new Date(); let fileName = 'news'+fileDate.getFullYear()+fileDate.getDate(); objToJsonFile(news, fileName); await browser.close(); console.log(' browser close success');})();function objToJsonFile(obj, fileName) { fs.open(__dirname + '/' + fileName + '.json', 'w', (err, fd) => { if (err) { throw err; } let jsonStr = JSON.stringify(obj); fs.write(fd, jsonStr, (err, written) => { if (err) { throw err; } }) fs.close(fd); });}

总结

闲话:这次的爬虫,陆陆续续的调试了很多次,也花了很多时间,都是在业余时间进行开发和调试,时间断断续续就会导致思路也是断断续续的,有时候来刚来了点灵感,但又需要去做其他事。但不断的尝试,尝试,还是算给出了解决方案,虽然不是很完美,但只要坚持下去,总会有结果,嗯嗯。

1 这次的爬虫中,有尝试使用 crawlerpuppeteer
crawler 优点:轻量级,速度快。
crawler 缺点:一次只对单个链接进行爬取,无法模拟浏览器操作。
puppeteer 优点:可模拟浏览器操作,可以爬取单页应用,可直接运行浏览器中js代码,只要浏览器可以的操作,使用puppeteer 都可以进行模拟。
puppeteer 缺点:太笨重,每一次运行都需要加载一次chrome 内核,速度慢,内存占用高。

2 这次爬虫的目的是想实现一个私人定制的今日头条,而不是今日头条按照个人兴趣进行AI推荐的内容。(有段时间有类似上瘾的感觉,每次今日头条都很能抓住我的兴趣,导致每天都会花很多时间去刷今日头条,但这样真的好吗,这样是否会导致每个人的兴趣都固定在同一个圈内,而我要的是各个行业的新闻,兴趣应该是广泛的,我想看的是大家的想法、也许我就是乌合之众吧!!!个人的想法)
这次有尝试爬取当天的新闻,也成功爬取了一天中的新闻,并进行了分析,按照之前的想法去构建一个私人定制的今日头条。但按照思路进行了处理,处理后发现结果并不是想象中结果。
爬取了14页左右的今日头条,并按照个人想法进行过滤(按照评论数进行排序,按照关键词标签排除了娱乐新闻、美食、汽车、视频、家居、美文、育儿、健康,这些都不是我想关注。)。

3 处理后发现结果并不是想象中结果,原因大概是,点击爬取中各条新闻就会发现,今日头条首页中的新闻并不都是按照最新的时间进行排序的,有些还是好几天前的新闻。也就是说首页中展示的新闻,都是由小编推荐的新闻, 而我想看的只是今天或者昨天的新闻,目的是每天都只关注最近的新闻,并达到如果每天都看新闻的话,你会不漏掉所有的新闻,所有的热点,且不会看到重复的新闻。

4 考虑解决方案,这样爬虫下来,并不能达到我想要的目标和结果。
如果考虑只想关注特定的新闻,例如国内政治新闻,最好还是去爬取人民网什么的,还没去了解,搜索下政治新闻排行网站什么就能得到排行。按照这个思路去爬虫,数据会更接近想要的结果,更纯粹。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Node:使用Puppeteer完成一次复杂的爬虫
爬虫利器 Puppeteer 实战
利用 Lighthouse 與 Puppeteer 對全站網頁做效能檢測並產生報表 | Summer。桑莫。夏天
前端开发爬虫首选puppeteer
puppeteer(headless chrome)实现网站登录
爬取某位大佬简书上所有文章并保存为pdf
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服