// ==UserScript==
// @name Pornhub video download with one click
// @name:ar Pornhub Video Download بنقرة واحدة
// @name:bg Pornhub видео Изтеглете с едно щракване
// @name:cs PornHub Video Stáhnout s jedním kliknutím
// @name:da Pornhub video download med et enkelt klik
// @name:de Pornhub Video Download mit einem Klick
// @name:el Λήψη βίντεο pornhub με ένα κλικ
// @name:en Pornhub video download with one click
// @name:eo Pornhub Video Elŝuti per unu klako
// @name:es Descarga de video pornhub con un solo clic
// @name:fi Pornhub -videon lataa yhdellä napsautuksella
// @name:fr Téléchargement vidéo pornhub en un clic
// @name:fr-CA Téléchargement vidéo pornhub en un clic
// @name:he הורדת וידאו של Pornhub בלחיצה אחת
// @name:hr PornHub video preuzmi s jednim klikom
// @name:hu Pornhub videó letöltése egy kattintással
// @name:id Unduh video pornhub dengan satu klik
// @name:it Download video di Pornhub con un clic
// @name:ja ポルノハブビデオダウンロードワンクリックでダウンロードします
// @name:ka Pornhub Video ჩამოტვირთვა ერთი დაჭერით
// @name:ko 한 번의 클릭으로 Pornhub 비디오 다운로드
// @name:nb Pornhub video nedlasting med ett klikk
// @name:nl Pornhub video downloaden met één klik
// @name:pl Pobierz wideo Pornhub za pomocą jednego kliknięcia
// @name:pt-BR Download de vídeo pornHub com um clique
// @name:ro Descărcare video PornHub cu un singur clic
// @name:ru Скачать видео Pornhub с одним щелчком
// @name:sk Stiahnutie videa pornhub s jedným kliknutím
// @name:sr ПорнХуб Видео Довнлоад са једним кликом
// @name:sv Pornhub video nedladdning med ett klick
// @name:th ดาวน์โหลดวิดีโอ Pornhub ด้วยคลิกเดียว
// @name:tr Pornhub Video İndir Bir Tıkla İndir
// @name:ug Pornhub سىن چۈشۈرۈش بىر چېكىش ئارقىلىق
// @name:uk Завантажити відео Pornhub одним клацанням
// @name:vi Tải xuống video pornhub chỉ bằng một cú nhấp chuột
// @name:zh Pornhub 视频一键下载
// @name:zh-CN Pornhub 视频一键下载
// @name:zh-HK Pornhub 視頻一鍵下載
// @name:zh-SG Pornhub 视频一键下载
// @name:zh-TW Pornhub 視頻一鍵下載
// @description Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions
// @description:ar Pornhub تنزيل مع نقرة واحدة
// @description:bg Pornhub Video с едно щракване |
// @description:cs Stahování videa PornHub |
// @description:da Pornhub -video Download med et klik |
// @description:de Pornhub -Video Download mit einem Klick | Pornhub.com |
// @description:el Pornhub Video Download με ένα κλικ | Pornhub.com |
// @description:en Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions
// @description:eo Pornhub Video Elŝuti kun unu klako | Pornhub.com |
// @description:es Pornhub Video Descarga con un clic |
// @description:fi PornHub -video
// @description:fr Téléchargement de la vidéo PornHub en un clic | Pornhub.com |
// @description:fr-CA Téléchargement de la vidéo PornHub en un clic | Pornhub.com |
// @description:he הורדת וידאו של Pornhub עם לחיצה אחת |
// @description:hr Porno preuzimanje s jednim klikom |
// @description:hu Pornhub videó egy kattintással |
// @description:id Unduh video pornhub dengan satu klik |
// @description:it Download video di Pornhub con un clic |
// @description:ja Pornhubのダウンロード|
// @description:ka Pornhub ვიდეო ჩამოტვირთვა ერთი დაჭერით |
// @description:ko Pornhub는 한 번의 클릭으로 다운로드하십시오
// @description:nb Pornhub Video nedlasting med ett klikk |
// @description:nl Pornhub -video downloaden met één klik | Pornhub.com | Download direct zonder inloggen |
// @description:pl Pornhub Pobierz z jednym kliknięciem |
// @description:pt-BR Download de vídeo porn, com um clique |
// @description:ro Pornhub Descărcare cu un singur clic |
// @description:ru Pornhub Video Скачать с одним кликом |
// @description:sk Stiahnutie videa s jedným kliknutím
// @description:sr ПорнХуб Видео Довнлоад са једним кликом | ПорнХуб.цом | Преузмите директно без пријаве | Преузмите бесплатни за гледање плаћених видео записа | Преузмите видео забрањене видео снимке | Преузмите све видљиве резолуције
// @description:sv Pornhub Video Ladda ner med ett klick |
// @description:th ดาวน์โหลดวิดีโอ Pornhub ด้วยการคลิกหนึ่งครั้ง |
// @description:tr Pornhub bir tıklama ile indirin |
// @description:ug PornHub سىن يوللاش بىر چېكىش ئارقىلىق چۈشۈرۈش | PornHub.com | بىۋاسىتە كىرىش | ھەقسىز سىنلارنى كۆرۈش ئۈچۈن ھەقسىز چۈشۈرۈڭ | چەكلەنگەن بارلىق كۆرگەزمە قىلىش
// @description:uk Відео PornHub одним натисніть
// @description:vi Tải xuống Video của Pornhub với một lần nhấp chuột |
// @description:zh Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-CN Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-HK Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率
// @description:zh-SG Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率
// @description:zh-TW Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率
// @grant unsafeWindow
// @grant GM_setClipboard
// @grant GM_download
// @grant GM_addStyle
// @match *://*.pornhub.com/view_video.php?viewkey=*
// @match *://*.pornhubpremium.com/view_video.php?viewkey=*
// @require https://update.greasyfork.org/scripts/498897/1404834/Toastnew.js
// @require https://code.jquery.com/jquery-3.7.1.min.js
// @author liuwanlin,heckles,人民的勤务员 <[email protected]>
// @namespace https://github.com/ChinaGodMan/UserScripts
// @supportURL https://github.com/ChinaGodMan/UserScripts/issues
// @homepageURL https://github.com/ChinaGodMan/UserScripts
// @license MIT
// @icon data:image/svg+xml;charset=utf-8;base64,Cjxzdmcgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIvPgo8cmVjdCB4PSIxMDgiIHk9IjEwIiB3aWR0aD0iODAiIGhlaWdodD0iNTAiIHJ4PSI0IiBmaWxsPSIjZjc5NzFkIi8+Cgo8ZyB0cmFuc2Zvcm09Im1hdHJpeCguMSAwIDAgLjEgODYuODUgMzAuMTUpIiBzdHJva2Utd2lkdGg9IjEwIj4KPHBhdGggZD0ibTg4Ny0zMGMtNS0yLTExLTMtMTctMy0yNC0yLTU0IDctNjggMTlsMy05N2gtNTd2MzAxaDUzdi0xN2MyNSAxNCA0MyAyMSA2NiAyMSA2Ni01IDkzLTY0IDkzLTExNi0xLTUyLTIzLTk3LTczLTEwOHptLTMyIDE3OWMtMzUgMC01MC00MS01MC03M3MxMS02NSA0OC02NSA0OCA0MSA0OCA3MGMwIDMyLTExIDY4LTQ2IDY4em0tMjAwLTg1YzAgMzEtMiA1MC01IDU4LTggMTgtMjQgMjgtNDIgMjktMTgtMS0yNi0xMC0zMy0yMy0yLTctMy0yNi0zLTU2di0xMDBoLTU4djEzOGMtMSA0OSAyNSA4NCA3MyA4NCAyNiAwIDU0LTkgNzItMjh2MjNoNTN2LTIxN2gtNTd6bS0yNDEtOTdjLTI4LTEtNTkgNi03NCAyMHYtOThoLTU3djMwMGg1N3YtMTA5YzAtMTggMi0zMiA1LTQxIDktMTggMjQtMjggNDMtMjggMTYgMCAyNSA4IDMyIDIwIDIgNiAzIDIxIDMgNDR2MTE1aDU4di0xMjhjMC0yMC0xLTM0LTMtNDMtMTItMzQtMzYtNTEtNjQtNTIiLz4KPHBhdGggZD0ibTY4LTQ1Yy0yNC0xLTYzIDgtNzUgMjd2LTIyaC01NnYyMjloNjB2LTEwM2MwLTI2IDItNDMgNS01MyA4LTIwIDI2LTMxIDQ1LTMxIDE4IDAgMjcgOSAzNCAyMyAyIDcgNCAyMyA0IDQ4djExNmg2MHYtMTQyYzAtMTgtMS0zMS0zLTQxLTEwLTM1LTQxLTUwLTc0LTUxem0tMjU3IDI3di0yMmgtNTZ2MjI5aDYwdi03MGMwLTM5IDItNjUgNS03NyA0LTEyIDgtMjEgMTQtMjYgNi00IDEzLTcgMjItNyA4IDAgMTggNCAyOCAxMGwxOS01MmMtMTMtOC0yNi0xMi00MC0xMi0yMCAxLTQwIDEyLTUyIDI3em0tMjA1LTI3Yy0yMiAwLTQyIDUtNjAgMTUtMTkgMTAtMzMgMjQtNDMgNDNzLTE1IDM4LTE1IDU5YzAgMjYgNSA0OCAxNSA2NiAxMCAxOSAyNSAzMyA0NCA0MiAxOSAxMCAzOSAxNCA2MCAxNCAzNCAwIDYyLTExIDg0LTM0IDIzLTIzIDM0LTUxIDM0LTg2IDAtMzQtMTEtNjMtMzMtODUtMjMtMjMtNTEtMzQtODYtMzRtNDAgMTcyYy0xMCAxMi0yNCAxOC0zOSAxOC0xNiAwLTI5LTYtNDAtMThzLTE2LTMwLTE2LTUyYzAtMjMgNS00MCAxNi01MnMyNC0xOCA0MC0xOGMxNSAwIDI5IDYgMzkgMTggMTEgMTIgMTYgMjkgMTYgNTEgMCAyMy01IDQxLTE2IDUzbS0zMTAtMjU0aC0xMDN2MzE2aDY0di0xMTloNDJjNTEgMiAxMDItNiAxMjYtNTEgNy0xMyAxMC0yOSAxMC00OSAwLTQzLTI0LTgxLTYzLTkyLTEyLTMtMzctNS03Ni01em00NyAxMzhjLTkgNC0yNiA1LTUxIDVoLTM1di04OWgzMWMyMyAwIDM4IDAgNDYgMiAyMiA1IDM2IDIyIDM2IDQyLTEgMTktMTEgMzQtMjcgNDAiIGZpbGw9IiNmZmYiLz4KPC9nPgo8L3N2Zz4K
// @compatible chrome
// @compatible firefox
// @compatible edge
// @compatible opera
// @compatible safari
// @compatible kiwi
// @version 2025.03.05.0145
// @created 2025-03-05 01:45:13
// @modified 2025-03-05 01:45:13
// ==/UserScript==
//!人民的勤务员修改自以下脚本 感谢heckles和liuwanlin
/*https://greasyfork.org/zh-CN/scripts/491333
https://greasyfork.org/zh-CN/scripts/491329
*/
GM_addStyle(`
.download-urls ul { padding: 10px; font-weight: bold; line-height: 1.5; }
.download-urls ul li { display: flex; align-items: center; height: 20px; max-width:400px; }
.download-url-label { /* width: 100px; */ text-align: right; }
.download-url-copy { flex: 1; }
.download-url-mp4 { flex: 1; }
.download-url-input { flex: 3; font-size: 12px; padding: 0 5px; border: 1px solid #ffff; margin: 0 5px; }
`);
(function () {
'use strict'
const userLang = (navigator.languages && navigator.languages[0]) || navigator.language || 'en'
const translations = {
'en': {
downloading: 'Downloading...',
finderror: 'Video download link not found',
fetcherror: 'Error fetching video, please check the console for details',
downloadsuccess: 'Download successful',
downloaderror: 'Error downloading video, please check the console for details',
downloadfailed: 'Download failed',
downloadfailed_nosize: 'Unable to retrieve file size',
copydownloadbtn: 'Copy address',
copysuccess: 'Copy successful',
downloadbtn: 'Download video',
linkTip: 'Video download URL:'
},
'zh-CN,zh,zh-SG': {
downloading: '下载中...',
finderror: '未找到视频下载链接',
fetcherror: '获取视频时出错,请到控制台查看详细信息',
downloadsuccess: '下载成功',
downloaderror: '下载视频时出错,请到控制台查看详细信息',
downloadfailed: '下载失败',
downloadfailed_nosize: '无法获取文件大小',
copydownloadbtn: '复制地址',
copysuccess: '复制成功',
downloadbtn: '下载视频',
linkTip: '视频下载地址:'
},
'zh-TW,zh-HK,zh-MO': {
downloading: '下載中...',
finderror: '未找到視頻下載連結',
fetcherror: '獲取視頻時出錯,請到控制台查看詳細信息',
downloadsuccess: '下載成功',
downloaderror: '下載視頻時出錯,請到控制台查看詳細信息',
downloadfailed: '下載失敗',
downloadfailed_nosize: '無法獲取文件大小',
copydownloadbtn: '複製地址',
copysuccess: '複製成功',
downloadbtn: '下載視頻',
linkTip: '視頻下載地址:'
},
'ja': {
downloading: 'ダウンロード中...',
finderror: 'ビデオのダウンロードリンクが見つかりません',
fetcherror: 'ビデオの取得中にエラーが発生しました。詳細はコンソールを確認してください',
downloadsuccess: 'ダウンロード成功',
downloaderror: 'ビデオのダウンロード中にエラーが発生しました。詳細はコンソールを確認してください',
downloadfailed: 'ダウンロード失敗',
downloadfailed_nosize: 'ファイルサイズを取得できません',
copydownloadbtn: 'アドレスをコピー',
copysuccess: 'コピー成功',
downloadbtn: 'ビデオをダウンロード',
linkTip: 'ビデオダウンロードURL:'
},
'vi': {
downloading: 'Đang tải xuống...',
finderror: 'Không tìm thấy liên kết tải video',
fetcherror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết',
downloadsuccess: 'Tải xuống thành công',
downloaderror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết',
downloadfailed: 'Tải xuống thất bại',
downloadfailed_nosize: 'Không thể lấy kích thước tệp',
copydownloadbtn: 'Sao chép địa chỉ',
copysuccess: 'Sao chép thành công',
downloadbtn: 'Tải xuống video',
linkTip: 'URL tải video:'
},
'fr': {
downloading: 'Téléchargement...',
finderror: 'Lien de téléchargement vidéo introuvable',
fetcherror: 'Erreur lors de la récupération de la vidéo, veuillez vérifier la console pour plus de détails',
downloadsuccess: 'Téléchargement réussi',
downloaderror: 'Erreur lors du téléchargement de la vidéo, veuillez vérifier la console pour plus de détails',
downloadfailed: 'Échec du téléchargement',
downloadfailed_nosize: 'Impossible de récupérer la taille du fichier',
copydownloadbtn: 'Copier l’adresse',
copysuccess: 'Copie réussie',
downloadbtn: 'Télécharger la vidéo',
linkTip: 'URL de téléchargement vidéo :'
},
'es': {
downloading: 'Descargando...',
finderror: 'No se encontró el enlace de descarga del video',
fetcherror: 'Error al obtener el video, consulte la consola para más detalles',
downloadsuccess: 'Descarga exitosa',
downloaderror: 'Error al descargar el video, consulte la consola para más detalles',
downloadfailed: 'Error en la descarga',
downloadfailed_nosize: 'No se puede obtener el tamaño del archivo',
copydownloadbtn: 'Copiar dirección',
copysuccess: 'Copia exitosa',
downloadbtn: 'Descargar video',
linkTip: 'URL de descarga del video:'
}
}
const getTranslations = (lang) => {
for (const key in translations) {
if (key === lang || key.split(',').includes(lang)) {
return translations[key]
}
}
return translations['en']
}
const translate = new Proxy(
function (key) {
const lang = userLang
const strings = getTranslations(lang)
return strings[key] || translations['en'][key]
},
{
get(target, prop) {
const lang = userLang
const strings = getTranslations(lang)
return strings[prop] || translations['en'][prop]
}
}
)
unsafeWindow.translate = translate
const MutationObserver = unsafeWindow.MutationObserver || unsafeWindow.WebKitMutationObserver || unsafeWindow.MozMutationObserver
const mutationObserver = new MutationObserver(mutations => {
mutationObserver.disconnect()
setTimeout(() => {
unsafeWindow.VideoParsing.init()
}, 200)
})
//PC和非PC,注意判断条件里不能用$简写,不知为问什么
let playerdiv//let可以先不赋值,用在这里
if (document.querySelector('#player')) {
playerdiv = document.querySelector('#player')
}
else {
console.log('安卓')
playerdiv = document.querySelector('.playerWrapper')
}
const playerDom = playerdiv
//
if (playerDom) {
mutationObserver.observe(playerDom, {
childList: true,
subtree: true
})
} else {
Toast(translate('finderror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
}
})();
(function () {
class VideoParsing {
// 根据 key 开头字母获取对象中的值,返回数组
static getObjectValueByStartsWithChar(obj, char) {
const vars = []
Object.keys(obj).forEach(key => {
if (key.startsWith(char)) {
vars.push({
key: key,
value: obj[key]
})
}
})
return vars
}
// 获取下载地址信息,返回数组
static getUrlInfo() {
const flashvars = this.getObjectValueByStartsWithChar(unsafeWindow, 'flashvars_')
if (!flashvars.length) {
Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
return
}
let videosInfo = []
try {
videosInfo = flashvars[0]['value']['mediaDefinitions']
} catch (e) {
Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top')
console.error(translate('fetcherror'), e, flashvars)
return
}
let remoteAddress = undefined
let urlInfo = []
for (let i = 0; i < videosInfo.length; i++) {
if (videosInfo[i]['remote']) {
remoteAddress = videosInfo[i]['videoUrl']
break
}
}
// MP4 信息
if (remoteAddress) {
$.ajax({
url: remoteAddress,
async: false,
success: (data) => {
if (data && data.length) {
urlInfo = urlInfo.concat(data.map(item => ({
quality: item.quality + '.' + item.format,
url: item.videoUrl
})))
}
}
})
}
console.log(videosInfo)
return urlInfo
}
// 注入到下载面板
static injectUrls2Dom(urlInfo) {
const li = []
urlInfo.forEach(item => {
li.push(`
<li>
<span class="download-url-label">[ ${item.quality} ]</span>
<input class="download-url-input" value="${item.url}" style="width: 50px;" />
<a target="_blank" class="download-url-copy" data-href="${item.url}" href="javascript: void(0);">${translate('copydownloadbtn')}</a>
<a target="_blank" class="download-url-mp4" data-href="${item.url}" href="javascript: void(0);">${translate('downloadbtn')}</a>
</li>
`)
})
//pc和非PC两种情况都加上
$('.playerWrapper').after(`<div class="download-urls"><h3>${translate('linkTip')}</h3><ul>${li.join('')}</ul></div>`)
$('#player').after(`<div class="download-urls"><h3>${translate('linkTip')}</h3><ul>${li.join('')}</ul></div>`)
}
// 初始化事件
static initEvens() {
// 点击下载复制到粘贴板中
$(document).on('click', '.download-url-copy', function (e) {
e.preventDefault()
GM_setClipboard($(this).data('href'))
Toast(translate('copysuccess'), 3000, 'rgb(18, 219, 18)', '#ffffff', 'top')
})
}
static initDownEvens() {
$(document).on('click', '.download-url-mp4', function (e) {
e.preventDefault()
downloadMp4($(this).data('href'), $(this))
})
}
static init() {
this.injectUrls2Dom(this.getUrlInfo())
this.initEvens()
this.initDownEvens()
}
}
unsafeWindow.VideoParsing = VideoParsing
//转换字节
function getHumanReadableSize(sizeb) {
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const size = sizeb
let i = parseInt(Math.floor(Math.log(size) / Math.log(1024)))
const humanReadableSize = (size / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]
return humanReadableSize
}
function sanitizeTitle() {
var title = document.title
title = title.replace(/- Pornhub\.com/, '')
return title.replace(/[/:*?"<>|]/g, '_')
}
//下载函数
async function downloadMp4(videoUrl, targetElement) {
try {
const response = await fetch(videoUrl)
if (!response.ok) {
$(targetElement).text(translate('downloadfailed'))
}
const contentLength = response.headers.get('Content-Length')
if (!contentLength) {
$(targetElement).text(translate('downloadfailed_nosize'))
return
}
const reader = response.body.getReader()
const totalSize = contentLength ? parseInt(contentLength, 10) : 0 // 文件总大小
let downloadedSize = 0 // 已下载大小
const chunks = [] // 存储数据块
while (true) {
const { done, value } = await reader.read()
if (done) break
// 更新下载大小
downloadedSize += value.length
chunks.push(value)
if (totalSize) {
const progress = ((downloadedSize / totalSize) * 100).toFixed(2)
$(targetElement).text(`${translate('downloading')} ${progress}% (${getHumanReadableSize(downloadedSize)} / ${getHumanReadableSize(totalSize)})`)
} else {
$(targetElement).text(`${translate('downloading')} ${getHumanReadableSize(downloadedSize)}`)
}
}
const blob = new Blob(chunks)
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = url
a.download = sanitizeTitle() + '.mp4'
document.body.appendChild(a)
a.click()
window.URL.revokeObjectURL(url)
document.body.removeChild(a)
Toast(translate('downloadsuccess'), 3000, 'rgb(18, 219, 18)', '#ffffff', 'top')
} catch (error) {
Toast(translate('downloaderror'), 3000, 'rgb(173, 7, 7)', '#ffffff', 'top')
console.error(translate('downloaderror'), error)
}
}
})()