您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Parse Douban Info
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/438042/1005307/Douban%20Info%20Class.js
// ==UserScript== // @name Douban Info Class // @description parse douban info // @version 0.0.11 // @author Secant(TYT@NexusHD) // @icon https://movie.douban.com/favicon.ico // @contributionURL https://i.loli.net/2020/02/28/JPGgHc3UMwXedhv.jpg // @contributionAmount 10 // @namespace https://greasyfork.org/users/152136 // @grant GM_xmlhttpRequest // @connect movie.douban.com class DoubanInfo { static origin = "https://movie.douban.com"; static subjectPathName = "/subject/"; static timeout = 6000; constructor(id) { Object.defineProperties(this, { id: { configurable: true, enumerable: true, get: function () { return (async () => { Object.defineProperty(this, "id", { writable: false, configurable: false, enumerable: true, value: (async () => id)(), }); return this.id; })(); }, }, pathname: { configurable: true, enumerable: false, get: function () { return (async () => { const pathname = DoubanInfo.subjectPathName + (await this.id) + "/"; Object.defineProperty(this, "pathname", { writable: false, configurable: false, enumerable: false, value: (async () => pathname)(), }); return this.pathname; })(); }, }, subjectDoc: { configurable: true, enumerable: false, get: function () { return (async () => { const currentURL = new URL(window.location.href); let doc; if ( currentURL.origin === DoubanInfo.origin && currentURL.pathname === (await this.pathname) ) { doc = document; } else { doc = new Promise(async (resolve) => { GM_xmlhttpRequest({ method: "GET", url: new URL( await this.pathname, DoubanInfo.origin ).toString(), headers: { referrer: DoubanInfo.origin, }, timout: DoubanInfo.timeout, onload: (resp) => { try { resolve( new DOMParser().parseFromString( resp.responseText, "text/html" ) ); } catch (err) { console.warn(err); resolve(null); } }, ontimeout: (e) => { console.warn(e); resolve(null); }, onerror: (e) => { console.warn(e); resolve(null); }, }); }); } Object.defineProperty(this, "subjectDoc", { writable: false, configurable: false, enumerable: false, value: (async () => doc)(), }); return this.subjectDoc; })(); }, }, linkingData: { configurable: true, enumerable: false, get: function () { return (async () => { const doc = await this.subjectDoc; const ldJSON = dJSON.parse( heDecode( doc?.querySelector("head>script[type='application/ld+json']") ?.textContent ) ) || null; Object.defineProperty(this, "linkingData", { writable: false, configurable: false, enumerable: false, value: (async () => ldJSON)(), }); return this.linkingData; })(); }, }, type: { configurable: true, enumerable: true, get: function () { return (async () => { const ld = await this.linkingData; const type = ld?.["@type"]?.toLowerCase() || null; Object.defineProperty(this, "type", { writable: false, configurable: false, enumerable: true, value: (async () => type)(), }); return this.type; })(); }, }, poster: { configurable: true, enumerable: true, get: function () { return (async () => { const doc = await this.subjectDoc; const ld = await this.linkingData; const posterFromMeta = doc?.querySelector("head>meta[property='og:image']")?.content || null; const posterFromLD = ld?.image || null; const posterFromPage = doc?.querySelector("body #mainpic img")?.src || null; const poster = (posterFromMeta || posterFromLD || posterFromPage) ?.replace("s_ratio_poster", "l_ratio_poster") .replace(/img\d+\.doubanio\.com/, "img9.doubanio.com") .replace(/\.webp$/i, ".jpg") || null; Object.defineProperty(this, "poster", { writable: false, configurable: false, enumerable: true, value: (async () => poster)(), }); return this.poster; })(); }, }, title: { configurable: true, enumerable: false, get: function () { return (async () => { const doc = await this.subjectDoc; const ld = await this.linkingData; const titleFromPage = doc?.querySelector("body #content h1>span[property]") ?.textContent || null; const titleFromMeta = doc?.querySelector("head>meta[property='og:title']")?.content || null; const titleFromLD = ld?.name || null; const title = titleFromPage || titleFromMeta || titleFromLD || null; Object.defineProperty(this, "title", { writable: false, configurable: false, enumerable: false, value: (async () => title)(), }); return this.title; })(); }, }, chineseTitle: { configurable: true, enumerable: true, get: function () { return (async () => { const doc = await this.subjectDoc; const chineseTitle = doc?.title?.slice(0, -5); Object.defineProperty(this, "chineseTitle", { writable: false, configurable: false, enumerable: true, value: (async () => chineseTitle)(), }); return this.chineseTitle; })(); }, }, originalTitle: { configurable: true, enumerable: true, get: function () { return (async () => { let originalTitle; if (await this.isChinese) { originalTitle = await this.chineseTitle; } else { originalTitle = (await this.title) ?.replace(await this.chineseTitle, "") .trim(); } Object.defineProperty(this, "originalTitle", { writable: false, configurable: false, enumerable: true, value: (async () => originalTitle)(), }); return this.originalTitle; })(); }, }, isChinese: { configurable: true, enumerable: false, get: function () { return (async () => { let isChinese = false; if ((await this.title) === (await this.chineseTitle)) { isChinese = true; } Object.defineProperty(this, "isChinese", { writable: false, configurable: false, enumerable: false, value: (async () => isChinese)(), }); return this.isChinese; })(); }, }, duration: { configurable: true, enumerable: true, get: function () { return (async () => { const doc = await this.subjectDoc; const ld = await this.linkingData; const durationFromMeta = parseInt( doc?.querySelector("head>meta[property='video:duration']") ?.content, 10 ) || null; const durationFromLD = ld?.duration?.replace( /^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/, (_, p1, p2, p3) => { return ( parseInt(p1, 10) * 3600 + parseInt(p2, 10) * 60 + parseInt(p3, 10) ).toString(); } ) || null; /*const durationFromPage =*/ const duration = durationFromMeta ? [{ duration: durationFromMeta, type: undefined }] : durationFromLD ? [{ duration: durationFromLD, type: undefined }] : []; Object.defineProperty(this, "duration", { writable: false, configurable: false, enumerable: true, value: (async () => duration)(), }); return this.duration; })(); }, }, }); } }