From 664e41975120951a244e9245ad50a5ef027176fe Mon Sep 17 00:00:00 2001 From: Karim shoair Date: Tue, 7 Apr 2026 05:39:39 +0200 Subject: [PATCH] docs(agent): update skill with the latest changes --- agent-skill/Scrapling-Skill.zip | Bin 80521 -> 81526 bytes agent-skill/Scrapling-Skill/SKILL.md | 2 + .../references/spiders/advanced.md | 45 ++++++++++++++++++ .../references/spiders/architecture.md | 4 ++ 4 files changed, 51 insertions(+) diff --git a/agent-skill/Scrapling-Skill.zip b/agent-skill/Scrapling-Skill.zip index 8daa704beeec310c297074e243fa9197cb9cbdb5..c43d0df74a3310ba0889e6bc2f6d30f1c55b9d78 100644 GIT binary patch delta 15835 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 z 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 Pe|(WaKyH2~f`I%VXQa@O diff --git a/agent-skill/Scrapling-Skill/SKILL.md b/agent-skill/Scrapling-Skill/SKILL.md index d4519bb..23f1de4 100644 --- a/agent-skill/Scrapling-Skill/SKILL.md +++ b/agent-skill/Scrapling-Skill/SKILL.md @@ -302,6 +302,8 @@ QuotesSpider(crawldir="./crawl_data").start() ``` Press Ctrl+C to pause gracefully - progress is saved automatically. Later, when you start the spider again, pass the same `crawldir`, and it will resume from where it stopped. +While iterating on a spider's `parse()` logic, set `development_mode = True` on the spider class to cache responses to disk on the first run and replay them on subsequent runs - so you can re-run the spider as many times as you want without re-hitting the target servers. The cache lives in `.scrapling_cache/{spider.name}/` by default and can be overridden with `development_cache_dir`. Don't ship a spider with this enabled. + ### Advanced Parsing & Navigation ```python from scrapling.fetchers import Fetcher diff --git a/agent-skill/Scrapling-Skill/references/spiders/advanced.md b/agent-skill/Scrapling-Skill/references/spiders/advanced.md index 1244c9e..654e17c 100644 --- a/agent-skill/Scrapling-Skill/references/spiders/advanced.md +++ b/agent-skill/Scrapling-Skill/references/spiders/advanced.md @@ -85,6 +85,49 @@ async def on_start(self, resuming: bool = False): self.logger.info("Starting fresh crawl") ``` +## Development Mode + +When you're iterating on a spider's `parse()` logic, re-hitting the target servers on every run is slow and noisy. Development mode caches every response to disk on the first run and replays them from disk on subsequent runs, so you can tweak your selectors and re-run the spider as many times as you want without making a single network request. + +Enable it by setting `development_mode = True` on your spider: + +```python +class MySpider(Spider): + name = "my_spider" + start_urls = ["https://example.com"] + development_mode = True + + async def parse(self, response: Response): + yield {"title": response.css("title::text").get("")} +``` + +The first run fetches normally and stores each response on disk. Every subsequent run serves the same requests from the cache, skipping the network entirely. + +### Cache Location + +By default, responses are cached in `.scrapling_cache/{spider.name}/` relative to the current working directory (where you ran the spider from, **not** where the spider script lives). You can override the location with `development_cache_dir`: + +```python +class MySpider(Spider): + name = "my_spider" + start_urls = ["https://example.com"] + development_mode = True + development_cache_dir = "/tmp/my_spider_cache" +``` + +### How It Works + +1. **Cache key**: Each response is keyed by the request's fingerprint, so any change to fingerprint-affecting attributes (`fp_include_kwargs`, `fp_include_headers`, `fp_keep_fragments`) will produce a fresh fetch. +2. **Storage format**: One JSON file per response, named `{fingerprint_hex}.json`. The body is base64-encoded so binary content is preserved exactly. Writes are atomic (temp file + rename). +3. **Replay**: On a cache hit, the engine skips the network entirely, including `download_delay`, rate limiting, and the `is_blocked()` retry path. The cached response goes straight to your callback. +4. **Stats**: Cached requests still count toward `requests_count`, `response_bytes`, and the per-status counters, so your stat output looks the same as a normal crawl. Two extra counters, `cache_hits` and `cache_misses`, let you see how the cache performed. + +### Clearing the Cache + +There's no automatic expiration. To force a fresh crawl, delete the cache directory or call the manager's `clear()` method directly. + +**Warning:** Development mode is meant for development, not production. Cached responses never expire, and replay bypasses rate limiting and blocked-request retries. Don't ship a spider with `development_mode = True`. + ## Streaming For long-running spiders or applications that need real-time access to scraped items, use the `stream()` method instead of `start()`: @@ -220,6 +263,8 @@ print(f"Failed: {stats.failed_requests_count}") print(f"Blocked: {stats.blocked_requests_count}") print(f"Offsite filtered: {stats.offsite_requests_count}") print(f"Robots.txt disallowed: {stats.robots_disallowed_count}") +print(f"Cache hits: {stats.cache_hits}") +print(f"Cache misses: {stats.cache_misses}") print(f"Items scraped: {stats.items_scraped}") print(f"Items dropped: {stats.items_dropped}") print(f"Response bytes: {stats.response_bytes}") diff --git a/agent-skill/Scrapling-Skill/references/spiders/architecture.md b/agent-skill/Scrapling-Skill/references/spiders/architecture.md index 9976f31..54186a1 100644 --- a/agent-skill/Scrapling-Skill/references/spiders/architecture.md +++ b/agent-skill/Scrapling-Skill/references/spiders/architecture.md @@ -60,6 +60,10 @@ When a request comes in, the Session Manager routes it to the correct session ba An optional system that, if enabled, saves the crawler's state (pending requests + seen URL fingerprints) to a pickle file on disk. Writes are atomic (temp file + rename) to prevent corruption. Checkpoints are saved periodically at a configurable interval and on graceful shutdown. Upon successful completion (not paused), checkpoint files are automatically cleaned up. +### Response Cache + +An optional cache that, when development mode is enabled, stores every fetched response on disk and replays it on subsequent runs. Each response is keyed by request fingerprint and serialized as JSON (with the body base64-encoded so binary content survives). It's meant for iterating on `parse()` logic without re-hitting the target servers, not for production use. + ### Output Scraped items are collected in an `ItemList` (a list subclass with `to_json()` and `to_jsonl()` export methods). Crawl statistics are tracked in a `CrawlStats` dataclass which contains a lot of useful info.