跳到正文
DEV Community· InApp·· 2 小時前AI 評分42

我的求職搜尋 API 發現薪酬範圍只是市場宣傳的虛構,令我重新思考「結構化數據」的含義

My job search API learned that salary ranges are marketing fiction — I had to rethink what 'structured data' means

AI 導讀

求職搜尋 API 的開發者發現,職位刊登的薪酬資料充滿噪音,遂把薪酬視為需要解讀的分佈,而非單一數值。約 30% 的職位刊登以文字而非數字填寫薪酬欄;API 會正規化金額、貨幣和薪酬週期,並從描述擷取估算數字。單一端點會按關鍵字和地點回傳正規化、去重的職位資料,並附上信心提示和來源備註。

正文

I built a job postings search API that returns title, company, location, salary, and a dozen other fields as clean JSON. Looked perfect in testing. Then I started actually using it as an agent — comparing offers, filtering by comp, alerting on new roles — and realized half the salary field was noise.

Here's what I found when I started treating the salary data as something to reason over rather than something to display:

The same role, three listings, four salaries. "Senior Engineer, Berlin" appeared from the same company with ranges of €70–90k, €85–110k, and one posting with no salary at all. The dedup key I'd chosen (title + company) was fine, but the data wasn't. I ended up clustering by normalized title + company + location and treating salary as a distribution, not a point.

'Competitive' is a value. About 30% of postings put a string where the schema expected a number. My first instinct was to drop those rows. That threw away a third of the market. Now I parse what I can, flag the rest, and let the caller decide.

Currency is a lie until you normalize. I saw "£60k", "60000 GBP", "60,000£", and "€60.000" — European decimal comma, attached symbols, pre-tax vs gross vs TC labels buried in the description. I added a normalization pass that extracts amount + currency + period (annual/monthly/hourly) and converts to a common annual figure. It's still wrong sometimes, but it's consistently wrong in a way I can filter on.

The description is the real salary field. The structured salary is often a placeholder. The actual number usually lives in a sentence like "compensation up to €95k depending on experience." I added a light extraction pass that pulls candidate figures from the description and marks them as estimated: true so downstream agents don't treat them as authoritative.

This changed how I think about APIs that return "structured data." The structure is the easy part. The meaning — what a salary range actually represents, who posted it, when it was last updated, whether it's gross or net — is where the value is. My API now returns the raw fields plus a confidence hint and a source_note. It's messier. It's also actually useful.

I packaged the whole thing as a single endpoint that takes keywords + locations and returns normalized, deduplicated postings: https://x402.freeq.one/tools/jobs.html

If you're building agents that make decisions over scraped or aggregated data, spend the time on the normalization layer. The schema is not the product. The interpretation is.

來源:DEV Community · dev.to