{"record":{"id":"8a36f57a0f9a7083","repo":"DIYgod/RSSHub","slug":"waphomerenderdata","errorCode":null,"errorMessage":"WapHomeRenderData 数据未找到","messagePattern":"WapHomeRenderData 数据未找到","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/sohu/mobile.ts","lineNumber":42,"sourceCode":"        {\n            source: ['m.sohu.com/limit'],\n            target: '/mobile',\n        },\n    ],\n    name: '首页新闻',\n    maintainers: ['asqwe1'],\n    handler,\n    description: '订阅手机搜狐网的首页新闻',\n};\n\nasync function handler() {\n    const response = await ofetch('https://m.sohu.com/limit');\n    // 从HTML中提取JSON数据\n    const $ = load(response);\n    const jsonScript = $('script:contains(\"WapHomeRenderData\")').text();\n    const jsonMatch = jsonScript?.match(/window\\.WapHomeRenderData\\s*=\\s*(\\{.*\\})/s);\n    if (!jsonMatch?.[1]) {\n        throw new Error('WapHomeRenderData 数据未找到');\n    }\n    const renderData = JSON.parse(jsonMatch[1]);\n    const list = extractPlateBlockNewsLists(renderData)\n        .filter((item) => item.id && item.url?.startsWith('//'))\n        .map((item) => ({\n            title: item.title,\n            link: new URL(item.url.split('?', 1)[0], 'https://m.sohu.com').href,\n        }));\n    const items = await Promise.all(\n        list.map((item) =>\n            cache.tryGet(item.link, async () => {\n                try {\n                    const detailResp = await ofetch(item.link);\n                    const $d = load(detailResp);\n\n                    let description = '';\n                    let pubDate: string | undefined = '';\n                    if (item.link.includes('/xtopic/')) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/sohu/mobile.ts#L24-L60","documentation":"Thrown as a plain Error when the Sohu mobile homepage HTML does not contain the expected 'WapHomeRenderData' JavaScript variable. The handler fetches https://m.sohu.com/limit, loads it with cheerio, finds a <script> tag containing 'WapHomeRenderData', and regex-matches /window\\.WapHomeRenderData\\s*=\\s*(\\{.*\\})/s. If no match is found (the script tag doesn't exist, the variable was renamed, or the page returned an anti-bot challenge), the error is thrown. This is a fragile HTML-scraping pattern that breaks when the page structure changes.","triggerScenarios":"Sohu redesigned their mobile homepage and renamed or restructured the WapHomeRenderData variable; the /limit path now serves a different page template; an anti-bot/anti-crawler interstitial (e.g. a CAPTCHA or verification page) is served instead of the real homepage HTML; or the page loaded partially and the script tag was not in the response body.","commonSituations":"Sohu pushes a frontend redesign that renames the data injection variable; the RSSHub instance IP is flagged and gets a challenge page; or Sohu A/B tests different page templates and only some contain the variable.","solutions":["Fetch https://m.sohu.com/limit in a browser with devtools open and search the page source for 'WapHomeRenderData' to confirm it still exists.","If the variable was renamed, update the cheerio selector and regex pattern in the handler to match the new variable name.","If anti-bot is the cause, set config.trueUA to a realistic browser User-Agent or route through a residential proxy.","If the page structure fundamentally changed, rewrite the handler to use Sohu's API endpoints (check network tab for JSON responses) instead of HTML scraping."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const jsonScript = $('script:contains(\"WapHomeRenderData\")').text();\nconst jsonMatch = jsonScript?.match(/window\\.WapHomeRenderData\\s*=\\s*(\\{.*\\})/s);\nif (!jsonMatch?.[1]) {\n    throw new Error('WapHomeRenderData not found — the Sohu page structure may have changed');\n}","typeGuard":"function isRenderDataObject(data: unknown): data is Record<string, unknown> {\n    return data !== null && typeof data === 'object' && !Array.isArray(data);\n}","tryCatchPattern":"try {\n    const renderData = JSON.parse(jsonMatch[1]);\n    if (!isRenderDataObject(renderData)) throw new Error('Invalid render data');\n} catch (e) {\n    logger.error('Failed to parse Sohu WapHomeRenderData', e);\n    throw new Error('WapHomeRenderData 数据未找到');\n}","preventionTips":["Prefer official API endpoints over HTML scraping whenever possible — check the network tab for JSON responses.","Make scraping patterns resilient by logging the full page HTML when the regex fails, so you can quickly identify structural changes.","Add HTML structure assertions and alerting so maintainers are notified when the selector breaks.","Consider using the page's API directly if Sohu exposes one behind the same /limit URL."],"tags":["scraping","upstream","anti-crawler","fragile-selector","sohu","regex"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}