mirror of
https://github.com/venera-app/venera-configs.git
synced 2025-09-27 00:27:23 +00:00
Update comick and add baihehui (#88)
* add new source from comick * fix some code * fix gif load and comic list info(none-type/chapter/volume) * add some comick hidden tags * revise coding error in file * info updata time * fix no-EN error * add new function - Multi-language comic selection support - Added comic recommendations - Fixed empty chapter return bug - Resolved tag click issues - Optimized data processing * Optimize network request Remove redundant requests and prevent async deadlocks * Update comick.js * new small comic source from baihehui
This commit is contained in:
673
baihehui.js
Normal file
673
baihehui.js
Normal file
@@ -0,0 +1,673 @@
|
||||
/** @type {import('./_venera_.js')} */
|
||||
class Baihehui extends ComicSource {
|
||||
// Note: The fields which are marked as [Optional] should be removed if not used
|
||||
|
||||
// name of the source
|
||||
name = "百合会"
|
||||
|
||||
// unique id of the source
|
||||
key = "baihehui"
|
||||
|
||||
version = "1.0.0"
|
||||
|
||||
minAppVersion = "1.4.0"
|
||||
|
||||
// update url
|
||||
url = "https://cdn.jsdelivr.net/gh/venera-app/venera-configs@main/baihehui.js"
|
||||
|
||||
settings = {
|
||||
domains: {
|
||||
title: "主页源",
|
||||
type: "select",
|
||||
options: [
|
||||
{ value: "yamibo.com" },
|
||||
],
|
||||
default: "yamibo.com"
|
||||
},
|
||||
}
|
||||
|
||||
get baseUrl() {
|
||||
return `https://www.${this.loadSetting('domains')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Optional] init function
|
||||
*/
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
account = {
|
||||
login: async (username, password) => {
|
||||
Network.deleteCookies("https://www.yamibo.com");
|
||||
// 1. GET 登录页,保存 PHPSESSID 和 _csrf-frontend
|
||||
let resGet = await Network.get("https://www.yamibo.com/user/login", {
|
||||
headers: { "User-Agent": "Mozilla/5.0" }
|
||||
});
|
||||
if (resGet.status !== 200) throw "无法打开登录页";
|
||||
|
||||
// 1.1 提取并保存 GET 返回的 Set-Cookie
|
||||
let sc1 = resGet.headers["set-cookie"] || resGet.headers["Set-Cookie"] || [];
|
||||
let initialCookies = [];
|
||||
for (let line of Array.isArray(sc1) ? sc1 : [sc1]) {
|
||||
let [pair] = line.split(";");
|
||||
let [name, value] = pair.split("=");
|
||||
name = name.trim(); value = value.trim();
|
||||
if (name === "PHPSESSID" || name === "_csrf-frontend") {
|
||||
initialCookies.push(new Cookie({ name, value, domain: "www.yamibo.com" }));
|
||||
}
|
||||
}
|
||||
Network.setCookies("https://www.yamibo.com", initialCookies);
|
||||
|
||||
// 2. 解析 CSRF token
|
||||
let doc = new HtmlDocument(resGet.body);
|
||||
let csrf = doc
|
||||
.querySelector('meta[name="csrf-token"]')
|
||||
.attributes.content;
|
||||
doc.dispose();
|
||||
|
||||
// 3. 构造编码后的表单
|
||||
let form = [
|
||||
`_csrf-frontend=${encodeURIComponent(csrf)}`,
|
||||
`LoginForm%5Busername%5D=${encodeURIComponent(username)}`,
|
||||
`LoginForm%5Bpassword%5D=${encodeURIComponent(password)}`,
|
||||
'LoginForm%5BrememberMe%5D=0',
|
||||
'LoginForm%5BrememberMe%5D=1',
|
||||
`login-button=${encodeURIComponent("登录")}`
|
||||
].join("&");
|
||||
|
||||
// 4. POST 登录(会自动带上刚才的 Cookie)
|
||||
let resPost = await Network.post(
|
||||
"https://www.yamibo.com/user/login",
|
||||
{
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Referer": "https://www.yamibo.com/user/login",
|
||||
"User-Agent": "Mozilla/5.0"
|
||||
},
|
||||
form
|
||||
);
|
||||
if (resPost.status === 400) throw "登录失败";
|
||||
Network.deleteCookies("https://www.yamibo.com");
|
||||
|
||||
// …account.login 中 POST 后提取 Cookie 部分…
|
||||
let raw = resPost.headers["set-cookie"] || resPost.headers["Set-Cookie"];
|
||||
if (!raw) throw "未收到任何 Cookie";
|
||||
|
||||
// 1. 将单条字符串按“逗号+Cookie名=”拆分
|
||||
let parts = Array.isArray(raw)
|
||||
? raw
|
||||
: raw.split(/,(?=\s*(?:PHPSESSID|_identity-frontend|_csrf-frontend)=)/);
|
||||
|
||||
// 2. 提取目标 Cookie
|
||||
const names = ["PHPSESSID", "_identity-frontend", "_csrf-frontend"];
|
||||
let cookies = parts.map(line => {
|
||||
let [pair] = line.split(";");
|
||||
let [k, v] = pair.split("=");
|
||||
k = k.trim(); v = v.trim();
|
||||
if (names.includes(k)) return new Cookie({ name: k, value: v, domain: "www.yamibo.com" });
|
||||
}).filter(Boolean);
|
||||
|
||||
// 3. 验证并保存
|
||||
if (cookies.length !== names.length) {
|
||||
throw "登录未返回完整 Cookie,实际:" + cookies.map(c => c.name).join(",");
|
||||
}
|
||||
Network.setCookies("https://www.yamibo.com", cookies);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
Network.deleteCookies("https://www.yamibo.com");
|
||||
},
|
||||
|
||||
registerWebsite: "https://www.yamibo.com/user/signup"
|
||||
}
|
||||
|
||||
|
||||
static category_types = {
|
||||
"全部作品": "manga/list@a@?",
|
||||
"原创": "manga/list?q=4@a@&",
|
||||
"同人": "manga/list?q=6@a@&",
|
||||
}
|
||||
|
||||
static article_types = {
|
||||
"翻页漫画": "search/type?type=3&tag=@b@翻页漫画",
|
||||
"条漫": "search/type?type=3&tag=@b@条漫",
|
||||
"四格": "search/type?type=3&tag=@b@四格",
|
||||
"绘本": "search/type?type=3&tag=@b@绘本",
|
||||
"杂志": "search/type?type=3&tag=@b@杂志",
|
||||
"合志": "search/type?type=3&tag=@b@合志",
|
||||
}
|
||||
|
||||
static relate_types = {
|
||||
"编辑推荐": "manga/rcmds?type=3012@c@&",
|
||||
"最近更新": "manga/latest@c@?",
|
||||
"原创推荐": "manga/rcmds?type=3014@c@&",
|
||||
"同人推荐": "manga/rcmds?type=3015@c@&",
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// explore page list
|
||||
explore = [
|
||||
{
|
||||
title: "百合会",
|
||||
type: "singlePageWithMultiPart",
|
||||
load: async (page) => {
|
||||
// 1. 拿到 HTML
|
||||
let res = await Network.get("https://www.yamibo.com/site/manga");
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
// 2. 解析文档
|
||||
let doc = new HtmlDocument(res.body);
|
||||
|
||||
// 3. 通用解析单元函数
|
||||
function parseItem(el) {
|
||||
let a = el.querySelector(".media-img") || el.querySelector("a.media-img");
|
||||
let href = a.attributes.href;
|
||||
let id = href.match(/\/manga\/(\d+)/)[1];
|
||||
// 从 style 中提取 url
|
||||
let style = a.attributes.style || "";
|
||||
let cover = `https://www.yamibo.com/coverm/000/000/${id}.jpg`;
|
||||
let title = el.querySelector("h3 a").text.trim();
|
||||
return new Comic({ id, title, cover });
|
||||
}
|
||||
|
||||
// 4. 抓「编辑推荐」
|
||||
let editor = [];
|
||||
let editorEls = doc.querySelectorAll(".recommend-list .media-cell.horizontal");
|
||||
for (let el of editorEls) {
|
||||
editor.push(parseItem(el));
|
||||
}
|
||||
|
||||
// 5. 抓「最近更新」
|
||||
let latest = [];
|
||||
// 找到标题元素,再拿其后面的 <ul> 下的 .media-cell.vertical
|
||||
let latestTitle = doc.querySelectorAll("h2.module-title")
|
||||
.find(e => e.text.includes("最近更新"));
|
||||
if (latestTitle) {
|
||||
let ul = latestTitle.nextElementSibling;
|
||||
if (ul) {
|
||||
let items = ul.querySelectorAll(".media-cell.vertical");
|
||||
for (let el of items) latest.push(parseItem(el));
|
||||
}
|
||||
}
|
||||
|
||||
// 原创推荐
|
||||
let original = [];
|
||||
let originalTitle = doc.querySelectorAll("h2.module-title")
|
||||
.find(e => e.text.includes("原创推荐"));
|
||||
if (originalTitle) {
|
||||
let ul = originalTitle.nextElementSibling;
|
||||
if (ul) {
|
||||
let items = ul.querySelectorAll(".media-cell.vertical");
|
||||
for (let el of items) original.push(parseItem(el));
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 抓「同人推荐」
|
||||
let fan = [];
|
||||
let fanTitle = doc.querySelectorAll("h2.module-title")
|
||||
.find(e => e.text.includes("同人推荐"));
|
||||
if (fanTitle) {
|
||||
let ul = fanTitle.nextElementSibling;
|
||||
if (ul) {
|
||||
let items = ul.querySelectorAll(".media-cell.vertical");
|
||||
for (let el of items) fan.push(parseItem(el));
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 清理并返回
|
||||
doc.dispose();
|
||||
return {
|
||||
"编辑推荐": editor,
|
||||
"最近更新": latest,
|
||||
"原创推荐": original,
|
||||
"同人推荐": fan
|
||||
};
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// categories
|
||||
category = {
|
||||
/// title of the category page, used to identify the page, it should be unique
|
||||
title: "百合会",
|
||||
parts: [
|
||||
{
|
||||
name: "分类",
|
||||
type: "fixed",
|
||||
categories: Object.keys(Baihehui.category_types),
|
||||
itemType: "category",
|
||||
categoryParams: Object.values(Baihehui.category_types),
|
||||
},
|
||||
{
|
||||
name: "作品类型(需要登陆)",
|
||||
type: "fixed",
|
||||
categories: Object.keys(Baihehui.article_types),
|
||||
itemType: "category",
|
||||
categoryParams: Object.values(Baihehui.article_types),
|
||||
},
|
||||
{
|
||||
name: "更多推荐",
|
||||
type: "fixed",
|
||||
categories: Object.keys(Baihehui.relate_types),
|
||||
itemType: "category",
|
||||
categoryParams: Object.values(Baihehui.relate_types),
|
||||
},
|
||||
],
|
||||
// enable ranking page
|
||||
enableRankingPage: false,
|
||||
}
|
||||
|
||||
/// category comic loading related
|
||||
categoryComics = {
|
||||
load: async (category, params, options, page) => {
|
||||
let param = params.split('@')[0];
|
||||
let type = params.split('@')[1];
|
||||
let type_options = params.split('@')[2];
|
||||
let url = ""
|
||||
if (type == "b") {
|
||||
url = `${this.baseUrl}/${param}${encodeURIComponent(type_options)}&sort=updated_at`;
|
||||
url += `&page=${page}&per-page=50`;
|
||||
} else {
|
||||
url = `${this.baseUrl}/${param}${type_options}sort=updated_at`;
|
||||
url += `&page=${page}&per-page=50`;
|
||||
}
|
||||
|
||||
// 发起请求
|
||||
let res = await Network.get(url, {
|
||||
headers: { "User-Agent": "Mozilla/5.0" }
|
||||
});
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
|
||||
// 解析 HTML
|
||||
let document = new HtmlDocument(res.body);
|
||||
|
||||
// 获取最大页数
|
||||
let lastPageElement = document.querySelector('li.last > a');
|
||||
let maxPage = lastPageElement ? parseInt(lastPageElement.attributes['data-page']) + 1 : 1;
|
||||
|
||||
|
||||
// 分类解析、
|
||||
if (type == "a") {
|
||||
let mangaList = [];
|
||||
// 获取所有漫画行
|
||||
let rows = document.querySelectorAll('tr[data-key]');
|
||||
|
||||
rows.forEach(row => {
|
||||
// 提取信息
|
||||
let href = row.querySelector('a').attributes['href'];
|
||||
// 提取最后的数字作为 id
|
||||
let rawId = href.match(/\/manga\/(\d+)$/)[1];
|
||||
|
||||
// 补零处理 - 确保id是3位数
|
||||
let id = rawId.padStart(3, '0');
|
||||
let title = row.querySelector('a').text;
|
||||
let author = row.querySelectorAll('td')[2].text;
|
||||
|
||||
// 获取标签
|
||||
let tags = [
|
||||
row.querySelectorAll('td')[4].text, // 作品分类(原创/同人)
|
||||
row.querySelectorAll('td')[5].text // 连载状态
|
||||
];
|
||||
|
||||
// 获取更新时间作为描述
|
||||
let updateTime = row.querySelectorAll('td')[8].text;
|
||||
|
||||
// 构建漫画对象
|
||||
let manga = {
|
||||
id: id,
|
||||
title: title,
|
||||
cover: `https://www.yamibo.com/coverm/000/000/${id}.jpg`, // 默认封面
|
||||
tags: tags,
|
||||
description: `更新于: ${updateTime}`
|
||||
};
|
||||
|
||||
mangaList.push(manga);
|
||||
});
|
||||
|
||||
return {
|
||||
comics: mangaList,
|
||||
maxPage: maxPage // 从分页信息可以看出总共5页
|
||||
};
|
||||
} else if (type == "b") {
|
||||
let mangaList = [];
|
||||
// 获取所有漫画行
|
||||
let rows = document.querySelectorAll('tr[data-key]');
|
||||
rows.forEach(row => {
|
||||
// 提取信息
|
||||
let href = row.querySelector('a').attributes['href'];
|
||||
// 提取最后的数字作为 id
|
||||
let rawId = href.match(/\/manga\/(\d+)$/)[1];
|
||||
// 补零处理 - 确保id是3位数
|
||||
let id = rawId.padStart(3, '0');
|
||||
let title = row.querySelector('a').text;
|
||||
let author = row.querySelectorAll('td')[2].text;
|
||||
|
||||
// 获取标签
|
||||
let tags = [
|
||||
row.querySelectorAll('td')[3].text.replace(/\[|\]/g, ''), // 作品分类 (去掉方括号)
|
||||
row.querySelectorAll('td')[4].text // 连载状态
|
||||
];
|
||||
|
||||
// 获取更新时间作为描述
|
||||
let updateTime = row.querySelectorAll('td')[6].text;
|
||||
|
||||
// 构建封面 URL
|
||||
let cover = `https://www.yamibo.com/coverm/000/000/${id}.jpg`;
|
||||
|
||||
// 构建漫画对象
|
||||
let manga = {
|
||||
id: id,
|
||||
title: title,
|
||||
cover: cover, // 使用有效封面或默认封面
|
||||
tags: tags,
|
||||
description: `${updateTime}`
|
||||
};
|
||||
|
||||
mangaList.push(manga);
|
||||
});
|
||||
|
||||
return {
|
||||
comics: mangaList,
|
||||
maxPage: maxPage // 从分页信息可以看出总共8页
|
||||
};
|
||||
} else {
|
||||
let mangaList = [];
|
||||
// 获取所有漫画行
|
||||
let rows = document.querySelectorAll('tr[data-key]');
|
||||
rows.forEach(row => {
|
||||
// 提取信息
|
||||
let href = row.querySelector('a').attributes['href'];
|
||||
// 提取最后的数字作为 id
|
||||
let rawId = href.match(/\/manga\/(\d+)$/)[1];
|
||||
// 补零处理 - 确保id是3位数
|
||||
let id = rawId.padStart(3, '0');
|
||||
let title = row.querySelector('a').text;
|
||||
|
||||
// 获取更新时间作为描述
|
||||
let updateTime = row.querySelector('td:last-child').text.trim();
|
||||
|
||||
// 构建封面 URL
|
||||
let cover = `https://www.yamibo.com/coverm/000/000/${id}.jpg`;
|
||||
|
||||
// 构建漫画对象
|
||||
let manga = {
|
||||
id: id,
|
||||
title: title,
|
||||
cover: cover, // 使用有效封面或默认封面
|
||||
tags: [],
|
||||
description: `更新于: ${updateTime}`
|
||||
};
|
||||
|
||||
mangaList.push(manga);
|
||||
});
|
||||
|
||||
return {
|
||||
comics: mangaList,
|
||||
maxPage: maxPage // 从分页信息可以看出总共8页
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// search related
|
||||
search = {
|
||||
/**
|
||||
* load search result
|
||||
* @param keyword {string}
|
||||
* @param options {string[]} - options from optionList
|
||||
* @param page {number}
|
||||
* @returns {Promise<{comics: Comic[], maxPage: number}>}
|
||||
*/
|
||||
load: async (keyword, options, page) => {
|
||||
let url = `https://www.yamibo.com/search/manga?SearchForm%5Bkeyword%5D=${encodeURIComponent(keyword)}&page=${page}`;
|
||||
let res = await Network.get(url, {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
let document = new HtmlDocument(res.body);
|
||||
// 获取最大页数
|
||||
let lastPageElement = document.querySelector('li.last > a');
|
||||
let maxPage = lastPageElement ? parseInt(lastPageElement.attributes['data-page']) + 1 : 1;
|
||||
// 提取漫画列表
|
||||
let mangaList = [];
|
||||
// 获取所有漫画行
|
||||
let rows = document.querySelectorAll('tr[data-key]');
|
||||
rows.forEach(row => {
|
||||
// 提取信息
|
||||
let href = row.querySelector('a').attributes['href'];
|
||||
// 提取最后的数字作为 id
|
||||
let rawId = href.match(/\/manga\/(\d+)$/)[1];
|
||||
// 补零处理 - 确保id是3位数
|
||||
let id = rawId.padStart(3, '0');
|
||||
let title = row.querySelector('a').text;
|
||||
|
||||
// 获取更新时间作为描述
|
||||
let updateTime = row.querySelector('td:last-child').text.trim();
|
||||
|
||||
// 构建封面 URL
|
||||
let cover = `https://www.yamibo.com/coverm/000/000/${id}.jpg`;
|
||||
|
||||
// 构建漫画对象
|
||||
let manga = {
|
||||
id: id,
|
||||
title: title,
|
||||
cover: cover, // 使用有效封面或默认封面
|
||||
tags: [],
|
||||
description: `更新于: ${updateTime}`
|
||||
};
|
||||
|
||||
mangaList.push(manga);
|
||||
});
|
||||
|
||||
return {
|
||||
comics: mangaList,
|
||||
maxPage: maxPage // 从分页信息可以看出总共8页
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* load search result with next page token.
|
||||
* The field will be ignored if `load` function is implemented.
|
||||
* @param keyword {string}
|
||||
* @param options {(string)[]} - options from optionList
|
||||
* @param next {string | null}
|
||||
* @returns {Promise<{comics: Comic[], maxPage: number}>}
|
||||
*/
|
||||
loadNext: async (keyword, options, next) => {
|
||||
|
||||
},
|
||||
|
||||
// provide options for search
|
||||
optionList: [],
|
||||
|
||||
// enable tags suggestions
|
||||
enableTagsSuggestions: false,
|
||||
}
|
||||
|
||||
/// single comic related
|
||||
comic = {
|
||||
/**
|
||||
* load comic info
|
||||
* @param id {string}
|
||||
* @returns {Promise<ComicDetails>}
|
||||
*/
|
||||
loadInfo: async (id) => {
|
||||
let res = await Network.get(`${this.baseUrl}/manga/${id}`);
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
let document = new HtmlDocument(res.body);
|
||||
|
||||
// 提取漫画标题
|
||||
let title = document.querySelector("h3.col-md-12").text.trim();
|
||||
|
||||
// 提取封面图片
|
||||
let cover = "https://www.yamibo.com/coverm/000/000/" + id + ".jpg";
|
||||
|
||||
// 提取作者信息
|
||||
let author = "";
|
||||
document.querySelectorAll("p").forEach(p => {
|
||||
if (p.text.includes("作者:")) {
|
||||
author = p.text.replace("作者:", "").trim();
|
||||
}
|
||||
});
|
||||
|
||||
// 提取标签
|
||||
let tags = [];
|
||||
document.querySelectorAll("a.label.label-ntype").forEach(tag => {
|
||||
tags.push(tag.text.trim());
|
||||
});
|
||||
|
||||
// 提取更新时间
|
||||
let updateTime = "";
|
||||
document.querySelectorAll("p").forEach(p => {
|
||||
if (p.text.includes("更新时间:")) {
|
||||
updateTime = p.text.replace("更新时间:", "").trim();
|
||||
}
|
||||
});
|
||||
|
||||
// 提取简介
|
||||
//let description = document.querySelector("div.panel-body > div.panel-collapse > div.panel-body").text.trim();
|
||||
let description = "";
|
||||
|
||||
// 提取章节信息
|
||||
let chapters = new Map();
|
||||
document.querySelectorAll("div[data-key]").forEach(chapter => {
|
||||
let chapterKey = chapter.attributes['data-key']; // 获取 data-key 值
|
||||
let chapterTitle = chapter.querySelector("a").text.trim(); // 获取章节标题
|
||||
chapters.set(chapterKey, chapterTitle); // 将 data-key 和章节标题存入 Map
|
||||
});
|
||||
|
||||
return {
|
||||
title: title,
|
||||
cover: cover,
|
||||
description: description,
|
||||
tags: {
|
||||
"作者": [author],
|
||||
"更新": [updateTime],
|
||||
"标签": tags
|
||||
},
|
||||
chapters: chapters
|
||||
};
|
||||
|
||||
},
|
||||
loadComments: async (comicId, subId, page, replyTo) => {
|
||||
let url = `${this.baseUrl}/manga/${comicId}?dp-1-page=${page}`;
|
||||
let res = await Network.get(url, {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
let document = new HtmlDocument(res.body);
|
||||
|
||||
// 提取评论总数
|
||||
let totalCommentsMatch = document.querySelector("div.panel-body").text.match(/共(\d+)篇/);
|
||||
let totalComments = totalCommentsMatch ? parseInt(totalCommentsMatch[1]) : 0;
|
||||
|
||||
// 提取评论列表
|
||||
let comments = [];
|
||||
document.querySelectorAll("div.post.row").forEach(post => {
|
||||
let userName = post.querySelector("span.cmt-username > a").text.trim();
|
||||
let avatar = "https://www.yamibo.com/" + post.querySelector("a > img.cmt-avatar").attributes['src'];
|
||||
let content = post.querySelector("div.row > p").text.trim();
|
||||
let time = post.querySelector("span.description").text.replace("在 ", "").trim();
|
||||
let replyCountMatch = post.querySelector("a.btn.btn-sm").text.match(/(\d+) 条回复/);
|
||||
let replyCount = replyCountMatch ? parseInt(replyCountMatch[1]) : 0;
|
||||
let id = post.querySelector("button.btn_reply").attributes['pid'];
|
||||
|
||||
comments.push({
|
||||
userName: userName,
|
||||
avatar: avatar,
|
||||
content: content,
|
||||
time: time,
|
||||
replyCount: replyCount,
|
||||
id: id
|
||||
});
|
||||
});
|
||||
|
||||
// 计算最大页数
|
||||
let maxPageElement = document.querySelector("li.last > a");
|
||||
let maxPage = maxPageElement ? parseInt(maxPageElement.attributes['data-page']) + 1 : 1;
|
||||
|
||||
return {
|
||||
comments: comments,
|
||||
totalComments: totalComments,
|
||||
maxPage: maxPage
|
||||
};
|
||||
},
|
||||
|
||||
loadEp: async (comicId, epId) => {
|
||||
let baseUrl = `https://www.yamibo.com/manga/view-chapter?id=${epId}`;
|
||||
let res = await Network.get(`${baseUrl}&page=1`, {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw `Invalid status code: ${res.status}`;
|
||||
}
|
||||
|
||||
let document = new HtmlDocument(res.body);
|
||||
|
||||
// 提取最大页数
|
||||
let lastPageElement = document.querySelector("li.last > a");
|
||||
let maxPage = lastPageElement ? parseInt(lastPageElement.attributes['data-page']) + 1 : 1;
|
||||
|
||||
let images = [];
|
||||
|
||||
// 循环抓取所有页面的图片
|
||||
for (let page = 1; page <= maxPage; page++) {
|
||||
let pageUrl = `${baseUrl}&page=${page}`;
|
||||
let pageRes = await Network.get(pageUrl, {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
|
||||
}
|
||||
});
|
||||
|
||||
if (pageRes.status !== 200) {
|
||||
throw `Invalid status code on page ${page}: ${pageRes.status}`;
|
||||
}
|
||||
|
||||
let pageDocument = new HtmlDocument(pageRes.body);
|
||||
|
||||
// 提取图片 URL
|
||||
let imageElement = pageDocument.querySelector("img#imgPic");
|
||||
if (!imageElement) {
|
||||
throw `Image not found on page ${page}.`;
|
||||
}
|
||||
let imageUrl = imageElement.attributes['src'];
|
||||
images.push(imageUrl);
|
||||
}
|
||||
|
||||
return {
|
||||
images: images, // 所有页面的图片 URL
|
||||
maxPage: maxPage
|
||||
};
|
||||
},
|
||||
|
||||
// enable tags translate
|
||||
enableTagsTranslate: false,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user