Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Die Bundesagentur für Arbeit verfügt über die größte Datenbank für offene


## Authentifizierung
ie Authentifizierung funktioniert über die clientId:
Die Authentifizierung funktioniert über die clientId:

**clientId:** jobboerse-jobsuche

Expand Down Expand Up @@ -95,12 +95,12 @@ Angebotsart: 1=ARBEIT; 2=SELBSTAENDIGKEIT; 4=AUSBILDUNG/Duales Studium; 34=Prakt
Befristung: 1 = befristet; 2 = unbefristet. Mehrere Semikolon-separierte Werte möglich (z.B. befristung=1;2).


Parameter: behinderung (Optional)
**Parameter:** *behinderung* (Optional)
- false
- true


Parameter: corona (Optional)
**Parameter:** *corona* (Optional)
- false
- true

Expand Down
67 changes: 42 additions & 25 deletions api_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import base64
import urllib.parse
from typing import Any, Dict, Optional

import requests

HEADERS = {
Expand All @@ -8,8 +11,13 @@
'Connection': 'keep-alive',
}

def search(what, where):
"""search for jobs. params can be found here: https://jobsuche.api.bund.dev/"""

def search(what: str, where: str) -> Dict[str, Any]:
"""Stellenanzeigen suchen.

Die verfügbaren Parameter sind unter https://jobsuche.api.bund.dev/
dokumentiert.
"""
params = (
('angebotsart', '1'),
('page', '1'),
Expand All @@ -19,48 +27,57 @@ def search(what, where):
('was', what),
('wo', where),
)
response = requests.get('https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc/v4/app/jobs',
headers=HEADERS, params=params, verify=False)
response = requests.get(
'https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc/v4/app/jobs',
headers=HEADERS, params=params, timeout=60)
response.raise_for_status()
return response.json()


def get_job_details(refnr):
"""Retrieve job details by refnr. The refnr is base64-encoded before sending."""
def get_job_details(refnr: str) -> Dict[str, Any]:
"""Jobdetails anhand der Referenznummer abrufen.

Die ``refnr`` wird vor dem Aufruf Base64-kodiert.
"""
encrypted = base64.b64encode(refnr.encode()).decode()
response = requests.get(
f'https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc/v4/jobdetails/{encrypted}',
headers=HEADERS, verify=False)
headers=HEADERS, timeout=60)
response.raise_for_status()
return response.json()


def get_employer_logo(kundennummer_hash):
"""Retrieve employer logo by arbeitgeberKundennummerHash from job details.
Returns None if no logo is available (404).
def get_employer_logo(kundennummer_hash: str) -> Optional[bytes]:
"""Arbeitgeberlogo anhand des ``arbeitgeberKundennummerHash`` abrufen.

