目标:爬取今日头条头条号王者荣耀资讯和视频。
爬虫关键点:1.分析单页面获取所需要的内容,2.找到文章列表页翻页规律,3.解析加密信息,获取所需要的内容
(1)通过搜索接口获取今日头条王者荣耀资讯
最初策略是通过今日头条首页搜索框搜索关键字“今日头条”,获取搜索列表。经过分析fillder 抓包可以得到今日头条搜索接口是https://www.toutiao.com/search/?keyword= 最后接上关键字既可以搜索得到想要的内容,但实际上获取文章列表真正链接的请求是:
“https://www.toutiao.com/search_content/?offset=0&format=json&keyword=王者荣耀&autoload=true&count=20&cur_tab=1&from=search_tab&pd=synthesis“
去掉其他信息之后,最终获取的有效的url是:
https://www.toutiao.com/search_content/?offset=0&format=json&keyword=王者荣耀&count=20
现在就很简单了,可以看到offset是翻页,format=json则表示是通过json格式生成传递数据,keyword则表示搜索的关键字,count 则表示一次传输获取到的数据。
第二步就是文章列表中,每一个关键的json数据样式,现在我们通过链接可以看到我们获取到的数据央视是这样的:
看起来很繁杂,仔细分析之后,可以看到,实际上是有规律可以遵循的,重点关注的是json格式数据里面的data的value值,里面是真正的文章信息列表。现在分析清楚之后,可以放下,再进行单页面的分析请求。
经过分析可以得到,今日头条单页面url链接是:
“https://www.toutiao.com/a6645464825897943555/“
很明显,最后的那一串数字是关键,那么,这一串数字是从哪里获取的呢,现在就要回头看前面的请求列表了,我们拿着“6645464825897943555“这串数字,在前面的
文章列表进行搜索,轻易的发现,展示这串数字的key值就是data里面的“group_id”虽然有点惊讶,但是最终还是拿到了。
现在我们通过搜索获取文章列表,跳转,和翻页我们都找到了接口。下面的事情就简单了,获取单页面数据。当我点开网页源代码的时候,发现里面就有我想要的内容。
最后通过xpath或者是正则就可以获取一个单页面文章所需要的内容。
这个页码有很多乱码,经过百度之后,发现其实这些乱码其实就是前端页面标签。经过简单的页面转义,就能保存为正常的前端页面。
然后是视频信息,现在我能够获取视频的video,但是怎么获取视频播放的原始url,是一个很头疼的问题。这里的分析后面再说。
剩下的就是可以写代码了,写好之后爬取,结果爬了一会就没了,总共就爬了245条。因此,就需要转方向,爬取头条号资料。
(2)ip被封,反爬。
可能是之前尝试次数太多了,头条将我的ip封掉。最后通过买了阿布云代理,配置好之后,又能够顺利爬取。
(3)爬取头条号里面的文章和视频内容
进入一个头条号页面:
https://www.toutiao.com/c/user/60018788872/#mid=1566905732637697
这个url可以固定,重点是爬取里面的文章列表和详情页。
现在我们能获取每一个单页面文章或视频的单页面内容,所以爬头条号资讯的时候,只需要解决怎么拉取文章列表和翻页就可以了。
首先是看源代码,里面没有任何我需要的文章内容的信息,所以可以判断是通过其他请求获取到数据的。
经过分析可以得知,获取文章列表链接是:
“https://www.toutiao.com/c/user/article/?page_type=1&user_id=%d&max_behot_time=%d&count=20&as=A185BCF242D2906&cp=5C22825930C6AE1&_signature=“
这些信息每一个都是必须的,user_id和max_behot_time 都是可以通过前面的文章列表获取。最关键的点是as,cp,_signature这三个值是怎么获取的,暂时没有找到出处。
一开始,因为不懂前端代码,没想过js会对这里产生影响,经过搜索之后,决定采用模拟浏览器的方式进行操作,即使用selenium库进行操作。通过模拟浏览器发送请求的方式,网页源代码经过模拟浏览器渲染,可以获取到标准的前端展示代码页面,也就可以直接获取到,同时通过模拟浏览器下拉菜单操作方式,获取更多的资讯。但是通过这个方式操作之后,发现有几个弊端:
[if !supportLists](1) [endif]下拉请求时经常无法更新页面,并不是每次请求必有回应。
[if !supportLists](2) [endif]需要获取数据的时候,每次都是从第一页开始拉取,翻页就是下拉菜单,但是在这过程中我并不能保存页面,所以无法做到实时存储。
[if !supportLists](3) [endif]爬取速度实在慢的可怜,其他我都忍了,20分钟才获取100多条数据,这种速度实在不能忍。
最后决定放弃这种方式,重新回到找url规律的问题上来。关键点就是as,cp,signature 这三个值怎么获取。通过百度之后,可以知道as,cp这些值,我可以在js中找到对应的函数。
即上图这,可以清楚的看到,里面有一个固定的as,cp函数,最开始,我天然的以为as,cp和signature是有某种函数关系存在的,然后又经过百度,可以找到那段函数。经过百度搜索和查询,最后找到签名函数是js中的:
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","newx[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>>065:h=,y=,[y]=h66:u(e(t[b],,67:y=,d=,u((g=).x===c?r(g.y,y,k):g.apply(d,y68:u(e((g=t[b])<"<"?(b--,f):g+g,,70:u(!1)71:n72:+f73:u(parseInt(f,3675:if(){bcase74:g=<<16>>16g76:u(k[])77:y=,u([y])78:g=,u(a(v,x-=g+1,g79:g=,u(k["$"+g])81:h=,[f]=h82:u([f])83:h=,k[]=h84:!085:void086:u(v[x-1])88:h=,y=,h,y89:u({e{r(e.y,arguments,k)}e.y=f,e.x=c,e})90:null91:h93:h=0:;default:u((g<<16>>16)-16)}}n=this,t=n.Function,s=Object.keys||(e){a={},r=0;for(cin e)a[r]=c;a=r,a},b={},k={};r'.replace(/[-]/g, function(i) {
return e[15 &i.charCodeAt(0)]
})
}("v[x++]=v[--x]t.charCodeAt(b++)-32function return
))++.substrvar .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>>s!0s%yA0s"l"l!r&lengthb&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
上面这一坨,到这里,我就绝望了,这鬼才看得懂。
询问领导之后,测试才发现,这个函数值跟as,cp没有半毛钱关系,跟user_id,和max_hot_time 有关系。但是怎么运行成了问题。
在这个地方卡了一天半之后,求助领导,领导在发现完全一样请求之后,依然解决不了问题。最后决定,将这部分代码拷贝下来,然后通过node.js在本地调用运行。最后获得正确的signture值。
至此,今日头条最难处理的部分就解决了。
在测试中还发现,在翻页的时候(翻页是使用json数据中,max_hot_time值进行翻页),失败率非常高,一个翻页需要请求多次。最后成功拿到文章列表。
最后一个要解决的问题就是,怎么通过video_id获取视频原始链接。经过百度,最终找到一个有效的解密方案(如果没有这个,我这辈子就解不开。)。即:
1.打开http://toutiao.com/a6309254755004875010/,查看网页源代码获取videoid = 0425d8f0c2bb425d9361c0eb2eeb4f16
2.拼接成如下字符串/video/urls/v/1/toutiao/mp4/{videoid}?r={randint}。其中
3. 将第二步拼接的字符串进行crc32校验(php有crc32函数),获取值为十六进制需转化成十进制crc32("/video/urls/v/1/toutiao/mp4/0425d8f0c2bb425d9361c0eb2eeb4f16?r=7937864853677161")= 4040162423
4.
拼接Urlhttp://i.snssdk.com/video/urls/v/1/toutiao/mp4/{videoid}?r={randint}&s={checksum}
5. 访问拼接Urlhttp://i.snssdk.com/video/urls/v/1/toutiao/mp4/0425d8f0c2bb425d9361c0eb2eeb4f16?r=2330415823304158&s=4218775840其中main_url为视频地址(需要base64解码)。
至此今日头条所有内容都可以爬取到了。
总结今日头条反爬策略:
[if !supportLists]1. [endif]封ip,这是最常见的,最后买个代理,省事省心。
[if !supportLists]2. [endif]网页文章链接(关键内容),通过另外的url请求获取,同时进行加密处理(as,cp,signture)
[if !supportLists]3. [endif]对网页js函数进行了加密处理,鬼才看得懂
[if !supportLists]4. [endif]视频通过videoid获取网页播放链接,经过三次加密处理才能获取最终url
[if !supportLists]5. [endif]翻页请求高失败率,显著降低了爬虫获取信息的速度。
总结爬虫策略:
[if !supportLists]1. [endif]首先找信息列表和下拉方式的url规律,分析获取单页面信息的规律,有了三个点,所有爬虫都可以爬了
[if !supportLists]2. [endif]如果是大网站,多百度多github,网友可以提供非常多的好的思路。
[if !supportLists]3. [endif]读懂前端代码很重要。
网友评论