{"record":{"id":"41e95f68e7eb1304","repo":"DIYgod/RSSHub","slug":"id-41e95f","errorCode":null,"errorMessage":"无法解析页面数据，请检查漫画 ID 是否正确或页面结构是否变动","messagePattern":"无法解析页面数据，请检查漫画 ID 是否正确或页面结构是否变动","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/comic-fuz/manga.ts","lineNumber":45,"sourceCode":"    maintainers: ['xiaobailoves'],\n\n    handler: async (ctx) => {\n        const { id } = ctx.req.param();\n        const baseUrl = 'https://comic-fuz.com';\n        const openUrl = `${baseUrl}/manga/${id}`;\n        const imgUrl = 'https://img.comic-fuz.com';\n\n        const response = await ofetch(openUrl, {\n            headers: {\n                'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8',\n            },\n        });\n\n        const $ = load(response);\n        const nextDataText = $('#__NEXT_DATA__').text();\n\n        if (!nextDataText) {\n            throw new Error('无法解析页面数据，请检查漫画 ID 是否正确或页面结构是否变动');\n        }\n\n        const nextData = JSON.parse(nextDataText);\n        const pageProps = nextData.props?.pageProps;\n\n        if (!pageProps) {\n            throw new Error('无法解析页面 Props 数据');\n        }\n\n        const mangaTitle = $('title').text();\n        const mangaAuthor = pageProps.authorships?.map((item: any) => item.author?.authorName).join(', ') || '';\n        const mangaDescription = pageProps.manga?.longDescription || '';\n\n        const chapterGroups = pageProps.chapters || [];\n\n        const allChapters = chapterGroups.flatMap((group: any) => group.chapters || []);\n\n        const items = allChapters.map((chapter: any) => {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/comic-fuz/manga.ts#L27-L63","documentation":"This error is thrown when the comic-fuz route fetches a manga page but the Next.js __NEXT_DATA__ script tag is empty or absent. RSSHub relies on this embedded JSON blob as its sole data source for title, author, chapters, and descriptions. When it is missing, the scraper cannot proceed because there is no alternative data path.","triggerScenarios":"The ofetch call to the comic-fuz manga URL returns HTML, but $('#__NEXT_DATA__').text() evaluates to an empty string. This happens when the server returns a 404/error page, a CAPTCHA interstitial, or a redesigned page that no longer embeds Next.js hydration data.","commonSituations":"Anti-scraping middleware returns a challenge page instead of content; the manga ID in the route path does not correspond to a valid manga (resulting in a Next.js error page that still has the script tag but empty); the site undergoes a frontend migration that removes or renames the __NEXT_DATA__ element.","solutions":["Open the comic-fuz manga URL directly in a browser to confirm the ID is valid and the page loads normally.","Inspect the actual HTML returned by ofetch — log or dump response to check whether a CAPTCHA or error page is being served.","Add a realistic User-Agent and Accept headers to the ofetch call to reduce anti-bot blocking.","If the site redesigned, locate the new data source (check for a JSON API endpoint or a different embedded script tag) and update the selector.","Report the broken route to RSSHub maintainers if the page structure has permanently changed."],"exampleFix":"// before\nconst response = await ofetch(openUrl, {\n    headers: {\n        'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8',\n    },\n});\n\n// after — add a realistic UA and log the response for diagnosis\nconst response = await ofetch(openUrl, {\n    headers: {\n        'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8',\n        'User-Agent': config.trueUA,\n    },\n});\nif (!response.includes('__NEXT_DATA__')) {\n    throw new Error('comic-fuz page did not contain __NEXT_DATA__; possible anti-bot block or site redesign');\n}","handlingStrategy":"validation","validationCode":"// Before calling ofetch, validate the manga ID format\nconst id = ctx.req.param('id');\nif (!id || !/^\\d+$/.test(id)) {\n    throw new InvalidParameterError('Manga ID must be numeric');\n}\n// After fetching, validate HTML contains expected data\nif (!response.includes('__NEXT_DATA__')) {\n    throw new Error('Page does not contain Next.js data; possible anti-bot block');\n}","typeGuard":"function hasNextData(html: string): boolean {\n    return html.includes('id=\"__NEXT_DATA__\"') && html.match(/id=\"__NEXT_DATA__\"[^>]*>[^<]+/) !== null;\n}","tryCatchPattern":"try {\n    const response = await ofetch(openUrl, { headers: { 'User-Agent': config.trueUA } });\n    const $ = load(response);\n    const nextDataText = $('#__NEXT_DATA__').text();\n    if (!nextDataText) throw new Error('No __NEXT_DATA__');\n} catch (e) {\n    logger.error(`comic-fuz fetch failed for ID ${id}: ${(e as Error).message}`);\n    throw e;\n}","preventionTips":["Always send a realistic User-Agent header when scraping Next.js sites.","Use cache.tryGet to reduce request frequency and avoid triggering anti-bot measures.","Validate the manga ID format before making the request.","Monitor for site structure changes by checking the route periodically."],"tags":["scraping","nextjs","parsing","comic-fuz","anti-bot"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}