Gibt ``None`` zurück, wenn kein Logo für diesen Arbeitgeber hinterlegt
ist (HTTP 404). Dies ist ein regulärer Fall, kein Fehler.
"""
import urllib.parse
encoded_hash = urllib.parse.quote(kundennummer_hash, safe='')
response = requests.get(
f'https://rest.arbeitsagentur.de/vermittlung/ag-darstellung-service/ct/v1/arbeitgeberlogo/{encoded_hash}',
headers=HEADERS, verify=False)
headers=HEADERS, timeout=60)
if response.status_code == 404:
return None
response.raise_for_status()
return response.content


result = search("bahn", "berlin")
if __name__ == "__main__":
result = search("bahn", "berlin")

refnr = result['stellenangebote'][0]["refnr"]
print("refnr:", refnr)
refnr = result['stellenangebote'][0]["refnr"]
print("refnr:", refnr)

details = get_job_details(refnr)
print("Titel:", details.get("stellenangebotsTitel") or details.get("titel"))
details = get_job_details(refnr)
print("Titel:", details.get("stellenangebotsTitel") or details.get("titel"))

kundennummer_hash = details.get("arbeitgeberKundennummerHash")
if kundennummer_hash:
logo = get_employer_logo(kundennummer_hash)
if logo:
print("Logo gefunden, Größe:", len(logo), "Bytes")
kundennummer_hash = details.get("arbeitgeberKundennummerHash")
if kundennummer_hash:
logo = get_employer_logo(kundennummer_hash)
if logo:
print("Logo gefunden, Größe:", len(logo), "Bytes")
else:
print("Kein Logo für diesen Arbeitgeber vorhanden.")
else:
print("Kein Logo für diesen Arbeitgeber vorhanden.")
else:
print("Kein arbeitgeberKundennummerHash – kein Logo verfügbar.")
print("Kein arbeitgeberKundennummerHash – kein Logo verfügbar.")
22 changes: 18 additions & 4 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ paths:
example: true
description: Gibt an, ob Jobs von Zeitarbeitsfirmen in die Suchergebnisse einbezogen werden sollen (default true).
required: false
- in: query
name: pav
schema:
type: boolean
example: false
description: Private Arbeitsvermittlung. Gibt an, ob Jobs von privaten Arbeitsvermittlungen in die Suchergebnisse einbezogen werden sollen.
required: false
- in: query
name: angebotsart
schema:
Expand All @@ -97,7 +104,7 @@ paths:
- 2
example: 1
required: false
description: Semikolon-separierte mehrere Werte möglich (z.B. befristung=1;2) 1 = befristet; 2 = unbefristet
description: "Befristung: 1 = befristet, 2 = unbefristet. Mehrere Werte können semikolon-separiert übergeben werden (z.B. befristung=1;2)."
- in: query
name: arbeitszeit
schema:
Expand All @@ -108,7 +115,7 @@ paths:
- snw
- ho
- mj
description: Semikolon-separierte mehrere Werte möglich (z.B. arbeitszeit=vz;tz) vz=VOLLZEIT, tz=TEILZEIT, snw=SCHICHT_NACHTARBEIT_WOCHENENDE, ho=HEIM_TELEARBEIT, mj=MINIJOB
description: "Arbeitszeit: vz=VOLLZEIT, tz=TEILZEIT, snw=SCHICHT_NACHTARBEIT_WOCHENENDE, ho=HEIM_TELEARBEIT, mj=MINIJOB. Mehrere Werte können semikolon-separiert übergeben werden (z.B. arbeitszeit=vz;tz)."
example: vz
required: false

Expand Down Expand Up @@ -201,6 +208,13 @@ paths:
example: true
description: Gibt an, ob Jobs von Zeitarbeitsfirmen in die Suchergebnisse einbezogen werden sollen (default true).
required: false
- in: query
name: pav
schema:
type: boolean
example: false
description: Private Arbeitsvermittlung. Gibt an, ob Jobs von privaten Arbeitsvermittlungen in die Suchergebnisse einbezogen werden sollen.
required: false
- in: query
name: angebotsart
schema:
Expand All @@ -222,7 +236,7 @@ paths:
- 2
example: 1
required: false
description: Semikolon-separierte mehrere Werte möglich (z.B. befristung=1;2) 1 = befristet; 2 = unbefristet
description: "Befristung: 1 = befristet, 2 = unbefristet. Mehrere Werte können semikolon-separiert übergeben werden (z.B. befristung=1;2)."
- in: query
name: arbeitszeit
schema:
Expand All @@ -233,7 +247,7 @@ paths:
- snw
- ho
- mj
description: Semikolon-separierte mehrere Werte möglich (z.B. arbeitszeit=vz;tz) vz=VOLLZEIT, tz=TEILZEIT, snw=SCHICHT_NACHTARBEIT_WOCHENENDE, ho=HEIM_TELEARBEIT, mj=MINIJOB
description: "Arbeitszeit: vz=VOLLZEIT, tz=TEILZEIT, snw=SCHICHT_NACHTARBEIT_WOCHENENDE, ho=HEIM_TELEARBEIT, mj=MINIJOB. Mehrere Werte können semikolon-separiert übergeben werden (z.B. arbeitszeit=vz;tz)."
example: vz
required: false

Expand Down