Scraping-friendly HTTP, string parsing, JSON helpers, and AI parsing.
Project description
Respondo
A lightweight Python library for web scraping, text extraction, and AI-powered parsing. Zero external dependencies.
Installation
pip install respondo
Features
- Text Extraction — Extract substrings, regex matches, and structured data
- HTML Parsing — Forms, tables, links, and visible text extraction
- JSON Utilities — Find embedded JSON, safe traversal, schema validation
- Response Handling — Status codes, headers, cookies, charset detection
- AI Parsing — 10 LLM providers with structured output support
Quick Start
from respondo import between, extract_links, parse_ai, Response
# Extract text between delimiters
between("<title>Hello World</title>", "<title>", "</title>")
# => "Hello World"
# Parse HTML response
resp = Response(200, {"content-type": "text/html"}, b"<a href='/page'>Link</a>")
extract_links(resp.text, base="https://example.com")
# => ["https://example.com/page"]
# AI-powered extraction
parse_ai("Extract all prices", "Item A: $29.99, Item B: $49.99", provider="openai")
# => "$29.99, $49.99"
Text Extraction
from respondo import between, betweens, between_last, between_n
between("Hello [World]!", "[", "]") # => "World"
betweens("a]x[b]y[c", "[", "]") # => ["b"]
between_last("[a]x[b]y", "[", "]") # => "b"
between_n("[a][b][c]", "[", "]", 2) # => "b" (1-indexed)
Regex
from respondo import regex_first, regex_all
regex_first("Price: $42.99", r"\$[\d.]+") # => "$42.99"
regex_first("Price: $42.99", r"\$([\d.]+)") # => "42.99" (capture group)
regex_all("<id>1</id><id>2</id>", r"<id>(\d+)</id>") # => ["1", "2"]
Text Utilities
from respondo import normalize_space, strip_tags, unescape_html
normalize_space(" hello world ") # => "hello world"
strip_tags("<p>Hello <b>World</b></p>") # => "Hello World"
unescape_html("<div>") # => "<div>"
HTML Parsing
from respondo import get_text, extract_links, extract_forms, extract_tables
html = """
<html>
<body>
<h1>Welcome</h1>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</body>
</html>
"""
# Extract visible text
get_text(html) # => "Welcome About Contact"
# Extract links
extract_links(html, base="https://example.com")
# => ["https://example.com/about", "https://example.com/contact"]
# Same-host filtering
extract_links(html, base="https://example.com", same_host=True)
# Extension filtering
extract_links(html, extensions=[".pdf", ".doc"])
Forms
html = '<form action="/login" method="post"><input name="user"><input name="pass" type="password"></form>'
extract_forms(html, base="https://example.com")
# => [{"action": "https://example.com/login", "method": "post", "fields": {"user": "", "pass": ""}}]
Tables
html = "<table><tr><th>Name</th><th>Age</th></tr><tr><td>Alice</td><td>30</td></tr></table>"
extract_tables(html)
# => [{"headers": ["Name", "Age"], "rows": [{"Name": "Alice", "Age": "30"}]}]
CSRF Tokens
from respondo import parse_csrf_token
parse_csrf_token('<input name="csrf_token" value="abc123">') # => "abc123"
parse_csrf_token('<meta name="csrf-token" content="xyz789">') # => "xyz789"
JSON Utilities
from respondo import find_first_json, find_all_json, json_get, json_in_html
# Find JSON in mixed text
find_first_json('callback({"user": "alice", "id": 42})')
# => {"user": "alice", "id": 42}
find_all_json('{"a":1} text {"b":2}')
# => [{"a": 1}, {"b": 2}]
# Safe nested access
data = {"user": {"profile": {"name": "Alice"}}}
json_get(data, "user", "profile", "name") # => "Alice"
json_get(data, "user", "missing", "key") # => None
# Array indexing
json_get([{"id": 1}, {"id": 2}], 0, "id") # => 1
# Extract JSON from HTML
json_in_html('<script type="application/json">{"config": true}</script>')
# => [{"config": true}]
Response Handling
from respondo import Response
resp = Response(
status=200,
headers={"Content-Type": "application/json; charset=utf-8"},
body=b'{"success": true}'
)
# Status checks
resp.is_success() # => True (200-299)
resp.is_redirect() # => False (300-399)
resp.is_client_error() # => False (400-499)
resp.is_server_error() # => False (500-599)
# Body access
resp.body # => b'{"success": true}'
resp.text # => '{"success": true}'
resp.json() # => {"success": True}
# Headers
resp.header("content-type") # => "application/json; charset=utf-8"
resp.headers_all("set-cookie") # => ["session=abc", "user=123"]
resp.content_type() # => ("application/json", "utf-8")
# Hashing
resp.hash() # => SHA-256 hex digest
resp.hash("md5") # => MD5 hex digest
# Charset detection
text, charset = resp.charset_sniff()
# Cookie parsing
resp.cookies()
# => [{"name": "session", "value": "abc", "attrs": {"path": "/", "httponly": ""}}]
# HTML shortcuts
resp.extract_links(base="https://example.com")
resp.extract_json()
resp.strip_scripts_styles()
Encoding Utilities
from respondo import url_encode, url_decode, b64_encode, b64_decode
# URL encoding
url_encode({"q": "hello world", "page": 1}) # => "q=hello+world&page=1"
url_encode({"tags": ["a", "b"]}) # => "tags=a&tags=b"
# URL decoding
url_decode("a=1&b=2&b=3") # => {"a": ["1"], "b": ["2", "3"]}
# Base64
b64_encode("hello") # => "aGVsbG8="
b64_decode("aGVsbG8=") # => b"hello"
# URL-safe Base64
b64_encode("data", urlsafe=True)
b64_decode("ZGF0YQ", urlsafe=True)
AI Parsing
Parse text using LLM APIs. Supports 10 providers with structured output.
from respondo import parse_ai, parse_ai_json, list_providers
# List available providers
list_providers()
# => {"openai": "gpt-4o-mini", "anthropic": "claude-3-5-haiku-latest", ...}
# Basic extraction
parse_ai("Extract all email addresses", "Contact: alice@example.com", provider="openai")
# => "alice@example.com"
# Custom model
parse_ai("Summarize this text", article, provider="anthropic", model="claude-3-5-sonnet-latest")
# JSON response
parse_ai_json("Extract name and age", "John is 30 years old", provider="openai")
# => {"name": "John", "age": 30}
# Structured output with schema
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string"}
},
"required": ["name", "age"],
"additionalProperties": False
}
parse_ai_json("Extract person data", text, provider="openai", schema=schema)
# => {"name": "John", "age": 30, "email": "john@example.com"}
Supported Providers
| Provider | Environment Variable | Default Model |
|---|---|---|
openai |
OPENAI_API_KEY |
gpt-4o-mini |
anthropic |
ANTHROPIC_API_KEY |
claude-3-5-haiku-latest |
gemini |
GEMINI_API_KEY |
gemini-2.0-flash |
grok |
GROK_API_KEY |
grok-2-latest |
mistral |
MISTRAL_API_KEY |
mistral-small-latest |
groq |
GROQ_API_KEY |
llama-3.3-70b-versatile |
cohere |
COHERE_API_KEY |
command-r |
together |
TOGETHER_API_KEY |
meta-llama/Llama-3.3-70B-Instruct-Turbo |
deepseek |
DEEPSEEK_API_KEY |
deepseek-chat |
perplexity |
PERPLEXITY_API_KEY |
sonar |
Error Handling
All functions return empty values instead of raising exceptions:
between("no match", "<", ">") # => ""
find_first_json("not json") # => None
regex_first("abc", r"\d+") # => ""
json_get({"a": 1}, "b", "c") # => None
b64_decode("invalid!!!") # => b""
parse_ai("prompt", "text") # => "" (if no API key)
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file respondo-0.3.1.tar.gz.
File metadata
- Download URL: respondo-0.3.1.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52dda7d1120f7e8a611ef7cb20568ba5b0f5eae002d186fc3b0401457d80bc9a
|
|
| MD5 |
f8d4cd3a2efeceb37df544f3f0ebadce
|
|
| BLAKE2b-256 |
fae97cd00ca02c09459170b9ba9f7f65523887d909cfd48205140129bd9608fb
|
File details
Details for the file respondo-0.3.1-py3-none-any.whl.
File metadata
- Download URL: respondo-0.3.1-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a60fa88b5b9c8730b4382a6cf15127a5153e4dec8cb10640e8572f879f05f270
|
|
| MD5 |
ec64b45117d8ff2f15069e8ed70b19ac
|
|
| BLAKE2b-256 |
a7a8d23b368d57c130e713fe6a201f7089be889d52cf9eba8824ab1e1cc8e4d6
|