Initial commit: LinkedIn job scraper for Basel area

- Paginated HTML scraper (up to 6 pages, 400ms delay between requests)
- Card-boundary-safe parsing to prevent field bleed across cards
- Language filter: drops German (m/w/d, umlauts) and French (H/F, accents) titles
- Software-role filter: requires title to contain a relevant tech term
- Global deduplication by job ID across runs
- 30-day recency filter via LinkedIn f_TPR parameter
- CSV output: date_found, posted_at, search, title, company, link
This commit is contained in:
2026-05-05 13:43:17 +02:00
commit b5a6f58fe3
6 changed files with 401 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
export type WorkType = "onsite" | "remote" | "hybrid";
export type JobType = "full-time" | "part-time" | "contract" | "temporary" | "internship";
export type TimePosted = "day" | "week" | "month";
export type Seniority = "internship" | "entry" | "associate" | "mid-senior" | "director" | "executive";
export interface SearchConfig {
label: string;
/** Use a raw LinkedIn URL instead of building one from filters. */
url?: string;
keywords?: string;
geoId?: string;
location?: string;
workType?: WorkType[];
jobType?: JobType[];
timePosted?: TimePosted;
seniority?: Seniority[];
}
const KEYWORDS = [
"Software Engineer",
"Solutions Engineer",
"Full Stack Engineer",
"Backend Engineer",
"Data Engineer",
"AI Engineer",
"Platform Engineer",
"DevOps Engineer",
"Staff Engineer",
"Principal Engineer",
"Tech Lead",
"Developer",
"Ruby on Rails",
"Python",
"Node.js",
"TypeScript",
].join(" OR ");
// --- Define your searches here ---
export const searches: SearchConfig[] = [
{
label: "Basel (city)",
keywords: KEYWORDS,
geoId: "103383283",
location: "Basel",
workType: ["onsite", "hybrid"],
timePosted: "month",
},
{
label: "Basel Metropolitan Area",
keywords: KEYWORDS,
geoId: "90009885",
location: "Basel Metropolitan Area",
workType: ["onsite", "hybrid"],
timePosted: "month",
},
{
label: "Basel-Country",
keywords: KEYWORDS,
geoId: "107117530",
location: "Basel-Country",
workType: ["onsite", "hybrid"],
timePosted: "month",
},
];