Skip to content

Instantly share code, notes, and snippets.

@cyb233
Last active October 19, 2023 07:53
Show Gist options
  • Save cyb233/ac48e598b22c9b258ef4d015fd815200 to your computer and use it in GitHub Desktop.
Save cyb233/ac48e598b22c9b258ef4d015fd815200 to your computer and use it in GitHub Desktop.
获取e站所有收藏,以及对所有标签进行排序以找到你最爱的标签,可按namespace分组,支持翻译

使用方式:

image


参考输出(依次为 收藏,reclass排序,tag排序,分组tag排序):

20230911005719


开启翻译:

20230911005851


关于tagListgroupedTagList在控制台查看会自动按key排序,推荐通过复制最后一行JSON.stringify输出的JSON字符串,通过vscode的JSON格式化或其他JSON格式化网站查看,如 https://jsonformatter.org/

// ==UserScript==
// @name e站收藏统计
// @namespace Schwi
// @version 0.5
// @description 获取e站所有收藏,以及对所有标签进行排序以找到你最爱的标签,可按namespace分组,支持翻译
// @author Schwi
// @match *://e-hentai.org/*
// @match *://exhentai.org/*
// @icon https://e-hentai.org/favicon.ico
// @grant none
// @license GPLv3
// ==/UserScript==
(function() {
'use strict';
// 在 https://e-hentai.org/ 或 https://exhentai.org/ 任意页面运行即可
if (!["e-hentai.org", "exhentai.org"].includes(location.hostname)) {
alert("error host!")
throw new Error("error host!")
}
// 是否翻译标签(需下载翻译文本)
const config = {}
config.translationUrl = "https://raw.githubusercontent.com/EhTagTranslation/DatabaseReleases/master/db.text.json"
config.favoritesUrl = location.origin + "/favorites.php?inline_set=dm_e"
function collect(config){
// 查询所有收藏
const queryUrl = new URL(config.favoritesUrl || location.href + "favorites.php?inline_set=dm_e")
let favList = []
function get(url) {
let xhr = new XMLHttpRequest()
xhr.open("GET", url, false)
xhr.send()
if (xhr.status === 200) {
return xhr.responseText
} else {
console.error(xhr.statusText)
}
}
let nextUrl = queryUrl.href
while (nextUrl) {
let resp = get(nextUrl)
if (resp) {
let doc = new DOMParser().parseFromString(resp, "text/html")
let next = doc.scripts[3]
let scriptContent = next.textContent || next.innerText
let match = scriptContent.match(/var nexturl="(.*?)"/)
nextUrl = match && match[1]
if(nextUrl && nextUrl.startsWith('http') && new URL(nextUrl).pathname != queryUrl.pathname) {
nextUrl = null
}
favList = favList.concat(Array.from(doc.querySelectorAll(".itg.glte>tbody>tr")))
}
}
// 整理所有收藏内容
let myFavList = []
favList.forEach(fav => {
let title = fav.querySelector(".glink").innerText
let url = fav.href
let reclass = fav.querySelector(".cn").innerText
let tags = []
fav.querySelectorAll("td>[title]").forEach(tag => {
let title = tag.title
if (title.startsWith(":")) {
title = "temp" + title
}
tags.push(title)
})
myFavList.push({ title, url, reclass, tags })
})
// 翻译tag
const select = document.querySelector('#schwi_translate')
if (select && select.checked) {
const translationUrl = config.translationUrl || "https://raw.githubusercontent.com/EhTagTranslation/DatabaseReleases/master/db.text.json"
try {
const response = get(translationUrl)
if (!response) {
throw new Error("Network response was not ok")
}
const db = JSON.parse(response)
myFavList.forEach(fav => {
if (fav.reclass in db.data[0].data) {
fav.reclass = db.data[0].data[fav.reclass].name
}
fav.tags = fav.tags.map(fullTag => {
let namespace = fullTag.split(":")[0]
let tag = fullTag.split(":")[1]
let data = db.data.filter(title => title.frontMatters.key === namespace)
if (data.length > 0) {
namespace = data[0].frontMatters.name
if (tag in data[0].data) {
tag = data[0].data[tag].name
}
}
return namespace + ":" + tag
})
})
} catch (error) {
console.error("Error fetching data:", error)
}
}
function sortByCount(list) {
const array = Object.entries(list)
array.sort((a, b) => (b[1] - a[1]) * 2 + (a[0].toUpperCase() > b[0].toUpperCase() ? 1 : -1))
return Object.fromEntries(array)
}
// reclass排序
let reclassList = {}
myFavList.forEach(fav => {
if (fav.reclass in reclassList) {
reclassList[fav.reclass]++
} else {
reclassList[fav.reclass] = 1
}
})
reclassList = sortByCount(reclassList)
// 所有tag排序
let tagList = {}
myFavList.forEach(fav => {
fav.tags.forEach(tag => {
if (tag in tagList) {
tagList[tag]++
} else {
tagList[tag] = 1
}
})
})
tagList = sortByCount(tagList)
// 按namespace分组的tag排序
let groupedTagList = {}
myFavList.forEach(fav => {
fav.tags.forEach(fullTag => {
let namespace = fullTag.split(":")[0]
let tag = fullTag.split(":")[1]
if (!(namespace in groupedTagList)) {
groupedTagList[namespace] = {}
}
if (fullTag in groupedTagList[namespace]) {
groupedTagList[namespace][fullTag]++
} else {
groupedTagList[namespace][fullTag] = 1
}
})
})
for (let k in groupedTagList) {
groupedTagList[k] = sortByCount(groupedTagList[k])
}
return { myFavList, reclassList, tagList, groupedTagList }
}
const div = document.createElement('div')
div.innerHTML = `
<a id="schwi_btn">统计收藏</a>
<input type="checkbox" id="schwi_translate" name="schwi_translate" />
<label for="schwi_translate">翻译结果</label>
`
document.querySelector("#nb").appendChild(div)
//不够宽了...
document.querySelector("#nb").style.maxWidth='1200px'
document.querySelector("#schwi_btn").onclick = (event) => {
const { myFavList, reclassList, tagList, groupedTagList } = collect(config)
console.log({ '收藏数量':Object.keys(myFavList).length, '标签数量':Object.keys(tagList).length })
console.log(myFavList)
console.log(reclassList)
console.log(tagList)
console.log(groupedTagList)
console.log(JSON.stringify(myFavList))
// JSON输出,myFavList太长了,单独打印吧
console.log(JSON.stringify({ reclassList, tagList, groupedTagList }))
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment