Skip to main content

Polite, resumable URL queues for bounded scraping jobs.

Project description

scrapequeue

Polite, resumable URL queues for bounded Python scraping jobs.

scrapequeue is for developers who already know what URLs they want to fetch and want reliable queue management without adopting a crawler framework. You provide a fetch(url) function; scrapequeue handles URL ingestion, dedupe, rate limiting, retries, SQLite checkpointing, resume, failed URL inspection, and CSV export.

When to use it

Use scrapequeue when you have:

  • hundreds to low-hundreds-of-thousands of known URLs
  • a script/notebook that keeps growing retry/checkpoint code
  • a need to stop/restart jobs without re-fetching successes
  • a custom fetcher using httpx, requests, Playwright, or another client

When not to use it

Use something else when you need:

  • link discovery / crawling / spider frontiers
  • distributed queues across machines
  • proxy rotation, CAPTCHA solving, or anti-bot evasion
  • HTML parsing helpers baked into the queue

For those, consider Scrapy/Crawlee/Playwright directly. scrapequeue intentionally stays smaller.

Install

pip install scrapequeue

For local development:

pip install -e '.[dev]'

Five-line quickstart

from scrapequeue import Queue

queue = Queue(rate_limit="1/s", retries=3, checkpoint="jobs.sqlite")
queue.add_urls(["https://example.com/a", "https://example.com/b"])
queue.run(lambda url: {"url": url, "body": "..."})
queue.export_csv("results.csv")

Real fetch function

import httpx
from scrapequeue import Queue

queue = Queue(rate_limit="30/m", retries=3, checkpoint="jobs.sqlite")
queue.add_urls("urls.csv")  # requires a `url` column


def fetch(url: str) -> dict:
    response = httpx.get(url, timeout=10, follow_redirects=True)
    response.raise_for_status()
    return {
        "status": response.status_code,
        "content_type": response.headers.get("content-type", ""),
        "body": response.text,
    }


queue.run(fetch, progress=True)
queue.export_csv("results.csv")
queue.export_failed("failed.csv")

Input sources

queue.add_urls(["https://a.com", "https://b.com"])
queue.add_urls("urls.txt")
queue.add_urls("urls.csv")  # CSV must contain a `url` column

Duplicate URLs are ignored, so re-adding the same source is safe.

State machine

Every URL is persisted in SQLite with one of these states:

pending -> in_progress -> success
pending -> in_progress -> retrying -> pending
pending -> in_progress -> failed

On startup, stranded in_progress / retrying rows are reset to pending so interrupted jobs can resume.

Retry failed URLs

queue.export_failed("failed.csv")
queue.retry_failed()
queue.run(fetch, only_failed=True)

This lets you inspect failures, fix your fetcher/network issue, then rerun only failed URLs.

Backoff and progress

queue = Queue(backoff="exponential", backoff_seconds=0.5)
queue.run(fetch, progress=True)

Backoff modes:

  • fixed
  • linear default
  • exponential
  • jitter

Progress can also be a callback:

events = []
queue.run(fetch, progress=events.append)

CLI

scrapequeue add urls.csv --checkpoint jobs.sqlite
scrapequeue status --checkpoint jobs.sqlite
scrapequeue run ./fetcher.py:fetch --checkpoint jobs.sqlite --retries 3 --rate-limit 1/s
scrapequeue run ./fetcher.py:fetch --checkpoint jobs.sqlite --only-failed --progress
scrapequeue export results.csv --checkpoint jobs.sqlite
scrapequeue export-failed failed.csv --checkpoint jobs.sqlite
scrapequeue retry-failed --checkpoint jobs.sqlite

run accepts a fetch callable as either:

module:function
/path/to/file.py:function

Public API

Queue(...)

Queue(
    checkpoint="jobs.sqlite",
    retries=3,
    rate_limit="1/s",
    backoff_seconds=0.25,
    backoff="linear",
)

Methods

queue.add_urls(urls)
queue.run(fetch, only_failed=False, progress=None)
queue.export_csv(path)
queue.export_failed(path)
queue.retry_failed()
queue.counts()

Comparison

Tool Best for Difference
Scrapy full crawlers/spiders much larger framework; scrapequeue is bounded URL queue only
Crawlee browser/crawling automation scrapequeue avoids crawler abstraction and external complexity
tenacity retrying functions scrapequeue adds URL persistence, resume, export, and state tracking
requests-cache HTTP caching scrapequeue is queue/checkpoint oriented, not response caching

Examples

See:

examples/basic.py
examples/httpx_fetch.py
examples/playwright_fetch.py
examples/urls.csv

Development

pytest -q
ruff check .
ruff format --check .
python -m build
twine check dist/*

Non-goals

  • HTML parsing
  • browser automation abstraction
  • distributed queues
  • proxy rotation / anti-bot evasion
  • crawling/link following

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scrapequeue-0.1.0.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scrapequeue-0.1.0-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file scrapequeue-0.1.0.tar.gz.

File metadata

  • Download URL: scrapequeue-0.1.0.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for scrapequeue-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ad6cc5c83f3d3c2bea89386eadadebbd5fd08d8031aa2692987e660a9fa6c3a6
MD5 67948de5a425ed6024c794ed9dc9162e
BLAKE2b-256 89792bce7079eae0fa4b2523d5a645747ae3dc170cbdb6672f48fbf46a617368

See more details on using hashes here.

File details

Details for the file scrapequeue-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: scrapequeue-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for scrapequeue-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1ad478f3a27bc6b44b17baf59817df2d55df6779aaa68af15f1dae35bbc14f62
MD5 2083416b667c35c56c3fe0f105db7e79
BLAKE2b-256 5d21ea4ae9466075f6d72b7ab5876ec5c6d71ff0570169e3a54ecb1e4aba1410

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page