我写了个 Chrome 插件,一键下载 Pornhub 视频! | 您所在的位置:网站首页 › 浏览器的视频可以下载吗 › 我写了个 Chrome 插件,一键下载 Pornhub 视频! |
小詹有个读者叫zgao,他之前写过一篇博客,爬取了 Pornhub(下面全部简称P站)上的视频,代码很简单,关键还好用!当时小詹就 P 站上爬取了一些考研数学视频,虽然我用不上,但是我热爱技术啊! ![]() 这是以前的 P 站。 ![]() 这是现在的 P 站。 ![]() 这两段都是 JS 代码,但是以前的一看就很清晰明了,而现在的有一大堆的垃圾注释在里面。不用说,肯定是做了 JS 混淆。 因为代码是被压缩过的,所以在 chrome 开发者工具里直接代码格式化。 ![]() 在 network 面板中将代码格式化之后可以看的很清楚,看上面定义的那一堆变量感觉就是我们要的 url,而下面就是将变量拼接的最后的视频链接。 我在想 P 站的程序猿不会真的这么傻吧,难道就这样拼接一堆字符串??所以我就去前面找到定义的那个变量。 ![]() 然后在控制台输出这个变量的值。 ![]() 我整个人都傻了,P 站的程序猿这么直接的吗?那还混淆个**的代码? 以前写个 P 站的爬虫还得每个 URL 正则匹配才能提取出来。现在更省事了,都不用爬了,直接把这个变量的值取出来就什么信息都有了。 我严重怀疑P站的前端程序猿是不是写代码的时候看片去了! 所以接下来要想提取出视频的url就很容易了,直接用ExecJS这个库来执行这段被混淆过的JS代码就ok了。 但是想了想这样也太简单了吧,没什么意思。要不我写一个Chrome的插件来完成这件事?因为本身视频加载之前JS肯定会执行。那么用插件的方式也更加方便。插件开发的过程,最关键的问题就是如何将包含所有视频接口信息的变量给提取出来。 一开始我是想到是直接在浏览器的全局变量window中拿到那个变量,这是最简单的办法。我发现通过注入JS代码用console.log(window)输出的全局变量中还是没有包含flashvars_*****这个变量,不清楚为什么。我一开始认为可能是页面onload的时候还没有执行JS所以没有变量信息。后面我想了想要不执行settimeout来实现延迟执行代码,但是还是不行。 于是我决定用另外一个办法,将字符串作为代码执行。也就是写木马最常用到的eval函数。在页面加载时,通过xpath得到混淆JS代码的位置,将它作为一段字符串当成代码执行,这样同样拿到了接口信息。 给大家看一下插件最核心的两段代码content-script.js,也就是注入页面的JS代码。(代码可左右拖动) 代码语言:javascript复制function Func() { return new Promise((resolve, reject) =; { var a = document.querySelector("#player ;script:nth-child(1)").innerHTML a = a.split('loadScriptUniqueId')[0] var c = a.match("flashvars_[0-9]{1,}")[0] eval(a) var d = eval(c) resolve(d) }) } window.onload = () =; { Func().then(res =; { var videoType = [] Object.keys(res).forEach((item) =; { if (item.startsWith('quality_')) { var obj={ key:item, val:res[item] } videoType.push(obj) } }) for(var i = 0, len = videoType.length; i ; len; i++){ console.log(videoType[i].key,videoType[i].val) } chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){ if(request.cmd == 'test') sendResponse(videoType); }); }) } popup.js function sendMessageToContentScript(message, callback) { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, message, function(response) { if(callback) callback(response); }); }); } sendMessageToContentScript({cmd:'test', value:'test'}, function(videoType) { console.log(videoType); for(var i = 0, len = videoType.length; i ; len; i++){ console.log(videoType[i].key,videoType[i].val) } var boxEl = document.getElementsByTagName('ul')[0] //var videoType = [{ key: 'qeqw', val: 'adasda' }, { key: 'qeqw', val: 'adasda' }, { key: 'qeqw', val: 'adasda' }] var videoStr = '' videoType.forEach(item =; { videoStr += ";li;" + ";label;清晰度:" + ";span;" + item.key + ";/span;" + ";/label;" + ";a href=" + item.val + " target='_blank';下载;/a;" + ";/li;" }); boxEl.innerHTML = videoStr });代码语言:javascript复制popup.js的作用主要就是和content-script.js通信,相互传值。然后在插件中渲染生成页面,JS间传值主要用到了Chrome的API。插件开发的过程中还涉及到很多细节问题,比如ico的制作,这些就不提了。 关于插件看到这的小伙伴,其实真正吸引你的是这最后的插件吧? 插件写完,我顺便上传到了Google商店里,毕竟是自己写的第一个Chrome插件,还是蛮激动的。感兴趣的小伙伴可以使用试试。 ![]() 插件使用方式: 安装插件(下文有插件压缩包)![]() ![]() ![]() |
CopyRight 2018-2019 实验室设备网 版权所有 |