Sleazy Fork is available in English.

【fork&mod】Pornhub 视频一键下载 | pornhub.com

Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率

  1. // ==UserScript==
  2. // @icon https://ci.phncdn.com/www-static/favicon.ico
  3. // @name 【fork&mod】Pornhub 视频一键下载 | pornhub.com
  4. // @namespace https://github.com/ekoooo/tampermonkey_pornhub_video_download
  5. // @version 0.1.3-01
  6. // @description Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
  7. // @author liuwanlin 【mod by heckles】
  8. // @match *://*.pornhub.com/view_video.php?viewkey=*
  9. // @match *://*.pornhubpremium.com/view_video.php?viewkey=*
  10. // @grant unsafeWindow
  11. // @grant GM_setClipboard
  12. // @grant GM_download
  13. // @grant GM_addStyle
  14. // @grant GM_notification
  15. // @require https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js
  16. // ==/UserScript==
  17.  
  18. GM_addStyle(`
  19. .download-urls ul {
  20. padding: 10px;
  21. font-weight: bold;
  22. line-height: 1.5;
  23. }
  24. .download-urls ul li {
  25. display: flex;
  26. align-items: center;
  27. height: 20px;
  28. max-width:400px;
  29. }
  30. .download-url-label {
  31. //width: 100px;
  32. text-align: right;
  33. }
  34. .download-url-copy {
  35. flex: 100;
  36. }
  37. .download-url-input {
  38. flex: 3;
  39. font-size: 12px;
  40. padding: 0 5px;
  41. border: 1px solid #ffff;
  42. margin: 0 5px;
  43. }
  44. `);
  45.  
  46. (function () {
  47. 'use strict';
  48.  
  49. const MutationObserver = unsafeWindow.MutationObserver || unsafeWindow.WebKitMutationObserver || unsafeWindow.MozMutationObserver;
  50. const mutationObserver = new MutationObserver(mutations => {
  51. mutationObserver.disconnect();
  52. setTimeout(() => {
  53. unsafeWindow.VideoParsing.init();
  54. }, 200);
  55. });
  56. //PC和非PC,注意判断条件里不能用$简写,不知为问什么
  57. let playerdiv;//let可以先不赋值,用在这里
  58. if (document.querySelector('#player')) {
  59. playerdiv = document.querySelector('#player');
  60. }
  61. else{
  62. console.log("安卓");
  63. playerdiv = document.querySelector('.playerWrapper');
  64. }
  65. const playerDom = playerdiv;
  66. //
  67.  
  68. if (playerDom) {
  69. mutationObserver.observe(playerDom, {
  70. childList: true,
  71. subtree: true,
  72. });
  73. } else {
  74. console.warn('视频一键下载未生效!');
  75. }
  76. })();
  77.  
  78. (function () {
  79. class VideoParsing {
  80. // 根据 key 开头字母获取对象中的值,返回数组
  81. static getObjectValueByStartsWithChar(obj, char) {
  82. const vars = [];
  83. Object.keys(obj).forEach(key => {
  84. if (key.startsWith(char)) {
  85. vars.push({
  86. key: key,
  87. value: obj[key],
  88. });
  89. }
  90. });
  91. return vars;
  92. }
  93.  
  94. // 获取下载地址信息,返回数组
  95. static getUrlInfo() {
  96. const flashvars = this.getObjectValueByStartsWithChar(unsafeWindow, 'flashvars_');
  97. if (!flashvars.length) {
  98. console.error('错误,未获取视频地址!', flashvars);
  99. return;
  100. }
  101.  
  102. let videosInfo = [];
  103.  
  104. try {
  105. videosInfo = flashvars[0]['value']['mediaDefinitions'];
  106. } catch (e) {
  107. console.error('错误,获取视频信息失败!', e, flashvars);
  108. return;
  109. }
  110.  
  111. let remoteAddress = undefined;
  112. let urlInfo = [];
  113.  
  114. for (let i = 0; i < videosInfo.length; i++) {
  115. if (videosInfo[i]['remote']) {
  116. remoteAddress = videosInfo[i]['videoUrl'];
  117. break;
  118. }
  119. }
  120.  
  121. // MP4 信息
  122. if (remoteAddress) {
  123. $.ajax({
  124. url: remoteAddress,
  125. async: false,
  126. success: (data) => {
  127. if (data && data.length) {
  128. urlInfo = urlInfo.concat(data.map(item => ({
  129. quality: item.quality + '.' + item.format,
  130. url: item.videoUrl
  131. })));
  132. }
  133. }
  134. });
  135. }
  136.  
  137. console.log(videosInfo);
  138.  
  139. return urlInfo;
  140. }
  141.  
  142. // 注入到下载面板
  143. static injectUrls2Dom(urlInfo) {
  144. const li = [];
  145.  
  146. urlInfo.forEach(item => {
  147. li.push(`
  148. <li>
  149. <span class="download-url-label">[ ${item.quality} ]</span>
  150. <input class="download-url-input" value="${item.url}" />
  151. <a target="_blank" class="download-url-copy" data-href="${item.url}" href="javascript: void(0);">点击复制地址</a>
  152. </li>
  153. `);
  154. });
  155. //pc和非PC两种情况都加上
  156. $('.playerWrapper').after(`<div class="download-urls"><h3>不同分辨率视频下载地址:</h3><ul>${li.join('')}</ul></div>`);
  157. $('#player').after(`<div class="download-urls"><h3>不同分辨率视频下载地址:</h3><ul>${li.join('')}</ul></div>`);
  158. }
  159.  
  160. // 初始化事件
  161. static initEvens() {
  162. // 点击下载复制到粘贴板中
  163. $(document).on('click', '.download-url-copy', function (e) {
  164. e.preventDefault();
  165. GM_setClipboard($(this).data('href'));
  166. GM_notification('下载地址复制成功!', '提示');
  167. });
  168. }
  169.  
  170. static init() {
  171. this.injectUrls2Dom(this.getUrlInfo());
  172. this.initEvens();
  173. }
  174. }
  175.  
  176. unsafeWindow.VideoParsing = VideoParsing;
  177. })();