{"record":{"id":"f494c020a8b5cfd2","repo":"jackwener/OpenCLI","slug":"zhihu-download","errorCode":"zhihu download","errorMessage":"The Zhihu column article had no exportable content.","messagePattern":"The Zhihu column article had no exportable content\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/zhihu/download-helpers.js","lineNumber":119,"sourceCode":"            img.setAttribute('src', src);\n            if (!seen.has(src)) {\n                seen.add(src);\n                imageUrls.push(src);\n            }\n        }\n    });\n    return { contentHtml: root.innerHTML, imageUrls };\n}\n\nfunction requireArticle(raw) {\n    const data = unwrapEvaluateResult(raw);\n    if (!data || typeof data !== 'object' || Array.isArray(data)\n        || typeof data.title !== 'string' || typeof data.contentHtml !== 'string'\n        || !Array.isArray(data.imageUrls) || !data.imageUrls.every((url) => typeof url === 'string')) {\n        throw new CommandExecutionError('Zhihu column download returned malformed article fields');\n    }\n    if (!data.contentHtml.trim()) {\n        throw new EmptyResultError('zhihu download', 'The Zhihu column article had no exportable content.');\n    }\n    return data;\n}\n\nexport async function extractColumnArticle(page, target) {\n    await page.goto(target.url);\n    await page.wait(3);\n    const normalize = `(${normalizeContentImages.toString()})`;\n    const raw = await page.evaluate(`\n      (() => {\n        const content = document.querySelector('.Post-RichTextContainer, .RichText, .ArticleContent');\n        const normalized = ${normalize}(content?.innerHTML || '');\n        return {\n          title: document.querySelector('.Post-Title, h1.ContentItem-title, .ArticleTitle')?.textContent?.trim() || 'untitled',\n          author: document.querySelector('.AuthorInfo-name, .UserLink-link')?.textContent?.trim() || '',\n          publishTime: document.querySelector('.ContentItem-time, .Post-Time')?.textContent?.trim() || '',\n          ...normalized\n        };","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/zhihu/download-helpers.js#L101-L137","documentation":"In `zhihu download` for a column article, requireArticle throws EmptyResultError (code EMPTY_RESULT, exit 66 / EX_NOINPUT) when the extracted article's `contentHtml` is present and correctly typed but contains only whitespace. The article shell was parsed, but there is no exportable body content to convert/export.","triggerScenarios":"The column article body fails to render before extraction (lazy loading / JS not finished), the article is empty or deleted, or the content selector matches a container whose text is behind a 'read more'/paywall expansion that never opened.","commonSituations":"Download running before the article content mounts on a slow connection; members-only or deleted columns where the body is blank for the current viewer; the extraction grabbing an empty preview container instead of the full article body.","solutions":["Re-run after increasing the post-navigation wait (e.g. page.wait(3) or waiting for the article body selector) so content mounts.","Verify the article has visible content when opened in the browser — if blank there, the column is deleted/members-only.","Scroll or click any 'expand/read more' control before extraction so the full body renders.","If content exists in the browser but extraction still yields empty HTML, fix the content selector in the extraction script."],"exampleFix":"// before\nawait page.goto(target.url);\nconst article = requireArticle(await page.evaluate(extractScript));\n// after: wait for the body before extracting\nawait page.goto(target.url);\nawait page.wait(3); // or waitForSelector on the article body\nconst article = requireArticle(await page.evaluate(extractScript));","handlingStrategy":"validation","validationCode":"const data = await page.evaluate(extractScript);\nif (typeof data?.contentHtml === 'string' && !data.contentHtml.trim()) {\n  throw new Error('Article body empty — wait for content or check paywall/deletion');\n}","typeGuard":"function hasExportableContent(v) {\n  return typeof v?.contentHtml === 'string' && v.contentHtml.trim().length > 0;\n}","tryCatchPattern":"try {\n  const article = requireArticle(await page.evaluate(extractScript));\n} catch (e) {\n  if (e.code === 'EMPTY_RESULT') {\n    console.warn('Column article had no exportable content — retry after full page load');\n    return null;\n  }\n  throw e;\n}","preventionTips":["Wait for the article body (selector or fixed delay) after page.goto before extracting.","Scroll/expand 'read more' or members-only placeholders before extraction.","Check the article renders non-empty in a normal browser session to rule out deletion or access restrictions."],"tags":["zhihu","empty-result","lazy-loading","scraping"],"backgroundTag":"empty-scrape-result","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}