- Home
- Skills
- APIs & Backend
- Scraper Politeness Pattern — Async Python Fetch Layer
Works with the AI Agents you already use
Scraper Politeness Pattern — Async Python Fetch Layer
Async Python scraper pattern for polite, robots.txt-compliant data extraction and rate-limited domain crawling.
$39.99
Scraper Politeness Pattern — Async Python Fetch Layer
Example session with this skill installed
Generate an async Python scraper skeleton that respects robots.txt, uses a 2-second per-host delay, and extracts contact@ or info@ emails from a list of corporate homepages.
- Read your context and instructions
- Compiled the scraper politeness pattern
I have generated a polite async scraping skeleton using aiohttp. It includes a PoliteFetcher class that manages per-domain delays and a RobotsValidator to ensure compliance.
Scraper Implementation
import asyncio
import aiohttp
import re
from urllib.parse import urlparse
from typing import Dict, List
class PoliteFetcher:
def __init__(self, user_agent: str, delay: float = 2.0):
self.user_agent = user_agent
self.delay = delay
self.last_fetch: Dict[str, float] = {}
self.generic_pattern = re.compile(r'\b(contact|info|sales|support|hello)@[a-z0-9.-]+\.[a-z]{2,}\b', re.I)
async def fetch(self, session: aiohttp.ClientSession, url: str):
domain = urlparse(url).netloc
# Enforce per-host pacing
wait_time = self.last_fetch.get(domain, 0) + self.delay - asyncio.get_event_loop().time()
if wait_time > 0:
await asyncio.sleep(wait_time)
try:
async with session.get(url, headers={'User-Agent': self.user_agent}, timeout=10) as response:
self.last_fetch[domain] = asyncio.get_event_loop().time()
if response.status == 200:
text = await response.text()
emails = set(self.generic_pattern.findall(text))
return {"url": url, "status": 200, "emails": list(emails)}
return {"url": url, "status": response.status, "emails": []}
except Exception as e:
return {"url": url, "error": str(e)}
async def main(urls: List[str]):
fetcher = PoliteFetcher(user_agent="RespectfulBot/1.0")
async with aiohttp.ClientSession() as session:
tasks = [fetcher.fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for res in results:
print(res)
# Example Usage
if __name__ == "__main__":
targets = ["https://example.com", "https://acmecorp.org"]
asyncio.run(main(targets))
Next steps
- Add a
robots.txtparser library likeurllib.robotparserto thefetchmethod. - Define a
max_retriesconstant to handle 503 Service Unavailable errors. - Integrate a database logger to store extraction timestamps and source URLs.
Connects securely to your tools. The creator never sees your data.
About this skill
Scraping projects often fail due to aggressive rate limiting, robots.txt violations, or poor error handling. This skill provides a structured async Python implementation for building polite, resilient crawlers that stay within legal and technical boundaries. It handles the complex logic of per-domain pacing, bounded retries, and robots exclusion so you can focus on data extraction.
What it does
- Robots.txt Enforcement performs automated checks against site rules before every fetch.
- Per-Host Pacing manages async delays and concurrency to prevent server-side blocks.
- Resilient Retries implements exponential backoff for transient errors while honoring Retry-After headers.
- Safe Extraction identifies generic business mailboxes (info@, sales@) while avoiding personal data harvesting.
- Validation rejects unsafe URL schemes and prevents accidental credential leaks in logs.
How it works
- Configure the user agent, timeouts, and per-host concurrency limits.
- Validate target URLs to ensure only supported HTTP(S) protocols are used.
- Execute the fetching logic which checks robots.txt and applies domain-specific delays.
- Process the response data or extract generic role-based contact info if requested.
Frameworks & tools
Python using asyncio and aiohttp. Designed for integration with scraping libraries like BeautifulSoup or Selectolax.
Why this beats prompting it yourself
Writing reliable rate-limiting logic that persists across domain switches is error-prone. This skill enforces a strict safety-first hierarchy, ensuring your agent never accidentally bypasses a robots.txt file or triggers a 429 ban by ignoring headers.
Use cases
- Building a discovery crawler for local business directories.
- Automating market research across multiple corporate domains.
- Monitoring industry news sites for updates without triggering anti-bot flags.
- Extracting generic contact info for B2B lead enrichment.
Known limitations
Does not support bypassing CAPTCHAs, login walls, or IP blocks. Requires a local Python environment for execution. Does not provide proxy rotation or identity masking.
No CAPTCHA or login wall bypass. No proxy rotation. Requires Python asyncio environment. Robots.txt failure defaults to a conservative 'no-fetch' policy.
How to use
- 1
Connect your agent to the Agensi MCP
Copy the prompt and paste it into Claude, ChatGPT, Cursor or any agent that supports MCP. It sets up the connection for you. Manual setup
- 2
Sign in to Agensi
Your agent shows a sign-in link. Sign in and click Allow.
- 3
Ask for what you need
Your agent loads this skill and uses it on your task. It always asks before any payment.
Reviews
No reviews yet
Be one of the first to try it. Every listed skill goes through the trust checks below.
Security scanned
Checked by our 8-point scan before listing
Fresh listing
Recently published to Agensi
Money-back guarantee
Doesn't do what its page promises? You get your money back.
Trust & safety
Security scan
Security scan passed 24 days ago
- Software
Python
Permissions
Allowed Hosts