{"record":{"id":"61cc4b04c4f10da8","repo":"DIYgod/RSSHub","slug":"year-issue","errorCode":null,"errorMessage":"无法获取最新的 year 和 issue","messagePattern":"无法获取最新的 year 和 issue","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/ajcass/shxyj.ts","lineNumber":38,"sourceCode":"    name: '社会学研究',\n    maintainers: ['CNYoki'],\n    handler,\n};\n\nasync function handler(ctx) {\n    let { year, issue } = ctx.req.param();\n\n    if (!year) {\n        const response = await got('https://shxyj.ajcass.com/');\n        const $ = load(response.body);\n        const latestIssueText = $('p.hod.pop').first().text();\n\n        const match = latestIssueText.match(/(\\d{4}) Vol\\.(\\d+):/);\n        if (match) {\n            year = match[1];\n            issue = match[2];\n        } else {\n            throw new Error('无法获取最新的 year 和 issue');\n        }\n    }\n\n    const url = `https://shxyj.ajcass.com/Magazine/?Year=${year}&Issue=${issue}`;\n    const response = await got(url);\n    const $ = load(response.body);\n\n    const items = $('#tab tr')\n        .toArray()\n        .map((item) => {\n            const $item = $(item);\n            const articleTitle = $item.find('a').first().text().trim();\n            const articleLink = $item.find('a').first().attr('href');\n            const summary = $item.find('li').eq(1).text().replace('[摘要]', '').trim();\n            const authors = $item.find('li').eq(2).text().replace('作者：', '').trim();\n            const pubDate = parseDate(`${year}-${Number.parseInt(issue) * 2}`);\n\n            if (articleTitle && articleLink) {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/ajcass/shxyj.ts#L20-L56","documentation":"社会学杂志 (shxyj.ajcass.com) route scrapes the homepage to discover the latest year/issue from a `p.hod.pop` element via the regex /(\\d{4}) Vol\\.(\\d+):/. If neither the selector nor the regex matches (markup changed, or no issue line present), it throws a generic `Error('无法获取最新的 year 和 issue')`.","triggerScenarios":"Calling /ajcass/shxyj without explicit year/issue params when the homepage markup has changed — selector `p.hod.pop` absent, or text no longer matches 'YYYY Vol.N:'.","commonSituations":"Site redesign renamed the CSS class; the homepage is temporarily showing a special-issue banner without the expected text format; the journal changed its issue-naming scheme.","solutions":["Supply explicit year and issue in the path so the homepage scrape is bypassed entirely.","If you maintain the route, inspect https://shxyj.ajcass.com/ and update the selector ('p.hod.pop') and/or the regex.","Retry later for transient homepage changes (e.g. a holiday banner)."],"exampleFix":"// before — relies on homepage scrape, throws when markup changes\nif (match) { year = match[1]; issue = match[2]; }\nelse { throw new Error('无法获取最新的 year 和 issue'); }\n// after — tolerate format drift by trying alternate selectors\nconst m = latestIssueText.match(/(\\d{4})\\s*Vol\\.?\\s*(\\d+)/) ?? $('a:contains(\"Vol\")').first().text().match(/(\\d{4})\\/?(\\d+)/);\nif (!m) throw new Error('无法获取最新的 year 和 issue');\n// OR call with explicit params: /ajcass/shxyj/2024/5","handlingStrategy":"fallback","validationCode":"// If you can supply explicit values, bypass the homepage scrape entirely:\nfunction explicitShxyjArgs(year, issue) {\n  return /^\\d{4}$/.test(String(year)) && /^\\d+$/.test(String(issue));\n}","typeGuard":"function isExplicitIssue(year, issue): boolean {\n  return /^\\d{4}$/.test(String(year ?? '')) && /^\\d+$/.test(String(issue ?? ''));\n}","tryCatchPattern":"let year = ctxYear, issue = ctxIssue;\nif (!year || !issue) {\n  try {\n    const $ = load((await got('https://shxyj.ajcass.com/')).body);\n    const m = $('p.hod.pop').first().text().match(/(\\d{4})\\s*Vol\\.?\\s*(\\d+)/);\n    if (!m) throw new Error('无法获取最新的 year 和 issue');\n    [year, issue] = [m[1], m[2]];\n  } catch (e) {\n    // fallback: try an alternate selector or a known-good recent issue\n    const m2 = $('a:contains(\"Vol\")').first().text().match(/(\\d{4})/);\n    if (!m2) throw e;\n    year = m2[1]; issue = '1';\n  }\n}","preventionTips":["Pass explicit year/issue in the path when you know them — it bypasses the fragile homepage scrape.","Treat a regex/selector failure as upstream markup drift and update the route.","Add a fallback selector before throwing so a single class rename doesn't break discovery."],"tags":["upstream-dependent","scraping","selector","regex","rsshub","error-class-mismatch"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}