{"record":{"id":"c5c204065238b282","repo":"jackwener/OpenCLI","slug":"taxonomy-selector-drift-site-jianyu-command-sear","errorCode":null,"errorMessage":"[taxonomy=selector_drift] site=jianyu command=search blocked by human verification / access challenge","messagePattern":"\\[taxonomy=selector_drift\\] site=jianyu command=search blocked by human verification / access challenge","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"warning","filePath":"clis/jianyu/search.js","lineNumber":588,"sourceCode":"                        ...row,\n                        source_id: SITE,\n                        notice_id: extractNoticeId(row.url),\n                        published_at: publishedAt,\n                        detail_status: detailSignal.detail_status,\n                        detail_reason: detailSignal.detail_reason,\n                    };\n                }))\n                    .filter((row) => row.detail_status === 'ok')\n                    .filter((row) => sinceDays == null || isWithinSinceDays(row.published_at, sinceDays))\n                    .slice(0, limit)\n                    .map((row, index) => ({\n                    ...row,\n                    rank: index + 1,\n                }));\n                return enriched;\n            }\n            if (apiResult.challenge || await isAuthRequired(page)) {\n                throw new AuthRequiredError(DOMAIN, '[taxonomy=selector_drift] site=jianyu command=search blocked by human verification / access challenge');\n            }\n        }\n        const records = toProcurementSearchRecords(rows, {\n            site: SITE,\n            query,\n            limit,\n        });\n        const enriched = dedupeByNoticeKey(records.map((row) => {\n            const detailSignal = classifyDetailStatus(row.url);\n            const publishedAt = normalizeDate(row.publish_time || row.date);\n            return {\n                ...row,\n                source_id: SITE,\n                notice_id: extractNoticeId(row.url),\n                published_at: publishedAt,\n                detail_status: detailSignal.detail_status,\n                detail_reason: detailSignal.detail_reason,\n            };","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jianyu/search.js#L570-L606","documentation":"AuthRequiredError thrown by the jianyu search command when the search results are blocked by human verification or an access challenge. The search flow either received a challenge flag in the API result (apiResult.challenge) or the isAuthRequired(page) check detected an auth/challenge page, and it tags the error with taxonomy 'selector_drift' because challenge pages usually mean the site's normal DOM/API contract no longer holds.","triggerScenarios":"Calling the jianyu search command when the site injects a CAPTCHA/slider challenge into the API response (apiResult.challenge truthy) or the rendered page matches isAuthRequired instead of returning result rows.","commonSituations":"Too many rapid searches from one IP triggering anti-bot rate limiting; datacenter/VPN IP flagged by Jianyu's WAF; expired session causing the search endpoint to redirect to a verification page; site security update adding new challenge types.","solutions":["Solve the CAPTCHA/challenge manually in the automated browser window, then re-run the search","Slow down request rate and add delays between searches to avoid tripping rate limits","Switch to a residential IP or disable the VPN/datacenter proxy being flagged","Re-authenticate (opencli jianyu login) so search uses a valid logged-in session","If challenges become persistent, update isAuthRequired/challenge detection in clis/jianyu/search.js for the new challenge markup"],"exampleFix":"// before: rapid loop trips challenge\nfor (const q of queries) await jianyuSearch(page, q);\n// after: throttle and reuse authenticated session\nfor (const q of queries) {\n  await jianyuSearch(page, q);\n  await page.wait(5);\n}","handlingStrategy":"retry","validationCode":"if (await isAuthRequired(page)) {\n  throw new Error('Jianyu is showing a verification page — solve the challenge in the browser before searching');\n}","typeGuard":"function isChallengeBlocked(e) {\n  return e instanceof Error && /blocked by human verification/.test(e.message);\n}","tryCatchPattern":"try {\n  rows = await jianyuSearch(page, query);\n} catch (e) {\n  if (isChallengeBlocked(e)) {\n    await solveChallengeInBrowser(page); // pause for human CAPTCHA solve\n    rows = await jianyuSearch(page, query); // retry once after solving\n  } else throw e;\n}","preventionTips":["Throttle search frequency and add delays between queries","Avoid datacenter/VPN IPs that Jianyu's WAF flags","Keep an authenticated session (login) for search rather than anonymous requests","Reuse one browser session instead of spawning fresh profiles per search","Solve CAPTCHAs promptly in the visible browser when the challenge appears"],"tags":["anti-bot","captcha","rate-limit","auth","jianyu"],"backgroundTag":"blocked-by-human-verification","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}