All notable changes to this project will be documented in this file.
- 🚨 Fixed runs failing and saving nothing after scraping successfully. Larger runs were finishing every page correctly and then losing the entire result set at the final save step, ending as a failed run with zero rows. Jobs that list employer benefits were the trigger, so the bigger the run, the more likely it hit. Those runs now complete and keep their rows.
- 🛡️ One unusual job can no longer discard an entire run's results. If a single row is ever refused, only that row is skipped and reported; every other job still ships.
- 🎁 Employer benefits now actually arrive. Benefits such as 五险一金, 绩效奖金, and 餐补 are delivered as a clean list, with a companion field grouping them under the category the source files them beneath. Jobs with no published benefits stay honestly empty.
- 🔢 Run summaries now report the number of rows genuinely saved rather than the number attempted.
- 📈 Recruiter responsiveness scoring: every job now includes a 0-100 responsiveness score, plus the underlying signals (last reply time, expected reply window, today's reply count, active-now/active-today flags), so you can sort and filter down to recruiters who are actually replying. New
minRecruiterResponsiveness input filter.
- 📊 Real search coverage: a search now reaches its true result depth (previously capped far short of what the source actually returns) instead of stopping early every time.
maxItems can go up to 2,000.
- 🗺️ Added sub-district street and named commercial-area fields when the source provides more location detail than city district alone.
- 💰 Salary is now read from the source's own normalized numeric range when available, falling back to the existing parser otherwise.
- 🐛 Fixed a search that legitimately matches nothing incorrectly failing the run. This was very likely the largest single cause of failed runs; a zero-result search now completes successfully with zero rows, as it always should have.
- 🛡️ A search that fails partway through no longer discards jobs already collected from other searches in the same run. Only the affected search's coverage is marked incomplete; everything else still ships.
- 🧹 Corrected a mislabeled field that was presenting job skill tags as employer benefits; the real benefits field is used instead, and is honestly empty when the source has no benefits data for a listing.
- 🔧 Job function/category tagging on detail-enriched rows, previously always empty due to a source field mismatch, now populates correctly.
- ⚡ Lowered the default result cap so a standard run finishes faster.
- 🧭 Replaced the CAPTCHA-prone legacy HTML state parser with Zhaopin's public JSON search API.
- ✅ Fixed
Work Experience and Employment Type searches returning empty datasets despite an advertised result count.
- 🛡️ Treat API schema changes, source errors, and non-empty result counts with empty pages as retryable failures; failed runs never save partial rows or monitoring state.
- ⚡ Added typed API pagination, bounded retries, a 20-request-per-minute cap, and a datacenter-proxy fallback only after a direct API request fails.
- 📋 Added the non-chargeable
run-diagnostics record with request, retry, and proxy-fallback counts.
- 💸 Reduced the default run memory from 512 MB to 256 MB after measuring a maximum 84 MB peak across recent successful runs. Store pricing is unchanged.
- 🔔 Added optional HTTPS webhook delivery for successful incremental monitoring runs.
- 🎯 Added selectable
NEW, UPDATED, REAPPEARED, and EXPIRED notification triggers.
- 💓 Added an opt-in no-change heartbeat for scheduled monitor health checks.
- 🛡️ Webhook endpoints are secret inputs, must use HTTPS, cannot target local or private networks, and cannot redirect requests.
- ⏱️ Delivery uses bounded samples, timeouts, and retries without changing monitoring state or invalidating successful scrape results.
- 🔎 Expanded Store and search-engine coverage for China jobs, China salary data, and 智联招聘数据采集.
- 📊 Clarified the normalized salary fields and their use in labor-market and hiring-intelligence workflows.
- 🚀 Simplified the Store first run to one
Python search in Beijing with 20 results.
- 🧭 Kept batch keywords and batch cities empty in the prefilled form so new users do not accidentally launch six searches.
- 🔌 Preserved the existing API and scheduler defaults for backward compatibility.
- 📋 Added a non-chargeable
run-summary Key-Value Store record and Output-tab link with current-job, emitted-row, and monitoring change counts.
- ✅ Added an explicit
zeroChangeRun signal so an intentionally empty monitoring dataset is distinguishable from a failed run.
- 🔒 Normalized public Zhaopin job links to HTTPS.
- 🔄 Prevented legacy HTTP links and their canonical HTTPS equivalents from producing spurious
UPDATED monitoring rows.
- ✨ Added multi-keyword and multi-city batches so one run can cover several China hiring markets.
- 🔄 Added optional job monitoring with new, updated, reappeared, unchanged, and expired states.
- 🕒 Added first-seen, last-seen, source-posted, and expiry timestamps for longitudinal datasets.
- 📦 Added compact output for alerts, databases, spreadsheets, and AI workflows.
- ➕ Added salary, company type, company size, and exact-search controls.
- 📊 Added a dedicated Hiring Changes dataset view.
- ⚡ Changed the result limit to apply to each keyword and city search in a batch.
- 🧹 Removed empty values from saved rows while preserving genuine zero and false values.
- 📈 Repositioned the Store listing around recurring China hiring data and labor-market intelligence.
- 🐛 Fixed missing publication dates being replaced with unrelated timestamps.
- 🛠️ Fixed blocked or malformed pages being treated as successful empty runs.
- 🛡️ Prevented failed, partial, or coverage-limited runs from expiring saved jobs.
- 🔗 Added quick links to our other 3 China jobs actors, so you can find mainstream, tech, and white-collar job leads all in one place.