Skip to content

Harden salary parsing against malformed job-board data - #380

Open
codechrl wants to merge 1 commit into
speedyapply:mainfrom
codechrl:fix/harden-scraper-parsing
Open

Harden salary parsing against malformed job-board data#380
codechrl wants to merge 1 commit into
speedyapply:mainfrom
codechrl:fix/harden-scraper-parsing

Conversation

@codechrl

@codechrl codechrl commented Aug 8, 2026

Copy link
Copy Markdown

Summary

Three parsing paths could raise and abort a scrape when a job board returned an
unusual salary/compensation field. Each is a single malformed value taking down
more than its own row.

Changes

  • currency_parser (jobspy/util.py) — non-numeric salary text
    ("Negotiable", "Competitive") reduces to "" and hit float("")
    ValueError. Now returns None, matching how callers already treat a missing
    value.
  • LinkedIn _parse_job (jobspy/linkedin/__init__.py) — a single-value
    salary ("$120,000+", no - range) indexed salary_values[1]
    IndexError; and int(None) raised once currency_parser can return None.
    Now parses defensively and only builds Compensation when both bounds are
    numeric.
  • convert_to_annual (jobspy/util.py) — raised KeyError on a missing
    interval and TypeError (None *= n) on a null min/max. Now scales only
    present amounts and no-ops on an unknown interval.

Testing

tests/test_util_parsing.py covers all three (non-numeric → None, missing
interval no-op, null amount, and unchanged behavior for normal values). Existing
salary parsing for normal ranges is unaffected.

Three crashes that could abort a scrape when a board returned an unusual
salary field:

- currency_parser raised ValueError on non-numeric text ('Negotiable',
  'Competitive') because it reduced to '' and called float(''). It now returns
  None, matching how callers already treat a missing value.
- LinkedIn _parse_job indexed salary_values[1] unconditionally, so a
  single-value salary ('$120,000+', no range) raised IndexError; and int(None)
  raised once currency_parser could return None. It now parses defensively and
  only builds Compensation when both bounds are numeric.
- convert_to_annual raised KeyError on a missing 'interval' and TypeError on a
  null min/max amount ('None *= n'). It now scales only present amounts and
  no-ops on an unknown interval.

Adds tests/test_util_parsing.py covering all three.
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