Skip to content

Commit 9a23514

Browse files
committed
docs: rework the extension-points guide around component contracts
1 parent aa273b7 commit 9a23514

1 file changed

Lines changed: 55 additions & 24 deletions

File tree

docs/guides/extending_crawlee.mdx

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
---
22
id: extending-crawlee
33
title: Extending Crawlee
4-
description: Learn which parts of Crawlee are designed to be extended, what contract each extension point defines, and where to find the detailed guide for each one.
4+
description: The extension points Crawlee exposes, the contract each one defines, and how to choose between them.
55
---
66

77
import ApiLink from '@site/src/components/ApiLink';
88

9-
Crawlee is built around a small number of abstract base classes that you can subclass to plug in your own behavior. This guide is the map: it lists every extension point, states the contract each one defines, and links to the guide that covers it in depth.
9+
Crawlee covers the common cases out of the box, but sooner or later you'll hit something it doesn't do: a parser for a format no built-in crawler understands, an HTTP backend your company mandates, a database you want your data in, or a browser that isn't launched the standard Playwright way. Rather than forking, you can plug your own implementation into the layer that differs and keep everything else.
1010

11-
If you maintain a third-party integration, such as an alternative browser backend or a storage adapter, you can build it against these contracts and host the integration guide in your own project. This page gives your users a stable reference for the interface your integration implements.
11+
This guide is the map. It covers the extension points, the contract each one defines, and links to the guide that goes deeper on it. If you maintain a third-party integration, you can build it against these contracts and host your own guide for it.
1212

1313
## Extension points
1414

15-
Crawlee currently has four extension points.
15+
The four extension points below are the main ones, and they're where most integrations plug in. They aren't the only abstract classes you can subclass - <ApiLink to="class/RequestLoader">`RequestLoader`</ApiLink>, <ApiLink to="class/FingerprintGenerator">`FingerprintGenerator`</ApiLink>, and <ApiLink to="class/RenderingTypePredictor">`RenderingTypePredictor`</ApiLink> are extensible too.
1616

1717
```mermaid
1818
---
@@ -27,6 +27,10 @@ class BasicCrawler {
2727
<<abstract>>
2828
}
2929
30+
class AbstractHttpCrawler {
31+
<<abstract>>
32+
}
33+
3034
class PlaywrightCrawler
3135
3236
class HttpClient {
@@ -35,64 +39,91 @@ class HttpClient {
3539
3640
class StorageClient {
3741
<<abstract>>
42+
create_dataset_client()
43+
create_kvs_client()
44+
create_rq_client()
45+
}
46+
47+
class DatasetClient {
48+
<<abstract>>
49+
}
50+
51+
class KeyValueStoreClient {
52+
<<abstract>>
53+
}
54+
55+
class RequestQueueClient {
56+
<<abstract>>
3857
}
3958
4059
class BrowserPool
4160
4261
class BrowserPlugin {
4362
<<abstract>>
63+
new_browser()
4464
}
4565
46-
BasicCrawler --> HttpClient : uses
47-
BasicCrawler --> StorageClient : uses
66+
class BrowserController {
67+
<<abstract>>
68+
}
69+
70+
BasicCrawler --|> AbstractHttpCrawler
4871
BasicCrawler --|> PlaywrightCrawler
72+
AbstractHttpCrawler --> HttpClient : uses
73+
BasicCrawler --> StorageClient : uses
74+
StorageClient --> DatasetClient : opens
75+
StorageClient --> KeyValueStoreClient : opens
76+
StorageClient --> RequestQueueClient : opens
4977
PlaywrightCrawler --> BrowserPool : uses
5078
BrowserPool --> BrowserPlugin : manages
79+
BrowserPlugin --> BrowserController : returns
5180
```
5281

5382
### Crawlers
5483

55-
Subclass a crawler when you need a parsing strategy or a request-handler context that the built-in crawlers do not provide.
84+
A crawler drives the whole run: it takes requests from the queue, fetches each one, builds the context object your handler receives, and manages retries, concurrency, sessions, and storage along the way. <ApiLink to="class/BasicCrawler">`BasicCrawler`</ApiLink> implements all of that and stays agnostic about how a page is fetched or parsed, which is what makes it the base every other crawler builds on.
5685

