Skip to content

product-scraper#2

Merged
Erik05Master merged 5 commits into
masterfrom
product-scraper
Jul 7, 2026
Merged

product-scraper#2
Erik05Master merged 5 commits into
masterfrom
product-scraper

Conversation

@Erik05Master

@Erik05Master Erik05Master commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Neue Funktionen
    • Amazon-Shops werden unterstützt (Preis-, Titel- und Verfügbarkeits-Erkennung) inkl. Blockade-Erkennung.
    • Erweiterte Shop-Fetch-Optionen: shop-spezifische Request-Header plus optionaler Warmup für Cookie-Vorbereitung.
    • Domain→Adapter-Auflösung per Best-Match (Longest-Suffix).
    • Dashboard zeigt „Active Alerts“ und „Target Prices Hit“.
  • Bug Fixes / Verbesserungen
    • Verbesserte CAPTCHA/WAF- und Fehlerseiten-Erkennung (u. a. auch bei eBay).
    • Mehr Adapter nutzen konsistent HTTPx zum Abruf (z. B. Anycubic, Elegoo, Prusa, 3DJake).
  • Chores
    • Pylint/CI-Checks wurden angepasst.

@Erik05Master
Erik05Master marked this pull request as draft July 6, 2026 13:08
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55a0caa0-4856-418a-a605-fde4a271cdb1

📥 Commits

Reviewing files that changed from the base of the PR and between 63cc497 and 255ee98.

📒 Files selected for processing (8)
  • .github/workflows/ci.yml
  • .github/workflows/docker-publish.yml
  • .github/workflows/pylint.yml
  • app/routes/api_keys.py
  • app/shop_adapters/_amazon.py
  • app/shop_adapters/registry.py
  • seed.py
  • seed_shops.py

Walkthrough

Die PR erweitert den HTTPX-Fetch-Pfad um adapterbasierte Header und Warmup-URLs, ergänzt neue und angepasste Shop-Adapter, aktualisiert das Dashboard um Alert- und Target-Price-Ansichten und passt mehrere Repo-Hygiene-Dateien an.

Changes

Shop-Fetch und Adapter-Erweiterungen

Layer / File(s) Summary
HTTPX-Hooks im Adapter-Vertrag
app/shop_adapters/base.py, app/price_check_service.py
BaseAdapter erhält optionale fetch_headers()- und warmup_url()-Hooks; _fetch_httpx und check_price nutzen diese Werte im HTTPX-Fetch-Pfad.
Amazon-Adapter und Registrierung
app/shop_adapters/_amazon.py, app/shop_adapters/registry.py
Neuer AmazonAdapter mit Domain-Header-Mapping, CAPTCHA-/Preis-/Verfügbarkeits-Extraktion und Registry-Eintrag.
eBay-Adapter für Marketplace-Fetch
app/shop_adapters/_ebay.py
EbayAdapter nutzt mehrere Domains, liefert Accept-Language-Header und erweitert Blockerkennung sowie Preisfehlerbehandlung.
Weitere Adapter auf httpx
app/shop_adapters/_3djake.py, app/shop_adapters/_anycubic.py, app/shop_adapters/_elegoo.py, app/shop_adapters/_prusa.py
Mehrere Adapter setzen fetch_engine="httpx"; ThreeDJakeAdapter ergänzt zusätzlich eine frühe WAF-Blockerkennung.
Preis- und Adapter-Dokumentation
CLAUDE.md, README.md, app/routes/shop_rules.py, app/shop_adapters/_esun.py
Dokumentation und Kommentare werden sprachlich verallgemeinert; ein veralteter Hinweis zu esun3d.com entfällt.

Dashboard-Ansichten

Layer / File(s) Summary
Alerts und Target-Prices im Dashboard
app/templates/dashboard/index.html
Das Dashboard rendert neue Bereiche für recent_alerts und target_hits und entfernt den später platzierten Doppelabschnitt.

API-Key-Routen

Layer / File(s) Summary
DB-Kontext in Admin- und Delete-Route
app/routes/api_keys.py
admin_required und die Delete-Route lesen und löschen Objekte nun über db.get(...) und db.delete(...) statt über session-basierte Aufrufe.

Workflow-, Seed- und Migrationsanpassungen

