A fast, headless Playwright crawler that discovers Finploy URLs and writes a standards-compliant XML sitemap.
- In-memory frontier (no database)
- Automatic scroll and "View more" button clicking
- URL normalization and domain allowlist
- Concurrent workers with gentle rate limiting
- Output:
output_sitemaps/sitemap.xml
- Python 3.8+
- Windows/macOS/Linux
- Create a virtual environment and install dependencies
python -m venv .venv . .venv/Scripts/activate # Windows PowerShell: ..venv\Scripts\Activate.ps1 pip install -r requirements.txt
2) Install the Playwright browser (Chromium)
```bash
python -m playwright install chromium
python finploy_crawler.pyThe crawler stores its frontier in memory and writes the final sitemap to output_sitemaps/sitemap.xml when finished.
Edit finploy_crawler.py to adjust behavior:
START_URL: Seed homepageALLOWED_HOSTS: Allowed hostnames setCONCURRENT_PAGES: Number of concurrent Playwright pagesMAX_PAGES: Crawl cap for unique pagesNAV_TIMEOUT: Navigation timeout (ms)SCROLL_PAUSE: Delay between scrolls (s)CLICK_RETRY_LIMIT: Attempts to click "view more" style buttonsREQUEST_DELAY: Delay between navigations per worker (s)VIEW_MORE_SELECTORS: CSS/text selectors to expand content
- Navigates pages headlessly via Playwright
- Auto-scrolls and clicks common "view more" patterns
- Extracts anchors, data-* links, onclick/script URLs, and paginated variants
- Normalizes and filters URLs to allowed hosts
- Maintains an in-memory queue and seen set
- Writes a single XML sitemap
- Language: Python 3.8+
- Runtime/Automation: Playwright (
playwright.async_api) - Concurrency:
asyncio - Parsing & utilities:
urllib.parse,re,pathlib,datetime - Sitemap generation:
xml.etree.ElementTree - Note:
requirements.txtcontains some legacy/optional deps (e.g., Selenium, BeautifulSoup) that are not required for this Playwright-based crawler.
- Frontier (no DB): In-memory
asyncio.Queueplus aseenmap with crawl metadata; guarded by anasyncio.Lock. - Concurrency:
CONCURRENT_PAGESPlaywright pages, each running a worker loop with gentleREQUEST_DELAY. - Navigation:
page.goto(..., wait_until="networkidle")withNAV_TIMEOUTand basic exception handling. - Dynamic discovery:
- Repeated auto-scroll until page height stabilizes
- Click common "View/Load more" selectors up to
CLICK_RETRY_LIMIT - Extract links from anchors, common
data-*attributes,onclickhandlers, and inline scripts
- Pagination heuristic: When encountering
?page=N, proactively enqueue the next few pages (N+1..N+5). - URL hygiene: Normalize URLs (drop fragments, sort query, strip
utm_*and common session params) and filter byALLOWED_HOSTS. - Stop conditions: Exit when the queue drains or
MAX_PAGESis reached. - Output: Generate a standards-compliant
urlsetsitemap withlastmodderived from HTTPLast-Modifiedheader when available, otherwisecrawled_at.
- Dynamic/Lazy content: Many pages require scrolling/clicking to reveal links.
- Resolution: Iterative scroll plus robust selector list and retries for "view more" actions.
- Timeouts/Fragile navigation: Dynamic sites can intermittently stall.
- Resolution: Conservative
NAV_TIMEOUT, try/catch around navigation and extraction, continue on failure.
- Resolution: Conservative
- Duplicate/Noisy URLs: Tracking params and session IDs inflate the frontier.
- Resolution: URL normalization removes
utm_*and common session params; queries sorted; fragments dropped.
- Resolution: URL normalization removes
- Pagination discovery: Next pages are not always linked visibly.
- Resolution: Heuristic expansion for
?page=patterns to uncover adjacent pages.
- Resolution: Heuristic expansion for
- Politeness vs. throughput: Balancing speed with server friendliness.
- Resolution: Tunable
CONCURRENT_PAGESandREQUEST_DELAY; domain allowlist prevents off-site crawl.
- Resolution: Tunable
- Sitemap correctness: Ensuring valid XML and meaningful
lastmod.- Resolution: Use
xml.etree.ElementTree; prefer HTTPLast-Modifiedheader with fallback to crawl timestamp.
- Resolution: Use
output_sitemaps/sitemap.xml: UTF-8 XML compliant with sitemaps.org
- If Playwright browsers are missing:
python -m playwright install chromium - If no URLs appear: verify
ALLOWED_HOSTSand seeds inSEED_URLS - Windows path issues: run from project root in PowerShell
- No database is used. Crawl state is ephemeral per run.
- To persist progress across runs, add a simple file-based checkpoint (can be added on request).
MIT