57-
For HTTP-based crawling, <ApiLink to="class/AbstractHttpCrawler">`AbstractHttpCrawler`</ApiLink> is the base class. A custom crawler supplies a parser that turns an HTTP response into your parsed type, a context type that exposes that parsed data to request handlers, and the crawler class that ties the two together. Everything else, including retries, concurrency, session management, and storage, is inherited from <ApiLink to="class/BasicCrawler">`BasicCrawler`</ApiLink>.
86+
For HTTP-based crawling, <ApiLink to="class/AbstractHttpCrawler">`AbstractHttpCrawler`</ApiLink> adds the fetch-and-parse layer on top. Extending it means supplying a parser that implements <ApiLink to="class/AbstractHttpParser">`AbstractHttpParser`</ApiLink>: `parse` turns an <ApiLink to="class/HttpResponse">`HttpResponse`</ApiLink> into your parsed type, `parse_text` does the same for a string, `select` and `is_matching_selector` apply selectors to it, and `find_links` extracts the URLs used for link enqueuing. You then pair that parser with a context type that exposes the parsed data to handlers, and a crawler class that ties the two together.
5887

59-
See [HTTP crawlers guide](./http-crawlers) for a worked example built on `selectolax`, and [Architecture overview](./architecture-overview) for how crawlers relate to the other components.
88+
See the [HTTP crawlers guide](./http-crawlers) for a worked example built on `selectolax`, and the [Architecture overview](./architecture-overview) for how crawlers relate to the other components.
6089

6190
### HTTP clients
6291

63-
Subclass an HTTP client when you want crawlers to talk to servers through a different HTTP library, or through a proxy or transport layer that the bundled clients do not cover.
92+
An HTTP client is what actually performs the network calls for HTTP-based crawlers. Swapping it changes the transport - the TLS stack, connection pooling, proxy handling, and browser impersonation - without touching how pages are parsed or how the crawl is orchestrated.
6493

65-
<ApiLink to="class/HttpClient">`HttpClient`</ApiLink> is the base class. Implementations must be async-compatible and must manage their own connection lifecycle and cleanup, because a single client instance is shared across concurrent requests.
94+
The contract is <ApiLink to="class/HttpClient">`HttpClient`</ApiLink>. `crawl` performs a request inside the crawler's pipeline and returns the result the crawler consumes, `send_request` covers standalone calls made from a handler, `stream` yields a response you read incrementally, and `cleanup` releases whatever the client holds open. Crawlee ships <ApiLink to="class/ImpitHttpClient">`ImpitHttpClient`</ApiLink>, <ApiLink to="class/HttpxHttpClient">`HttpxHttpClient`</ApiLink>, and <ApiLink to="class/CurlImpersonateHttpClient">`CurlImpersonateHttpClient`</ApiLink>.
6695

67-
See [HTTP clients guide](./http-clients) for the full interface and the built-in implementations.
96+
See the [HTTP clients guide](./http-clients) for the full contract and the trade-offs between the built-in clients.
6897

6998
### Storage clients
7099

71-
Subclass a storage client when you want Crawlee's storages to be backed by a system that is not covered by the built-in memory, file system, SQL, and Redis clients.
100+
A storage client is the backend behind Crawlee's three storages. <ApiLink to="class/Dataset">`Dataset`</ApiLink>, <ApiLink to="class/KeyValueStore">`KeyValueStore`</ApiLink>, and <ApiLink to="class/RequestQueue">`RequestQueue`</ApiLink> are the API you write against, and the storage client decides where that data actually lives. That separation is what lets you move a crawler from the local file system to a database or a cloud service without changing crawl code.
72101

73-
<ApiLink to="class/StorageClient">`StorageClient`</ApiLink> is the base class. It is a factory: it opens the per-storage clients for datasets, key-value stores, and request queues, and those clients implement the actual create, read, update, and delete operations.
102+
<ApiLink to="class/StorageClient">`StorageClient`</ApiLink> itself is only three factory methods - `create_dataset_client`, `create_kvs_client`, and `create_rq_client`. The real work sits in what they return: <ApiLink to="class/DatasetClient">`DatasetClient`</ApiLink> handles appending and reading items, <ApiLink to="class/KeyValueStoreClient">`KeyValueStoreClient`</ApiLink> handles record get, set, delete, and iteration, and <ApiLink to="class/RequestQueueClient">`RequestQueueClient`</ApiLink> handles adding, fetching, and marking requests as handled. A custom backend implements all four.
74103

