您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Parse Douban Info
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/438042/1005292/Douban%20Info%20Class.js
// ==UserScript== // @name Douban Info Class // @description parse douban info // @version 0.0.9 // @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.defineProperty(this, "id", { value: (async () => id)(), writable: false, }); } get pathname() { return (async () => { const pathname = DoubanInfo.subjectPathName + (await this.id) + "/"; Object.defineProperty(this, "pathname", { value: (async () => pathname)(), writable: false, }); return this.pathname; })(); } get subjectDoc() { 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", { value: (async () => doc)(), writable: false, }); return this.subjectDoc; })(); } get linkingData() { 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", { value: (async () => ldJSON)(), writable: false, }); return this.linkingData; })(); } get type() { return (async () => { const ld = await this.linkingData; const type = ld?.["@type"]?.toLowerCase() || null; Object.defineProperty(this, "type", { value: (async () => type)(), writable: false, }); return this.type; })(); } get poster() { 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", { value: (async () => poster)(), writable: false, }); return this.poster; })(); } get title() { 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", { value: (async () => title)(), writable: false, }); return this.title; })(); } get chineseTitle() { return (async () => { const doc = await this.subjectDoc; const chineseTitle = doc?.title?.slice(0, -5); Object.defineProperty(this, "chineseTitle", { value: (async () => chineseTitle)(), writable: false, }); return this.chineseTitle; })(); } get originalTitle() { 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", { value: (async () => originalTitle)(), writable: false, }); return this.originalTitle; })(); } get isChinese() { return (async () => { let isChinese = false; if ((await this.title) === (await this.chineseTitle)) { isChinese = true; } Object.defineProperty(this, "isChinese", { value: (async () => isChinese)(), writable: false, }); return this.isChinese; })(); } get duration() { 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 } : { duration: null, type: undefined }; Object.defineProperty(this, "duration", { value: (async () => duration)(), writable: false, }); return this.duration; })(); } }