javlibrary网站 增强内容包括:预览视频、在线播放、下载链接、预览图补全 etc.
// ==UserScript==
// @name javlibrary enhancement
// @name:zh javlibrary 图书馆网站增强
// @namespace http://tampermonkey.net/
// @version 1.0.1
// @description javlibrary网站 增强内容包括:预览视频、在线播放、下载链接、预览图补全 etc.
// @author https://greasyfork.org/zh-CN/users/25283
// @match https://*.javlibrary.com/*
// @icon https://www.javlibrary.com/favicon.ico
// @grant GM_xmlhttpRequest
// @connect cc3001.dmm.co.jp
// @connect pics.dmm.co.jp
// @connect pics.dmm.com
// @connect www.dmm.com
// @connect www.dmm.co.jp
// @connect sukebei.nyaa.si
// @connect missav.ws
// @connect av-wiki.net
// @connect supjav.com
// @license MIT
// ==/UserScript==
//在前人的基础上修改,增强内容包括:
// 1、首页热门影片预览图高度固定,在高分显示器上预览图太小了,放大画面的话就会显示不全,修改热门影片列表高度为自动。(建议在4K显示器放大画面设为175%或200%)
// 2、由于DMM反盗链,以前的视频地址失效了,更新了影片预览视频的方式,直接嵌入DMM的预览页面。需要注意,DMM的视频只允许日本IP预览,日本以外的IP会被拒绝。
// 3、添加VR影片的预览视频,无须VR眼镜也能观看,由于DMM的VR视频页禁止嵌入,只能做成链接形式,但好处是可以全屏放大,方法是按F11键,并且VR影片可以用鼠标拖动调整视角,提高观影体验。
// 4、如果图书馆的预览截图缺失,尝试重新补足 示例:REBD-669 和 ABF-226,切换插件开关可以看到效果。
// 5、如果你有下片时收藏封面图和预览图和预览视频的习惯,可以在浏览器扩展商店安装Chrono下载器插件,然后在预览图下方链接,右键可以批量保存预览图,省却你一张一张点的麻烦。
// 6、直接显示Sukebei.nyaa.si的搜索结果,在页内就可以直接下载影片。
// 7、将左侧导航栏和顶部Logo隐藏,并增加5项分类标签,方便直达特殊分类。
//本插件专注四项核心需求:预览视频、在线播放、下载链接、预览图补全,页面干净清爽,秒杀其他一堆乱七八糟功能搞得页面混乱不堪的脚本,请试着关闭其他脚本感受一下。
//尽量少修改页面元素,可以最大限度与其他脚本兼容。有疑问请站内私讯 Warma
(function () {
'use strict';
const gmFetch = (url, { method, headers, anonymous } = {}) => new Promise((onload, onerror) => {GM_xmlhttpRequest({ url, method, headers, anonymous, onload, onerror })})
const parseHTML = (str) => {const tmp = document.implementation.createHTMLDocument();tmp.body.innerHTML = str; return tmp;}
//const check = async (src) => (await gmFetch(src, { method: 'HEAD' })).status === 200
function normalizeString(str) {
if (typeof str !== 'string') return str;
str.replace("55t38","55t3800") //T38-***系列的需要特殊处理
// 惰性前缀 + 贪婪末尾数字(至少 3 位),一次性完成拆分
const m = /^(.*?)(\d{3,})$/.exec(str);
if (!m) return str; // 无法拆分,原样返回
const prefix = m[1];
const digits = m[2];
const arr = [
['41hodv', '5642hodv'],
['9oae', 'oae'],
];
const map = new Map(arr);
const replacedFront = map.has(prefix) ? map.get(prefix) : prefix;
// 只有恰好 3 位时才补两个 0
let newDigits = digits.length === 3 ? '00' + digits : digits;
// 总长度不足 5 位 → 前面补 0 至 5 位
if (newDigits.length < 5) {
newDigits = newDigits.padStart(5, '0');
}
return replacedFront + newDigits;
}
function mainpage(){ // 优化首页显示效果
console.log("首页");
try{
var leftmenu = document.querySelector("#leftmenu");
var rightcolumn = document.querySelector("#rightcolumn");
// 左边导航菜单增加几项分类
const node = document.querySelector("#leftmenu > div > ul > li:nth-child(3)");
node.insertAdjacentHTML('afterend', '<li><a href="vl_genre.php?g=aazq" style="color:red">漫改作品</a></li>')
node.insertAdjacentHTML('afterend', '<li><a href="vl_genre.php?g=anbq" style="color:red">高品质VR</a></li>')
node.insertAdjacentHTML('afterend', '<li><a href="vl_genre.php?g=aaua" style="color:red">新发行VR</a></li>')
node.insertAdjacentHTML('afterend', '<li><a href="vl_genre.php?g=a5gq" style="color:red">介绍影片</a></li>')
node.insertAdjacentHTML('afterend', '<li><a href="vl_genre.php?g=my" style = "color:red">新人亮相</a></li>')
leftmenu.style.display='none'; // 隐藏左侧导航栏
document.querySelector("#toplogo").style.display='none'; // 隐藏LOGO
rightcolumn.style.margin='0px 10px 10px 0px';
var boxtitle = document.querySelector("#rightcolumn > div.boxtitle");
if (!boxtitle) {const $position = document.querySelector("#video_title");
const html = `<div class="boxtitle"><a onclick="leftmenu.style.display='inline-block';rightcolumn.style.margin='0px 10px 10px 180px';return false;"> >>><b style="color:red">显示</b><<< </a>左边导航菜单</div>`
$position.insertAdjacentHTML('beforebegin', html);}
else{boxtitle.innerHTML += '<a onclick="leftmenu.style.display=\'inline-block\';rightcolumn.style.margin=\'0px 10px 10px 180px\';return false;"> >>><b style="color:red">显示</b><<< </a>左边导航菜单';}
var category = document.querySelector("#leftmenu > div > div.category");
category.innerHTML += '<a onclick="leftmenu.style.display=\'none\';rightcolumn.style.margin=\'0px 10px 10px 0px\';return false;"> >>><b style="color:red">隐藏</b><<< </a>';
document.querySelector("#rightcolumn > div.videothumblist").style.height = '100%'; // 首页热门影片高度自动调整
document.querySelector("#leftmenu > div > ul:nth-child(2) > li:nth-child(2)").remove(); //18禁游戏
document.body.insertAdjacentHTML('afterend', '<style>.videothumblist .videos .video{display:inline-flex !important;height:auto !important} .videothumblist .videos .video .title{height:auto !important} </style>')
// 删除首页底部的一长串介绍文字
var elements = document.getElementsByClassName("about");
var array = Array.from(elements); array.forEach(function (element) {element.remove();}); //关于Javlibrary
return;
}catch (error) {};
//try{}catch (error) {console.error("首页效果错误",error);};
}
mainpage()
try{ // 优化影片详情页显示效果
console.log("详情页");
var video_jacket_img = document.querySelector("#video_jacket_img"); if (!video_jacket_img) return;
var imgpath = video_jacket_img.src.replace("so/","/").split('/')[6]; var imgpath1 = imgpath.substr(0,1); var imgpath3 = imgpath.length>5 ? imgpath.substr(0,3):imgpath.substr(0,2)+"0"; //例子:BeFree系列 bf728
var imgpathrest = imgpath.substr(0,imgpath.length-3); var imgpathnum = imgpath.substr(imgpath.length-3,3); var imgpath00 = imgpathrest+'00'+imgpathnum
var avid = document.querySelector("head > meta[name=keywords]").content.split(", "); // 两种格式的番号:SONE-001,sone001 使用avid[0],avid[1]选择,未来扩展功能备用。
const $stylesheet = document.querySelector("head > link[rel=stylesheet]")
const html = '<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css" rel="stylesheet">'
$stylesheet.insertAdjacentHTML('afterend', html);
document.querySelector("#video_id > table > tbody > tr > td.header").innerHTML += '<a href=\"https://123av.com/ja/search?keyword='+avid[0]+'\" title=\"搜索123AV\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
document.querySelector("#video_date > table > tbody > tr > td.header").innerHTML += '<a href=\"https://sukebei.nyaa.si/?q='+avid[0]+'\" title=\"搜索Sukebei\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
document.querySelector("#video_label > table > tbody > tr > td.header").innerHTML += '<a href=\"https://av-wiki.net/'+avid[0]+'/\" title=\"搜索AV-Wiki\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
document.querySelector("#video_maker > table > tbody > tr > td.header").innerHTML += '<a href=\"https://supjav.com/zh/?s='+avid[0]+'\" title=\"搜索SupJav\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
document.querySelector("#video_length > table > tbody > tr > td.header").innerHTML += '<a href=\"https://missav.ws/search/'+avid[0]+'\" title=\"搜索MissAV\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
document.querySelector("#video_director > table > tbody > tr > td.header").innerHTML += '<a href=\"https://www.javbus.com/'+avid[0]+'\" title=\"搜索JavBus\" target=\"sukebei\"><i class="fa fa-search"></i></a>'
const $position = document.querySelector("#rightcolumn > hr");if (!$position) return;
function previewsection(){
const race = (promises) => {
console.log("测试预览视频");
const newPromises = promises.map((p) => new Promise((resolve, reject) => p.then((v) => v && resolve(v), reject)));
newPromises.push(Promise.all(promises).then(() => false));
return Promise.race(newPromises)
}
const preview = async() => {
const vpdm = async() => {var video1 = 'https://pics.dmm.co.jp/digital/video/'+imgpath+'/'+imgpath+'-1.jpg';
try {
const check = async (src) => (await gmFetch(src, { method: 'HEAD' })).status === 200
if (await check(video1)) {return imgpath};} catch (error) {}
}
const vpdmm = async() => {var video2 = 'https://pics.dmm.co.jp/digital/video/'+imgpath00+'/'+imgpath00+'-1.jpg';
try {
const check = async (src) => (await gmFetch(src, { method: 'HEAD' })).status === 200
if (await check(video2)) {return imgpath00};} catch (error) {}
}
let src = await race([vpdmm(), vpdm()])
if (src){
for (let i=1;i<=20;i++){ // 这里偷懒未做判断,直接显示20个预览图,所以有可能会有无效的预览图
var thumbssrc ='https://pics.dmm.co.jp/digital/video/'+src+'/'+src+'jp-'+i+'.jpg'
var thumbssrc2='https://pics.dmm.co.jp/digital/video/'+src+'/'+src+'-'+i+'.jpg'
thumbsrc += '<a href="'+thumbssrc+'"><img width="120" height="90" border="0" src="'+thumbssrc2+'" ></a>';
};
try{document.querySelector("#rightcolumn > div.previewthumbs").remove();}catch (error) {}
const html =`<div class="previewthumbs" style="display:block; margin:10px auto;"></div>`
const $position = document.querySelector("#rightcolumn > div.socialmedia");
$position.insertAdjacentHTML('afterend', html);
document.querySelector("#rightcolumn > div.previewthumbs").innerHTML = thumbsrc;
// 创建批量保存预览图的链接
imgjacket_tag = document.querySelectorAll('#rightcolumn > div.previewthumbs > a');
var imghref = 'https://pics.dmm.co.jp/digital/video/'+src+'/'+src+'jp-[1:20].jpg';
const html1 =`<br> <a href=${imghref} onclick="return false;"> [右键用Chrono插件的菜单(链接另存为...)批量保存缩略图]</a> [预览补足] <a id='searchdmm' href='https://video.dmm.co.jp/av/list/?key=${normalizeString(avid[1])}' target=blank> 搜索DMM </a> `;
$position.insertAdjacentHTML('beforebegin', html1);
document.querySelector("#rightcolumn > div.socialmedia").remove(); // 删除社交网站图标栏
preview2();
}
}
const preview2 = async() => {
var imgpath22 = document.querySelector("#rightcolumn > div.previewthumbs > a").href.split("/")[5]
imgpath22 = normalizeString(imgpath22)
var avid = document.querySelector("head > meta[name=keywords]").content.split(", ");
if (avid[0].indexOf("VR") !== -1) {
const $position = document.querySelector("#searchdmm")
const html = `<a href="https://www.dmm.co.jp/digital/-/vr-sample-player/=/cid=${imgpath22}/" target=_blank > 点击打开VR预览视频(VR预览视频可以用鼠标拖动切换视角) </a>`;
$position.insertAdjacentHTML('afterend', html)
} else {
var src = 'https://www.dmm.co.jp/service/digitalapi/-/html5_player/=/cid='+imgpath22+'/';
}
console.log(src);
if (src) document.querySelector("#video_webplayer").style.display = 'block';
document.querySelector("#WebPlayer").src = src;
}
try{ //预览补足
console.log("预览补足");
var imgjacket_tag = document.querySelectorAll('#rightcolumn > div.previewthumbs > a ');
if (imgjacket_tag.length == 0) { // 如果预览图缺失,尝试补足 示例:REBD-937 和 ABF-226
var thumbsrc = '';
var thumbsrc00 = 'https://pics.dmm.co.jp/digital/video/'+imgpath00+'/'+imgpath00+'jp-1.jpg';
// var thumbsrc00 = 'https://pics.dmm.co.jp/digital/video/h_346rebd00937/h_346rebd00937jp-1.jpg' 例子
// var thumbsrc00 = 'https://pics.dmm.co.jp/digital/video/118abf226/118abf226jp-1.jpg' 例子
preview();
}//待扩展
else { // 创建批量保存预览图的链接
var imghref = imgjacket_tag[imgjacket_tag.length-1].getAttribute('href'); imghref = imghref.replace('jp-','jp-[1:'); imghref = imghref.replace('.jpg','].jpg');
const html =`<br> <a href=${imghref} onclick="return false;"> [右键用Chrono插件的菜单(链接另存为...)批量保存缩略图]</a> <a id='searchdmm' href='https://video.dmm.co.jp/av/list/?key=${normalizeString(avid[1])}' target=blank> 搜索DMM </a>`;
$position.insertAdjacentHTML('beforebegin', html);
document.querySelector("#rightcolumn > div.socialmedia").remove(); // 删除社交网站图标栏
}
try { // 尝试获取预览视频,使用iframe
const html = '<div id="video_webplayer" style="display:none;"><iframe src="" width="640" height="360" target="_self" scrolling="no" allow="autoplay; fullscreen;" style="border:0;" id="WebPlayer" name="WebPlayer"></iframe></div>'
$position.insertAdjacentHTML('afterend', html);
} catch (error) {console.error("预览视频错误");}
preview2()
}catch (error) {console.error("预览补足错误");}
}
previewsection()
function commentsection(){
//将评论里面只有推广链接没有评论内容的评论删掉
console.log("评论");
try{var elements = document.querySelectorAll("#video_comments > table > tbody > tr > td.t > div > b > a");
var array = Array.from(elements); array.forEach(function (element) {element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.remove();}); //使用者文章的种子链接
}catch {};
try{elements = document.querySelectorAll("#video_comments > table > tbody > tr > td.t > div > a");
array = Array.from(elements); array.forEach(function (element) {element.parentNode.parentNode.parentNode.parentNode.parentNode.remove();}); //使用者文章的种子链接
}catch {};
}
commentsection()
async function sukibeilinks() {
console.log("Sukibei")
try{ // 显示Sukebei的搜索结果磁力链
const $position = document.querySelector("#videoimages");
const res = await gmFetch(`https://sukebei.nyaa.si/?q=${avid[0]}`, {method: 'GET', anonymous: true, headers: {'Accept':'text/html,application/xhtml+xml,application/xml', 'User-Agent': 'Android'},});
const sukebei = parseHTML(res.responseText).querySelector("body > div > div > table");
if (sukebei){
var tds = sukebei.querySelectorAll("body > div > div > table > tbody > tr > td:nth-child(1)")
var array = Array.from(tds);
array.forEach(element => {element.remove();});
sukebei.querySelector("body > div > div > table > thead > tr > th").remove()
tds = sukebei.querySelectorAll("body > div > div > table > tbody > tr > td:nth-child(1) > a")
array = Array.from(tds);
array.forEach(element => {
element.removeAttribute("href");
element.innerHTML = element.innerHTML.toString().replace("中文","<b style='color:red;'>中文</b>");
element.innerHTML = element.innerHTML.toString().replace("FHDC","FHDC<b style='color:red;'>中文字幕</b>");
});
tds = sukebei.querySelectorAll("body > div > div > table > tbody > tr > td:nth-child(2)")
array = Array.from(tds);
array.forEach(element => {element.innerHTML = element.innerHTML.toString().replace('/download', 'https://sukebei.nyaa.si/download');});
$position.insertAdjacentHTML('beforebegin', "<table border='1'>"+sukebei.innerHTML+'</table><br>');
}
}catch (error) {console.error("Sukebei搜索结果错误");}
}
sukibeilinks()
const SupJav = async() => {
console.log("SupJav");
try {
const response = await new Promise((resolve, reject) => {GM_xmlhttpRequest({method:'GET', url:"https://supjav.com/zh/?s="+avid[0], onload:resolve, onerror:reject});});
const SupLink = parseHTML(response.responseText).querySelector("div.post > a")
const Suphtml = "<br><a href='"+SupLink.href+"' target=\"sukebei\">Supa "+SupLink.title+"</a>"
const $position = document.querySelector("#owned")
$position.insertAdjacentHTML('afterend', Suphtml)
}catch (error) {console.error("SupJav错误");}
}
SupJav()
}catch (error) {}
function MissAV() { // 获取MissAV的链接,如果显示多条,可能是有无码和/或中文。
async function checkVideoAvailability(avid) {
try {
const response = await new Promise((resolve, reject) => {GM_xmlhttpRequest({method:'GET', url:"https://missav.ws/search/"+avid, onload:resolve, onerror:reject});});
if (response.status !== 200) throw new Error(`HTTP错误: ${response.status}`);
const MissLink = parseHTML(response.responseText).querySelectorAll("body > div:nth-child(47) > div.sm\\:container.mx-auto.px-4.content-with-search.pb-12 > div.grid.grid-cols-2.md\\:grid-cols-3.xl\\:grid-cols-4.gap-5 > div > div > div > a.text-secondary.group-hover\\:text-primary")
MissLink.forEach(element => {
const MissHtml = "<br><a href='"+element.href+"' target=\"sukebei\">Miss "+element.text+"</a>"
const $position = document.querySelector("#owned")
$position.insertAdjacentHTML('afterend', MissHtml)
})
} catch (error) {}
}
function displayMissAVLink() {
const avid = document.querySelector("head > meta[name=keywords]").content.split(",")[0]
checkVideoAvailability(avid);
}
displayMissAVLink();
}
MissAV();
})();