我寫了個 Chrome 插件,一鍵下載 Pornhub 視頻!

點擊藍色 「小鹿動畫學編程」 關注我哦!
前端

加個 「星標」 ,天天一篇動畫餵飽你!web

做者 |  小詹
面試

來源 |  小詹學 Pythonchrome


插件獲取和使用見文末,請先欣賞技術流。

小詹有個讀者叫zgao,他以前寫過一篇博客,爬取了 Pornhub(下面所有簡稱P站)上的視頻,代碼很簡單,關鍵還好用!當時小詹就 P 站上爬取了一些考研數學視頻,雖然我用不上,可是我熱愛技術啊!
編程


技術分析

之因此有今天這篇文章呢,是由於zgao(下文中的我都爲讀者zgao)發現 P 站修改了前端的代碼,將視頻的接口信息所有隱藏起來了,不像之前那樣能直接在網頁源碼中找到視頻連接。因而我根據最新的 P 站狀況寫了一個插件,可以一鍵下載學習視頻。


如下是從分析到寫插件的全過程。首先能夠來對比下修改先後的 P 站:


這是之前的 P 站。


這是如今的 P 站。


這兩段都是 JS 代碼,可是之前的一看就很清晰明瞭,而如今的有一大堆的垃圾註釋在裏面。不用說,確定是作了 JS 混淆。瀏覽器


由於代碼是被壓縮過的,因此在 chrome 開發者工具裏直接代碼格式化。


在 network 面板中將代碼格式化以後能夠看的很清楚,看上面定義的那一堆變量感受就是咱們要的 url,而下面就是將變量拼接的最後的視頻連接。微信


我在想 P 站的程序猿不會真的這麼傻吧,難道就這樣拼接一堆字符串??因此我就去前面找到定義的那個變量。


而後在控制檯輸出這個變量的值。


我整我的都傻了,P 站的程序猿這麼直接的嗎?那還混淆個**的代碼?閉包


之前寫個 P 站的爬蟲還得每一個 URL 正則匹配才能提取出來。如今更省事了,都不用爬了,直接把這個變量的值取出來就什麼信息都有了。app


我嚴重懷疑P站的前端程序猿是否是寫代碼的時候看片去了!ide


因此接下來要想提取出視頻的url就很容易了,直接用ExecJS這個庫來執行這段被混淆過的JS代碼就ok了。


可是想了想這樣也太簡單了吧,沒什麼意思。要不我寫一個Chrome的插件來完成這件事?由於自己視頻加載以前JS確定會執行。那麼用插件的方式也更加方便。插件開發的過程,最關鍵的問題就是如何將包含全部視頻接口信息的變量給提取出來。


一開始我是想到是直接在瀏覽器的全局變量window中拿到那個變量,這是最簡單的辦法。我發現經過注入JS代碼用console.log(window)輸出的全局變量中仍是沒有包含flashvars_*****這個變量,不清楚爲何。我一開始認爲多是頁面onload的時候尚未執行JS因此沒有變量信息。後面我想了想要不執行settimeout來實現延遲執行代碼,可是仍是不行。

 

因而我決定用另一個辦法,將字符串做爲代碼執行。也就是寫木馬最經常使用到的eval函數。在頁面加載時,經過xpath獲得混淆JS代碼的位置,將它做爲一段字符串當成代碼執行,這樣一樣拿到了接口信息。


給你們看一下插件最核心的兩段代碼content-script.js,也就是注入頁面的JS代碼。(代碼可左右拖動)


   

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 = 0len = 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
});


   

popup.js的做用主要就是和content-script.js通訊,相互傳值。而後在插件中渲染生成頁面,JS間傳值主要用到了Chrome的API。插件開發的過程當中還涉及到不少細節問題,好比ico的製做,這些就不提了。


關於插件

看到這的小夥伴,其實真正吸引你的是這最後的插件吧?


插件寫完,我順便上傳到了Google商店裏,畢竟是本身寫的第一個Chrome插件,仍是蠻激動的。感興趣的小夥伴可使用試試。


插件使用方式:

  • 安裝插件 (下文有插件壓縮包)

  • 打開 P 站,打開你要下載的視頻網頁


  • 點擊菜單欄的 PH 插件便可選擇清晰度進行下載( 以下圖文)


插件壓縮包:

Pornhub視頻下載插件已經打包好(由於某些緣由,若是不能從谷歌商店安裝的話,能夠直接解壓導入。)


關注公衆號「 小詹學Python 」,回覆關鍵詞「 P站插件 」便可獲取這款神奇的插件~


一、本身不付出努力的話,就別期望別人幫你了!

二、動畫:什麼是閉包?

三、動畫:如何給面試官回答 TCP 的擁塞控制?

四、圖解:什麼是 JS 原型和原型鏈?


「小鹿動畫學編程」用動畫的形式和你分享技術!

長按識別二維碼關注

在看和轉發

都會帶來月末中獎的可能

本文分享自微信公衆號 - 小鹿動畫學編程(IT_Animation)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索