EXITO Supply Collector — a scraper that still tries on sites it's never seen
EvidenceDistributable desktop executable (PyInstaller)
EvidenceDistributable desktop executable (PyInstaller)
Store operators spend a large part of every day copying product data out of supplier sites. The supplier list keeps growing and no two sites are structured alike.
Writing a bespoke crawler per supplier means a developer is needed every time a supplier is added. Under that model the operator can never run it themselves.
When no registered crawler matches, a GenericCrawler walks structured data (JSON-LD), then OpenGraph, then meta tags, then the DOM. It isn't perfect, but the answer is never just 'this site is unsupported'.
Subclass `BaseCrawler`, implement `can_handle` and `collect`, register it with `CrawlerRegistry`. Site-specific selectors and credentials live in configuration rather than code.
I didn't stop at a CLI. It has a CustomTkinter MVC interface and ships as a PyInstaller executable, because a tool only gets used if a non-technical operator can open it and start working.
Image references inside collected HTML are rewritten to point at the downloaded local files, so the output survives the source site changing or blocking hotlinks.
Distributable desktop executable (PyInstaller)
The GenericCrawler loses accuracy on sites with poor structured data. Those ultimately need a dedicated plugin — which is exactly why the plugin structure came first.
Describe the thing you're currently stuck on. I'll reply by first separating what I can take on from what I can't.