Skip to content

fix: align URL pattern matching and limit semantics with crawlee-js - #2166

Open
atirna wants to merge 1 commit into
apify:masterfrom
atirna:fix/enqueue-links-js-parity
Open

fix: align URL pattern matching and limit semantics with crawlee-js#2166
atirna wants to merge 1 commit into
apify:masterfrom
atirna:fix/enqueue-links-js-parity

Conversation

@atirna

@atirna atirna commented Aug 16, 2026

Copy link
Copy Markdown

Description

Aligns enqueue_links / add_requests URL filtering with crawlee-js, following up on the differences found in the apify/crawlee#3533 review (thanks @vdusek for the detailed writeup).

  • Glob patterns now match case-insensitively, like Minimatch with nocase: true in JS (_utils/globs.py)
  • regex include/exclude patterns are matched with search instead of match, so they match anywhere in the URL like regexp.test in JS (crawler + SitemapRequestLoader, which mirrors url.match on the JS side)
  • limit now counts requests actually enqueued: applied last, after transform_request_function skipping, and duplicates already present in the queue don't consume it (JS decrements its maxNewRequests budget only for requests that weren't already there)

One thing worth calling out since @B4nan wanted more opinions on the regexp anchoring: I checked the JS side, and both enqueueLinks (createPatternObjectMatcher in packages/core/src/enqueue_links/shared.ts) and the sitemap loader (url.match(regexp) in packages/core/src/storages/sitemap_request_loader.ts) search unanchored, so a pattern like /\/products\// matching anywhere in the URL is the established cross-library behavior. That's what this implements.

Issues

Testing

before, on current master (172699b1):

  • Glob('https://Someplace.com/**/cats') did not match https://someplace.com/blog/category/cats
  • include=[re.compile(r'/category/cats')] enqueued nothing (the regex never matched at the start of the URL)
  • with limit=2 and a transform skipping 2 of 3 extracted links, the remaining link was not enqueued (limit burned slots on skipped URLs); URLs already in the queue also consumed the limit

after:

  • uv run pytest tests/unit/_utils/test_globs.py tests/unit/crawlers/_basic tests/unit/crawlers/_beautifulsoup tests/unit/request_loaders/test_sitemap_request_loader.py — new regression tests for all of the above (each fails on master, passes here), existing suite unaffected
  • uv run poe unit-tests — 2296 passed, 11 skipped
  • uv run poe lint / uv run poe type-check — clean

Checklist

  • CI passed

- Glob patterns now match case-insensitively (Minimatch nocase: true)
- Regex include/exclude patterns match unanchored, like regexp.test in JS
- enqueue_links limit counts newly enqueued requests, applied after
  transform_request_function and skipping duplicates already in the queue
- SitemapRequestLoader regex patterns follow the same unanchored semantics

Fixes apify#2122
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.

Align glob case-sensitivity, regexp anchoring, and limit/transform ordering with crawlee-js

2 participants