connecteur WooCommerce : sitemaps Yoast/AIOSEO et permaliens personnalisés
- locs() : ne garder que les <loc> du namespace sitemap (les sitemaps Yoast/AIOSEO embarquent des <image:loc> wp-content qui polluaient la liste), avec repli filtré pour les sitemaps sans namespace - inventaire : accepter les bases de permalien personnalisées (ex. /project/ sur mobilierurbain.ca) en plus de /produit|/product - sync : si la route liste est cassée (500 fatal) mais les fiches unitaires répondent, repli sitemap + fiches par slug (_sitemap_slug_fallback) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 changed file +19 −3
modified
fabrika/connectors/woocommerce.py
+19 −3
@@ -207,8 +207,15 @@ class WooCommerceConnector(BaseConnector): | ||
| 207 | 207 | try: |
| 208 | 208 | r = self.get(url) |
| 209 | 209 | root = ET.fromstring(r.content) |
| 210 | − return [e.text.strip() for e in root.iter() | |
| 211 | − if e.tag.endswith("loc") and e.text] | |
| 210 | + # <loc> du namespace sitemap seulement : les sitemaps Yoast/AIOSEO | |
| 211 | + # embarquent aussi des <image:loc> (URLs wp-content à exclure) | |
| 212 | + out = [e.text.strip() for e in root.iter( | |
| 213 | + "{http://www.sitemaps.org/schemas/sitemap/0.9}loc") if e.text] | |
| 214 | + if not out: | |
| 215 | + out = [e.text.strip() for e in root.iter() | |
| 216 | + if e.tag.endswith("loc") and e.text | |
| 217 | + and "/wp-content/" not in e.text] | |
| 218 | + return out | |
| 212 | 219 | except Exception: |
| 213 | 220 | return [] |
| 214 | 221 | |
@@ -224,8 +231,12 @@ class WooCommerceConnector(BaseConnector): | ||
| 224 | 231 | if sm in seen: |
| 225 | 232 | continue |
| 226 | 233 | seen.add(sm) |
| 234 | + # base de permalien standard (/produit/, /product/) OU personnalisée | |
| 235 | + # (ex. /project/ sur mobilierurbain.ca) : les sitemaps candidats ne | |
| 236 | + # listent que des produits, on accepte tout URL /base/slug/ | |
| 227 | 237 | product_urls += [u for u in locs(sm) |
| 228 | − if re.search(r"/(?:produit|product)/[^/]+/?$", u)] | |
| 238 | + if re.search(r"/(?:produit|product)/[^/]+/?$", u) | |
| 239 | + or re.fullmatch(r"https?://[^/]+/[^/]+/[^/]+/?", u)] | |
| 229 | 240 | slugs = [] |
| 230 | 241 | slug_seen: set[str] = set() |
| 231 | 242 | for u in product_urls: |
@@ -267,6 +278,11 @@ class WooCommerceConnector(BaseConnector): | ||
| 267 | 278 | html_out = self._html_fallback() |
| 268 | 279 | if html_out: |
| 269 | 280 | return html_out |
| 281 | + # Route liste cassée (500 fatal) mais fiches unitaires parfois | |
| 282 | + # saines (ex. mobilierurbain.ca) : tenter sitemap + fiches par slug | |
| 283 | + slug_out = self._sitemap_slug_fallback() | |
| 284 | + if slug_out: | |
| 285 | + return slug_out | |
| 270 | 286 | raise first_page_exc |
| 271 | 287 | |
| 272 | 288 | if not out and first_page_exc is None: |
| 273 | 289 | |