Layer / File(s) Summary
Pylint-Workflow und Lint-Jobs
.github/workflows/pylint.yml, .github/workflows/docker-publish.yml
Ein neuer Pylint-Workflow wird hinzugefügt und der Lint-Job im Docker-Publish-Workflow auf Python 3.12, .pylintrc und eine breitere Dateiauswahl umgestellt.
Seed-Formatierung und Kommentarbereinigung
seed.py, seed_shops.py, migrations/versions/...
Seed-Dateien werden in mehrzeilige Dictionary-Literale umformatiert, Import-Lint-Kommentare ergänzt und ein Migrationskommentarblock entfernt.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant check_price
  participant BaseAdapter
  participant _fetch_httpx
  participant httpx.AsyncClient

  check_price->>BaseAdapter: fetch_headers(link_url)
  BaseAdapter-->>check_price: extra_headers oder None
  check_price->>BaseAdapter: warmup_url(link_url)
  BaseAdapter-->>check_price: warmup_url oder None
  check_price->>_fetch_httpx: URL, extra_headers, warmup_url
  _fetch_httpx->>httpx.AsyncClient: optionaler Warmup-GET
  _fetch_httpx->>httpx.AsyncClient: eigentlicher Fetch mit gemergten Headern
  httpx.AsyncClient-->>_fetch_httpx: HTML
Loading

Poem

Ein Hase tippt im Code ganz leis,
und springt durch Shops auf HTTPX-Kreis 🐰
Mit Headern, Warmup, Adapterklang,
hüpft er durchs Netz den ganzen Tag entlang.
Im Dashboard blinken Alerts so fein,
und Zielpreise tanzen ins Licht hinein.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive Der Titel ist sehr allgemein und beschreibt die Änderungen am Scraper nur unzureichend. Wähle einen konkreten Titel, der die Hauptänderung nennt, z. B. neue Shop-Adapter oder HTTPX-Fetch-Verbesserungen.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch product-scraper

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
app/shop_adapters/_amazon.py (2)

52-56: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

CAPTCHA-Erkennung ist eng gefasst.

Es wird nur nach form[action*='validateCaptcha'] gesucht. Andere Amazon-Blockseiten-Varianten (z. B. abweichendes Markup ohne dieses Formular) würden nicht als blocked erkannt, sondern fallen in den generischen "Price element not found"-Error-Pfad. Ein sicherer Fallback existiert bereits, daher nur eine Anregung zur Robustheit — z. B. zusätzlich auf typische Captcha-Texte oder den URL-Pfad /errors/validateCaptcha prüfen.

