Working Nomads Elasticsearch API 客户端
| 4 | |
| 5 | |
| 6 | class WorkingNomadsAPI: |
| 7 | """Working Nomads Elasticsearch API 客户端""" |
| 8 | |
| 9 | BASE_URL = "https://www.workingnomads.com/jobsapi/_search" |
| 10 | |
| 11 | POSITION_TYPES = {"ft": "Full-time", "fr": "Freelance", "pt": "Part-time"} |
| 12 | |
| 13 | def __init__(self): |
| 14 | self.session = requests.Session() |
| 15 | self.session.headers.update( |
| 16 | { |
| 17 | "Content-Type": "application/json", |
| 18 | "User-Agent": "WorkingNomads-Scraper/1.0", |
| 19 | } |
| 20 | ) |
| 21 | |
| 22 | def fetch_jobs( |
| 23 | self, |
| 24 | category: str = "Development", |
| 25 | size: int = 50, |
| 26 | salary_min: int = None, |
| 27 | salary_max: int = None, |
| 28 | ) -> list[dict]: |
| 29 | """ |
| 30 | 从 Working Nomads API 获取职位数据 |
| 31 | """ |
| 32 | query = self._build_query(category, salary_min, salary_max) |
| 33 | |
| 34 | payload = { |
| 35 | "track_total_hits": True, |
| 36 | "from": 0, |
| 37 | "size": size, |
| 38 | "_source": [ |
| 39 | "id", |
| 40 | "title", |
| 41 | "company", |
| 42 | "category_name", |
| 43 | "description", |
| 44 | "position_type", |
| 45 | "salary_range", |
| 46 | "annual_salary_usd", |
| 47 | "tags", |
| 48 | "locations", |
| 49 | "apply_url", |
| 50 | "pub_date", |
| 51 | "experience_level", |
| 52 | ], |
| 53 | "query": query, |
| 54 | } |
| 55 | |
| 56 | response = self.session.post(self.BASE_URL, json=payload) |
| 57 | response.raise_for_status() |
| 58 | |
| 59 | data = response.json() |
| 60 | return data["hits"]["hits"] |
| 61 | |
| 62 | def _build_query(self, category: str, salary_min: int, salary_max: int) -> dict: |
| 63 | """构建 Elasticsearch 查询""" |