修复微信图书问题
This commit is contained in:
parent
7c00f32271
commit
961ecf693a
@ -175,7 +175,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
// 页面状态跟踪
|
// 页面状态跟踪
|
||||||
let animationInProgress = false;
|
let animationInProgress = false;
|
||||||
|
// 添加状态变量
|
||||||
|
let isLoading = false;
|
||||||
|
let contentReady = false;
|
||||||
|
|
||||||
// 根据当前页面动态确定容器配置
|
// 根据当前页面动态确定容器配置
|
||||||
const containers = ['main']; // 主容器始终存在
|
const containers = ['main']; // 主容器始终存在
|
||||||
@ -461,9 +463,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
hideLoadingSpinner(spinner);
|
hideLoadingSpinner(spinner);
|
||||||
|
|
||||||
// 重置状态
|
// 重置状态
|
||||||
|
animationInProgress = false;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
contentReady = false;
|
contentReady = false;
|
||||||
animationInProgress = false;
|
|
||||||
|
|
||||||
// 检查是否可以使用备用容器
|
// 检查是否可以使用备用容器
|
||||||
const mainContainer = document.querySelector('main');
|
const mainContainer = document.querySelector('main');
|
||||||
|
@ -62,111 +62,77 @@ async function fetchWithTimeout(url: string, options: RequestInit, timeoutMs: nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从脚本中提取书籍数据(简单直接的方法)
|
// 从HTML页面中提取书籍数据
|
||||||
function extractBooksFromScript(html: string): { title: string; author: string; cover: string; }[] | null {
|
function extractBooksFromScript(html: string): { title: string; author: string; cover: string; }[] | null {
|
||||||
try {
|
try {
|
||||||
// 1. 提取函数参数列表,用于解析参数引用
|
// 使用Cheerio解析HTML
|
||||||
const paramsMatch = html.match(/\(function\(([^)]*)\)/);
|
const $ = load(html);
|
||||||
if (!paramsMatch) {
|
|
||||||
console.error('未找到函数参数列表');
|
// 1. 从HTML结构中提取书名和作者信息(保证准确性)
|
||||||
|
const htmlBooks = new Map<string, string>(); // 以书名为键,作者为值
|
||||||
|
const orderedTitles: string[] = []; // 保持HTML中的顺序
|
||||||
|
|
||||||
|
$('.booklist_books li').each((index, element) => {
|
||||||
|
const title = $(element).find('.booklist_book_title').text().trim();
|
||||||
|
const author = $(element).find('.booklist_book_author').text().trim();
|
||||||
|
|
||||||
|
if (title && author) {
|
||||||
|
htmlBooks.set(title, author);
|
||||||
|
orderedTitles.push(title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (htmlBooks.size === 0) {
|
||||||
|
console.error('[WeRead] 无法从HTML中提取书籍信息');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = paramsMatch[1].split(',').map(p => p.trim());
|
// 2. 从脚本中提取封面URL
|
||||||
|
|
||||||
// 2. 提取bookEntities对象
|
|
||||||
const bookEntitiesMatch = html.match(/bookEntities:(\{.*?\}),bookIds/s);
|
const bookEntitiesMatch = html.match(/bookEntities:(\{.*?\}),bookIds/s);
|
||||||
if (!bookEntitiesMatch) {
|
if (!bookEntitiesMatch) {
|
||||||
console.error('未找到bookEntities数据');
|
console.error('[WeRead] 未找到bookEntities数据,无法获取书籍封面');
|
||||||
return null;
|
|
||||||
|
// 即使找不到封面URL,也可以返回标题和作者信息
|
||||||
|
const booksWithoutCovers = orderedTitles.map(title => ({
|
||||||
|
title,
|
||||||
|
author: htmlBooks.get(title) || '',
|
||||||
|
cover: ''
|
||||||
|
}));
|
||||||
|
|
||||||
|
return booksWithoutCovers;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 提取bookIds数组
|
// 从bookEntities中提取标题和封面URL的映射
|
||||||
const bookIdsMatch = html.match(/bookIds:\[(.*?)\]/s);
|
const coverMap = new Map<string, string>(); // 以标题为键,封面URL为值
|
||||||
if (!bookIdsMatch) {
|
const bookPattern = /"([^"]+)":\{.*?title:"([^"]+)",.*?cover:"([^"]+)".*?\}/g;
|
||||||
console.error('未找到bookIds数据');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bookIdsStr = bookIdsMatch[1];
|
|
||||||
const bookIds = bookIdsStr.split(',')
|
|
||||||
.map(id => id.trim().replace(/"/g, ''))
|
|
||||||
.filter(id => id && id !== '');
|
|
||||||
|
|
||||||
// 4. 创建参数到实际ID的映射
|
|
||||||
// 首先提取所有bookId参数引用
|
|
||||||
const bookIdParamPattern = /"([^"]+)":\{bookId:([^,]+),/g;
|
|
||||||
const paramToIdMap = new Map<string, string>();
|
|
||||||
let bookIdMatch;
|
|
||||||
|
|
||||||
while ((bookIdMatch = bookIdParamPattern.exec(bookEntitiesMatch[1])) !== null) {
|
|
||||||
const entityId = bookIdMatch[1]; // 如 "728774"
|
|
||||||
const paramRef = bookIdMatch[2]; // 如 "h"
|
|
||||||
|
|
||||||
if (paramRef.length === 1 && /[a-z]/.test(paramRef)) {
|
|
||||||
paramToIdMap.set(paramRef, entityId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 解析每本书的信息
|
|
||||||
const bookMap = new Map();
|
|
||||||
const bookPattern = /"([^"]+)":\{bookId:[^,]+,.*?author:([^,]+),.*?title:"([^"]+)",.*?cover:"([^"]+)"/g;
|
|
||||||
|
|
||||||
let match;
|
let match;
|
||||||
let bookCount = 0;
|
|
||||||
|
|
||||||
while ((match = bookPattern.exec(bookEntitiesMatch[1])) !== null) {
|
while ((match = bookPattern.exec(bookEntitiesMatch[1])) !== null) {
|
||||||
const bookId = match[1];
|
const title = match[2]; // 书名
|
||||||
const authorParam = match[2];
|
const cover = match[3].replace(/\\u002F/g, '/'); // 封面URL
|
||||||
const title = match[3];
|
coverMap.set(title, cover);
|
||||||
const cover = match[4].replace(/\\u002F/g, '/');
|
|
||||||
|
|
||||||
// 处理作者参数引用
|
|
||||||
let author = authorParam;
|
|
||||||
if (authorParam.length === 1 && /[a-z]/.test(authorParam)) {
|
|
||||||
const paramIndex = authorParam.charCodeAt(0) - 'a'.charCodeAt(0);
|
|
||||||
if (paramIndex >= 0 && paramIndex < params.length) {
|
|
||||||
author = params[paramIndex].replace(/"/g, '');
|
|
||||||
}
|
|
||||||
} else if (authorParam.startsWith('"') && authorParam.endsWith('"')) {
|
|
||||||
author = authorParam.substring(1, authorParam.length - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同时用实体ID和参数引用作为键存储书籍信息
|
// 3. 合并数据,按照HTML中的顺序
|
||||||
bookMap.set(bookId, { title, author, cover });
|
const finalBooks: { title: string; author: string; cover: string; }[] = [];
|
||||||
bookCount++;
|
|
||||||
|
// 遍历HTML中的书籍顺序
|
||||||
|
for (const title of orderedTitles) {
|
||||||
|
const author = htmlBooks.get(title) || '';
|
||||||
|
const cover = coverMap.get(title) || '';
|
||||||
|
|
||||||
|
finalBooks.push({ title, author, cover });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 按照bookIds的顺序返回书籍,使用参数映射
|
// 记录找不到封面的书籍数量
|
||||||
const orderedBooks = [];
|
const missingCovers = finalBooks.filter(book => !book.cover).length;
|
||||||
|
if (missingCovers > 0) {
|
||||||
for (const paramId of bookIds) {
|
console.warn(`[WeRead] 警告:有${missingCovers}/${finalBooks.length}本书未找到封面URL`);
|
||||||
// 如果是参数引用,使用映射查找实际ID
|
|
||||||
const actualId = paramToIdMap.get(paramId);
|
|
||||||
|
|
||||||
if (actualId) {
|
|
||||||
const book = bookMap.get(actualId);
|
|
||||||
if (book) {
|
|
||||||
orderedBooks.push(book);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试直接使用paramId查找
|
return finalBooks.length > 0 ? finalBooks : null;
|
||||||
const directBook = bookMap.get(paramId);
|
|
||||||
if (directBook) {
|
|
||||||
orderedBooks.push(directBook);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有找到任何书籍,返回所有书籍
|
|
||||||
if (orderedBooks.length === 0) {
|
|
||||||
return Array.from(bookMap.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
return orderedBooks;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('从脚本提取书籍数据时出错:', error);
|
console.error('[WeRead] 从HTML提取书籍数据时出错:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user