OneCrawler¶
Crawling hard? Not anymore.¶
Async Python crawling library with sitemap discovery, browser-based extraction, and LLM-powered structured output — one Settings object drives it all.
from onecrawler import Settings, SiteMap, Scraper
from onecrawler.utils import writter
async def main():
settings = Settings(include_link_patterns=["/news/*"], concurrency=10)
sitemap = SiteMap(settings)
urls = await sitemap.run("https://example.com")
async with Scraper(settings) as scraper:
results = await scraper.run(urls) # [{"url": ..., "result": ...}, ...]
writter.dump_json(results, "output.json")
Why OneCrawler¶
Many crawling projects start as small scripts and become hard to maintain once they need retries, concurrency, browser rendering, sitemap fallback, URL filtering, and structured extraction. OneCrawler gives those concerns a shared settings model and a few focused async engines, so production scripts stay readable.
-
Sitemap-first discovery
Collect URLs from
robots.txt, sitemap indexes,.xml.gz, and feeds — no browser required. Falls back to HTML crawling only when needed. -
Browser link extraction
Playwright-backed
shallowanddeeptraversal for JavaScript-rendered pages and sites without usable sitemaps. -
Heuristic & GenAI scraping
Fast trafilatura-based extraction by default, or a typed GenAI pipeline with a Pydantic
output_schemawhen you need structured fields. -
Composable filters
Filter extracted content by date, keywords, file type, or similarity — and combine predicates with
AND/OR/NOT. -
Async & concurrent
Every engine is
async with-managed with tunable concurrency, retries, and timeouts from a singleSettingsobject. -
Proxy rotation
Fan requests across a proxy pool with round-robin rotation, shared by both the sitemap layer and the browser engine.
Recommended first path
Start with sitemap discovery, store the URL list, then scrape those URLs in a separate step. This gives you cleaner retries and easier debugging.
Choosing the right tool¶
| Goal | Recommended feature | Why |
|---|---|---|
| Collect most public URLs quickly | SiteMap | Uses robots.txt, common sitemap paths, nested sitemap indexes, and optional HTML fallback |
| Inspect one listing page | shallow link extraction | Lower crawl cost and easier to reason about |
| Explore a site section recursively | deep link extraction | Follows internal links until your settings limit |
| Extract readable article text | heuristic scraping | Fast, deterministic, and does not require model calls |
| Produce strongly typed output | GenAI scraping with a Pydantic schema | Best fit when downstream systems require a stable structured shape |
| Filter results by date, keywords, or topic | onecrawler.filters with AND/OR/NOT | Composable post-extraction filters keep only relevant content |
| Avoid noisy crawls | include_link_patterns | Keeps discovery focused on URL paths you trust |
The full workflow¶
Start with sitemap discovery whenever possible — it is the fastest, cleanest, and least expensive way to collect URLs. If the site has no useful sitemap, use LinkExtractor (shallow for one page, deep for recursive traversal), then pass the final URL list to Scraper.
from onecrawler import Settings, LinkExtractor, Scraper
from onecrawler.utils import writter
async def main():
settings = Settings(
link_extraction_limit=500,
include_link_patterns=["/news/*"],
concurrency=10,
)
async with LinkExtractor(settings) as extractor:
urls = await extractor.run("https://example.com")
print(f"Found {len(urls)} URLs")
async with Scraper(settings) as scraper:
results = await scraper.run(urls)
print(f"Scraped {len(results)} pages")
writter.dump_json(results, "output.json")
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Crawling needs boundaries
Always set reasonable limits, filters, retries, and concurrency. Clear crawl boundaries protect both your job and the target site.
Production principles¶
- Prefer sitemaps before crawling pages. They are faster, friendlier to target sites, and usually more complete than what a browser can discover from navigation.
- Constrain every job. Set
link_extraction_limit,include_link_patterns,concurrency,request_timeout, andmax_retriesexplicitly so a crawl behaves predictably when the target site changes. - Use heuristic scraping by default. It is cheaper and more repeatable; move to GenAI only when you need semantic interpretation, field normalization, or a typed Pydantic schema.
- Treat browser crawling as the heavier tool. It is useful for JavaScript-rendered pages and dynamic link discovery, but has more moving parts than sitemap parsing or direct HTTP fetching.
Where to next¶
-
Installation
Package setup, browser requirements, and optional extras.
-
Quick start
First complete discovery and scraping workflows, end to end.
-
Configuration
Every
Settingsfield, defaults, and how the engines use them. -
API reference
Public classes and functions exported from
onecrawler.