75-
See [Storage clients guide](./storage-clients) for the interface, a custom client example, and how clients are registered and resolved.
104+
See the [Storage clients guide](./storage-clients) for the built-in implementations and a custom client example.
76105

77106
### Browser plugins
78107

79-
Subclass a browser plugin when an integration launches browsers through an API other than the standard Playwright one. Configuration options on <ApiLink to="class/PlaywrightBrowserPlugin">`PlaywrightBrowserPlugin`</ApiLink> cover the cases where the standard launch API is enough, so reach for a subclass only when the launch path itself differs.
108+
A browser plugin is what launches browsers for <ApiLink to="class/PlaywrightCrawler">`PlaywrightCrawler`</ApiLink>. The crawler never launches one itself: it goes through <ApiLink to="class/BrowserPool">`BrowserPool`</ApiLink>, which initializes the plugins it's given, forwards browser context options when creating pages, and manages each browser's lifecycle.
80109

81-
A plugin's `new_browser()` launches the browser and returns a <ApiLink to="class/PlaywrightBrowserController">`PlaywrightBrowserController`</ApiLink>; <ApiLink to="class/BrowserPool">`BrowserPool`</ApiLink> initializes the plugin, forwards browser context options when creating pages, and manages the controller's lifecycle.
110+
The contract is <ApiLink to="class/BrowserPlugin">`BrowserPlugin`</ApiLink>. Its `new_browser` launches a browser and returns a <ApiLink to="class/BrowserController">`BrowserController`</ApiLink>, which is what the pool then drives to open pages and tear things down. Reach for a subclass when the launch path itself differs from the standard Playwright one, since <ApiLink to="class/PlaywrightBrowserPlugin">`PlaywrightBrowserPlugin`</ApiLink>'s configuration options already cover the cases where it doesn't.
82111

83-
See [Playwright crawler guide](./playwright-crawler) for the contract and the responsibilities a subclass has to preserve, and the [Camoufox example](../examples/playwright-crawler-with-camoufox) for a complete integration.
112+
See the [Playwright crawler guide](./playwright-crawler) for the responsibilities a subclass has to preserve, and the [Camoufox example](../examples/playwright-crawler-with-camoufox) for a complete integration.
84113

85114
## Choosing an extension point
86115

87116
Match the layer to what actually differs in your integration.
88117

89-
- The response is fetched the usual way but parsed differently: extend a **crawler**.
90-
- The response is fetched over a different HTTP library or transport: extend an **HTTP client**.
91-
- Requests and results should live somewhere other than the built-in backends: extend a **storage client**.
92-
- Browsers are launched through a different API: extend a **browser plugin**.
118+
- The response format is one no built-in crawler parses - subclass <ApiLink to="class/AbstractHttpCrawler">`AbstractHttpCrawler`</ApiLink> with your own parser.
119+
- The transport differs, but parsing doesn't - implement <ApiLink to="class/HttpClient">`HttpClient`</ApiLink> and pass it to any HTTP crawler.
120+
- Data needs to live somewhere Crawlee doesn't support yet - implement <ApiLink to="class/StorageClient">`StorageClient`</ApiLink> and its three per-storage clients.
121+
- Browsers need to be launched through a different API - implement <ApiLink to="class/BrowserPlugin">`BrowserPlugin`</ApiLink> and hand it to <ApiLink to="class/BrowserPool">`BrowserPool`</ApiLink>.
93122

94-
Prefer configuration over a subclass wherever the built-in class already exposes the knob you need. Subclassing ties your integration to a contract that only changes with Crawlee's major versions, while configuration keeps you on the maintained path.
123+
When more than one fits, pick the narrowest. A custom HTTP client works with every HTTP crawler, so it's easier to maintain than a crawler subclass that hard-codes the same transport.
95124

96125
## Conclusion
97126

98-
Crawlee's extension points are crawlers, HTTP clients, storage clients, and browser plugins. Each is an abstract base class with a documented contract and a guide that covers it in depth. If you are building an integration, start from the contract that matches the layer you are replacing, and keep the rest of the pipeline on the built-in path.
127+
Each extension point is a small abstract class with a documented contract, and everything above it keeps working once you implement one. If you're building a third-party integration, these contracts are also the stable surface to write your own documentation against.
128+
129+
If anything here is unclear or you hit a case the contracts don't cover, open an issue on [GitHub](https://github.com/apify/crawlee-python) or join our [Discord](https://discord.com/invite/jyEM2PRvMU).

0 commit comments

Comments
 (0)