♻️ Möglicher robusterer Check
-        if tree.css_first("form[action*='validateCaptcha']"):
+        if tree.css_first("form[action*='validateCaptcha']") or "/errors/validateCaptcha" in url:
             return AdapterResult(
                 status="blocked",
                 error_message="Amazon returned a CAPTCHA challenge page.",
             )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/shop_adapters/_amazon.py` around lines 52 - 56, The CAPTCHA detection in
the Amazon adapter is too narrow because `AmazonAdapter` only checks for
`form[action*='validateCaptcha']`, so other block pages can slip through to the
generic missing-price error path. Update the blocked-page check in the adapter’s
parsing flow to also recognize common Amazon CAPTCHA indicators such as typical
CAPTCHA text and the `/errors/validateCaptcha` URL pattern, while keeping the
existing fallback to `blocked` when these signals are present.

49-95: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Fehlende Testabdeckung für extract().

Für die zentrale Extraktionslogik (success/error/blocked-Pfade, Preis-Parsing-Fehler, fehlende Elemente) existieren keine Tests. Da dies der kritische Pfad des neuen Adapters ist, wäre eine Unit-Test-Abdeckung sinnvoll.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/shop_adapters/_amazon.py` around lines 49 - 95, The Amazon adapter’s
central extract() flow currently has no unit tests covering the blocked, error,
and success paths. Add focused tests for _amazon.py’s extract method to verify
the CAPTCHA branch, missing price element behavior, parse_price failure
handling, and a successful extraction with title, price, and availability. Use
the existing AdapterResult outputs and the extract/parse_price symbols to keep
the tests targeted and resilient to HTML changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/shop_adapters/_amazon.py`:
- Around line 52-56: The CAPTCHA detection in the Amazon adapter is too narrow
because `AmazonAdapter` only checks for `form[action*='validateCaptcha']`, so
other block pages can slip through to the generic missing-price error path.
Update the blocked-page check in the adapter’s parsing flow to also recognize
common Amazon CAPTCHA indicators such as typical CAPTCHA text and the
`/errors/validateCaptcha` URL pattern, while keeping the existing fallback to
`blocked` when these signals are present.
- Around line 49-95: The Amazon adapter’s central extract() flow currently has
no unit tests covering the blocked, error, and success paths. Add focused tests
for _amazon.py’s extract method to verify the CAPTCHA branch, missing price
element behavior, parse_price failure handling, and a successful extraction with
title, price, and availability. Use the existing AdapterResult outputs and the
extract/parse_price symbols to keep the tests targeted and resilient to HTML
changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c416d2d-b700-4031-9899-059b65c86215

📥 Commits

Reviewing files that changed from the base of the PR and between c710f71 and 07a8d90.

📒 Files selected for processing (4)
  • app/price_check_service.py
  • app/shop_adapters/_amazon.py
  • app/shop_adapters/base.py
  • app/shop_adapters/registry.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/shop_adapters/_ebay.py (1)

15-51: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Domain-Matching in fetch_headers/warmup_url ignoriert das neue Suffix-Fallback aus registry.py.

get_adapter() in registry.py liefert diesen Adapter jetzt auch für Subdomains eines registrierten eBay-Hosts (z. B. cgi.ebay.com, m.ebay.de) über die neue Suffix-Logik. fetch_headers/warmup_url machen aber einen exakten Lookup auf _ACCEPT_LANGUAGE.get(domain) mit dem vollen Hostnamen (nur www. wird entfernt) — für eine solche Subdomain gäbe es dort keinen Treffer, wodurch Accept-Language und Warmup-Request stillschweigend entfallen, obwohl der Adapter aktiv für diese URL ausgewählt wurde.

Empfehlung: Domain-Auflösung analog zum Suffix-Matching in registry.get_adapter durchführen (z. B. gemeinsame Hilfsfunktion), statt eines reinen exakten Dict-Lookups.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/shop_adapters/_ebay.py` around lines 15 - 51, `EbayAdapter.fetch_headers`
and `EbayAdapter.warmup_url` currently do an exact `_ACCEPT_LANGUAGE` lookup
after only stripping `www.`, so URLs matched via the new suffix logic in
`registry.get_adapter` (for example subdomains like `cgi.ebay.com` or
`m.ebay.de`) lose both the `Accept-Language` header and warmup request. Update
domain resolution in `EbayAdapter` to mirror `registry.get_adapter`’s suffix
matching, ideally via a shared helper, so the adapter can derive the registered
eBay host from subdomains before looking up `_ACCEPT_LANGUAGE` and building the
homepage warmup URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/templates/dashboard/index.html`:
- Line 110: The hover state uses a non-standard Tailwind color token, so replace
the `hover:bg-gray-750` usage in the dashboard template with an existing
Tailwind gray shade that is already available. Update the class list where the
button/card styling is defined so the hover background applies correctly without
requiring a custom palette extension.

---

Nitpick comments:
In `@app/shop_adapters/_ebay.py`:
- Around line 15-51: `EbayAdapter.fetch_headers` and `EbayAdapter.warmup_url`
currently do an exact `_ACCEPT_LANGUAGE` lookup after only stripping `www.`, so
URLs matched via the new suffix logic in `registry.get_adapter` (for example
subdomains like `cgi.ebay.com` or `m.ebay.de`) lose both the `Accept-Language`
header and warmup request. Update domain resolution in `EbayAdapter` to mirror
`registry.get_adapter`’s suffix matching, ideally via a shared helper, so the
adapter can derive the registered eBay host from subdomains before looking up
`_ACCEPT_LANGUAGE` and building the homepage warmup URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5997baba-4e70-468b-9dd4-ed014c5e15c3

📥 Commits

Reviewing files that changed from the base of the PR and between 07a8d90 and 63cc497.

📒 Files selected for processing (15)
  • CLAUDE.md
  • README.md
  • app/price_check_service.py
  • app/routes/shop_rules.py
  • app/shop_adapters/_3djake.py
  • app/shop_adapters/_amazon.py
  • app/shop_adapters/_anycubic.py
  • app/shop_adapters/_ebay.py
  • app/shop_adapters/_elegoo.py
  • app/shop_adapters/_esun.py
  • app/shop_adapters/_prusa.py
  • app/shop_adapters/base.py
  • app/shop_adapters/registry.py
  • app/templates/dashboard/index.html
  • migrations/versions/20260702_1108_033d388a81e3_rename_spool_status_enum_members_to_.py
💤 Files with no reviewable changes (3)
  • app/shop_adapters/_esun.py
  • app/shop_adapters/_amazon.py
  • migrations/versions/20260702_1108_033d388a81e3_rename_spool_status_enum_members_to_.py
✅ Files skipped from review due to trivial changes (3)
  • README.md
  • app/routes/shop_rules.py
  • CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/price_check_service.py

Comment thread app/templates/dashboard/index.html
@Erik05Master
Erik05Master marked this pull request as ready for review July 7, 2026 08:21
@Erik05Master
Erik05Master merged commit a0682da into master Jul 7, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant