fetching-and-extracting

Guides HTML fetching, rendering, and article extraction decisions in the newsletter crawler codebase.

2|1|Updated Jun 29, 2026
One-click install
npx skills add https://github.com/frederico-kluser/newsletter-crawler --skill fetching-and-extracting-frederico-kluser
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: fetching-and-extracting
Source: https://github.com/frederico-kluser/newsletter-crawler/tree/main/.agents/skills/fetching-and-extracting
Command: npx skills add https://github.com/frederico-kluser/newsletter-crawler --skill fetching-and-extracting-frederico-kluser

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Editing the crawler's fetch and extraction pipeline (src/fetch.js, src/clean.js, src/parse-core.js, src/parse-pool.js, src/selectors.js) is risky because subtle invariants — like RENDER_PROFILES existing, fork-based parse isolation, and selector validation thresholds — have caused real production crashes and hangs. This Skill injects the verified, hard-won knowledge needed to change that code safely. ## Core Features & Use Cases - fetchSmart rendering decisions: Documents the static-got-first heuristic, per-host needsJs caching, and the RENDER_PROFILES constant whose loss once broke every rendered fetch. - Fault-isolated parsing: Explains why JSDOM/Readability runs in a forked child-process pool (worker_threads cannot isolate a native SIGSEGV) and the safe-default/respawn invariants. - Smart scroll and date handling: Covers incremental link harvest during infinite scroll, date-floor stopping, publication-date extraction chains, and future-date clamping. - Use Case: When changing Playwright scroll behavior or the Readability extraction threshold, load this Skill to avoid regressions like orphaned Chromium processes, segfault-killed crawls, or selector cache poisoning. ## Quick Start Ask the AI to modify the article extraction threshold in src/clean.js while following the fetching-and-extracting skill guidance.

Frequently Asked Questions about fetching-and-extracting

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How does fetchSmart decide between static fetch and Playwright rendering?

fetchSmart tries a static got request first and renders with Playwright only if the page looks empty (fewer than 5 links or under 500 chars of body text). The needsJs result is cached per host so the decision is not re-made, and forceRender bypasses the heuristic.

Why does JSDOM and Readability parsing run in a forked child process?

A forked child process isolates native crashes: a JSDOM CSS-parser segfault in worker_threads kills the whole process because threads share memory, while a forked child contains it. On child crash the pool resolves the task to a safe default and respawns, never re-running inline.

How does the crawler stop infinite scroll at a date floor?

The listing profile harvests link href, text, and datetime each scroll round and stops when at least 2 new dated items are all older than the --since floor, when 3 consecutive checks yield no new hrefs, or at the round/deadline cap. Harvested links merge conservatively into the crawl queue.

What thresholds validate AI-derived CSS selectors before caching?

Link selectors must yield at least 3 unique links, content selectors at least 400 characters, and date specs must produce parseable dates for at least max(3, 50%) of items. Below threshold the selector is re-derived instead of cached.

Why does the crawler hang after a crawl finishes?

Orphaned Chromium child processes with open pipes can hold the Node event loop after a run ends. The fix gives browser close 10 seconds, then SIGKILLs direct Chromium children of the process, with a CLI backstop timer that exits after the database closes.

How are anti-bot interstitial pages handled during extraction?

isBlockedPage checks title and text for Cloudflare or captcha challenge patterns and gates every save, since challenge pages return HTTP 200. For curated items a blocked target keeps the aggregator blurb instead of being dropped.