Skip to content
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.11 (2026-07-23)
### Fixed
- Fix HH pegel page scraping

## 1.0.10 (2026-02-17)
### Fixed
- Fix HE without flow (add FetchError class)
Expand Down
24 changes: 24 additions & 0 deletions docs/pegel.json
Original file line number Diff line number Diff line change
Expand Up @@ -1816,32 +1816,46 @@
"HE_44850108": "Hümme / Esse",
"HE_44950055": "Helmarshausen / Diemel",
"HE_45100100": "Bad_Karlshafen / Weser",
"HH_5950081": "Este Inneres Sperrwerk BP / Este",
"HH_5950082": "Este Inneres Sperrwerk AP / Este",
"HH_80000001": "Hintzenort / Alte Süderelbe",
"HH_99003": "Brügkamp / Ammersbek",
"HH_99004": "Lottbektal / Lottbek",
"HH_99006": "Herrenhausallee / Ammersbek",
"HH_99007": "Vogt-Kölln-Straße / Kollau",
"HH_99014": "Wohldorfer Damm / Bredenbek",
"HH_99015": "RHB Wohldorfer Damm / RHB Bredenbek/Hörndiek",
"HH_99019": "Poppenbüttler Hauptstraße / Mellingbek",
"HH_99020": "Bergstedter Chaussee / Saselbek",
"HH_99021": "Schleuse Poppenbüttel / Alster",
"HH_99023": "Teetzparkweg / Susebek",
"HH_99024": "Hafen Bergedorf / Schleusengraben",
"HH_99045": "Klövensteenweg / Wedeler Au",
"HH_99070": "Grotmannskroog / Wandse",
"HH_99072": "Delingsdorfer Weg / Wandse",
"HH_99077": "Rahlstedter Straße / Stellau",
"HH_99079": "Wilhelm-Grimm-Straße / Wandse",
"HH_99080": "Dove-Elbe Schleuse / Dove-Elbe",
"HH_99081": "Bei der blauen Brücke / Dove-Elbe",
"HH_99082": "Wulffsbrücke / Gose-Elbe",
"HH_99083": "Krugkoppelbrücke / Alster",
"HH_99084": "Heinrich-Stubbe-Brücke / Gose-Elbe",
"HH_99091": "Mantiusstraße / Bille",
"HH_99102": "Neuländer Elbdeich / Neuländer Wettern, Brack",
"HH_99109": "Nordschleswiger Straße / Osterbek",
"HH_99116": "Gotthelfweg / Außenmühlenteich",
"HH_99121": "Fünfhausener Landweg / Fünfhausener Landwegwettern",
"HH_99136": "Olloweg / Mühlenau",
"HH_99137": "Billstedter Hauptsraße / Schleemer Bach",
"HH_99154": "Niendorfer Weg / Tarpenbek",
"HH_99176": "Finkenwerder Landscheideweg / Finkenwerder Landscheide",
"HH_99182": "Pollhof / Alte Brookwetterung",
"HH_99210": "Bramfelder Straße / Seebek",
"HH_99256": "Rahmoor / Tarpenbek",
"HH_99294": "Nordmeerstraße / Nordmeergraben",
"HH_99304": "Krohnstieg (RHB) / Tarpenbek",
"HH_99306": "An der Steinbek / Glinder Au",
"HH_99313": "Neuenfelder Fährdeich / Liedenkummer Wettern",
"HH_99328": "Torfhuder Stieg / Ammersbek",
"HH_99329": "Berner Heerweg / Berner Au",
"HH_99341": "Wandsbeker Allee / Wandse",
Expand All @@ -1855,13 +1869,19 @@
"HH_99353": "Bäckerbrücke / Alster",
"HH_99387": "Neuenfelder Hinterdeich / Moorwettern",
"HH_99390": "An der Falkenbek / Falkengraben",
"HH_99391": "Dierksstegel / Scheidebach",
"HH_99410": "Am Osdorfer Born / Düpenau",
"HH_99421": "Jakobsberg (Einlagedeich) / Rethwettern",
"HH_99422": "Siedenfelder Weg / Bewässerungsgraben",
"HH_99428": "Grellkamp / Bornbach",
"HH_99486": "Lohe / Diekbek",
"HH_99487": "Horster Damm / Brookwetterung",
"HH_99559": "Jakobsberg (Jakobsweg) / Stillhorner Wettern",
"HH_99561": "Moldauweg / Neue Höder Wettern",
"HH_99562": "Wagenwerkweg / Seeve-Kanal",
"HH_99605": "Außenmühlenweg / Engelbach",
"HH_99636": "RHB Brügkamp / Ammersbek",
"HH_99642": "Karl-Arnold-Ring / Stübenhofer Wettern",
"HH_99643": "Allerm. Deich, Sportzentrum / Dove-Elbe",
"HH_99652": "Möllers Kamp / Schulenbrooksbek",
"MV_03127.0": "Bodstedt / Bodstedter Bodden",
Expand Down Expand Up @@ -2862,6 +2882,7 @@
"RP_4250640": "Epinal / Mosel",
"RP_5730610": "Toul / Mosel",
"RP_6051020": "Saint-Die / Meurthe",
"RP_6330": "Ouren / Our",
"RP_676101001": "Damelevières / Meurthe",
"RP_7": "Mersch / Alzette",
"RP_7010610": "Custines / Mosel",
Expand All @@ -2873,6 +2894,8 @@
"RP_9372050": "Bliesbruck / Blies",
"RP_9372053": "Frauenberg / Blies",
"RP_9402110": "Bousseviller / Hornbach",
"RP_9914": "Reuland / Our",
"RP_9926": "Schönberg / Our",
"SH_110005": "Wyk Foehr / Nordsee",
"SH_110006": "Hooge-Anleger / Nordsee",
"SH_110007": "Schlüttsiel AP / Nordsee",
Expand Down Expand Up @@ -3098,6 +3121,7 @@
"SN_10001580": "Kleinvoigtsberg 1 / Freiberger Mulde",
"SN_10001720": "Raschau 1 / Weiße Elster",
"SN_10001860": "Burgneudorf 1 / Kleine Spree",
"SN_10002000": "Flößberg / Eula",
"SN_1100001": "Rosenthal 1 / Lausitzer Neiße",
"SN_1100002": "Jänkendorf 1 / Schwarzer Schöps",
"SN_1100003": "Hartau 1 / Lausitzer Neiße",
Expand Down
24 changes: 24 additions & 0 deletions docs/pegel.md
Original file line number Diff line number Diff line change
Expand Up @@ -1817,32 +1817,46 @@
| HE_44850108 | Hümme / Esse |
| HE_44950055 | Helmarshausen / Diemel |
| HE_45100100 | Bad_Karlshafen / Weser |
| HH_5950081 | Este Inneres Sperrwerk BP / Este |
| HH_5950082 | Este Inneres Sperrwerk AP / Este |
| HH_80000001 | Hintzenort / Alte Süderelbe |
| HH_99003 | Brügkamp / Ammersbek |
| HH_99004 | Lottbektal / Lottbek |
| HH_99006 | Herrenhausallee / Ammersbek |
| HH_99007 | Vogt-Kölln-Straße / Kollau |
| HH_99014 | Wohldorfer Damm / Bredenbek |
| HH_99015 | RHB Wohldorfer Damm / RHB Bredenbek/Hörndiek |
| HH_99019 | Poppenbüttler Hauptstraße / Mellingbek |
| HH_99020 | Bergstedter Chaussee / Saselbek |
| HH_99021 | Schleuse Poppenbüttel / Alster |
| HH_99023 | Teetzparkweg / Susebek |
| HH_99024 | Hafen Bergedorf / Schleusengraben |
| HH_99045 | Klövensteenweg / Wedeler Au |
| HH_99070 | Grotmannskroog / Wandse |
| HH_99072 | Delingsdorfer Weg / Wandse |
| HH_99077 | Rahlstedter Straße / Stellau |
| HH_99079 | Wilhelm-Grimm-Straße / Wandse |
| HH_99080 | Dove-Elbe Schleuse / Dove-Elbe |
| HH_99081 | Bei der blauen Brücke / Dove-Elbe |
| HH_99082 | Wulffsbrücke / Gose-Elbe |
| HH_99083 | Krugkoppelbrücke / Alster |
| HH_99084 | Heinrich-Stubbe-Brücke / Gose-Elbe |
| HH_99091 | Mantiusstraße / Bille |
| HH_99102 | Neuländer Elbdeich / Neuländer Wettern, Brack |
| HH_99109 | Nordschleswiger Straße / Osterbek |
| HH_99116 | Gotthelfweg / Außenmühlenteich |
| HH_99121 | Fünfhausener Landweg / Fünfhausener Landwegwettern |
| HH_99136 | Olloweg / Mühlenau |
| HH_99137 | Billstedter Hauptsraße / Schleemer Bach |
| HH_99154 | Niendorfer Weg / Tarpenbek |
| HH_99176 | Finkenwerder Landscheideweg / Finkenwerder Landscheide |
| HH_99182 | Pollhof / Alte Brookwetterung |
| HH_99210 | Bramfelder Straße / Seebek |
| HH_99256 | Rahmoor / Tarpenbek |
| HH_99294 | Nordmeerstraße / Nordmeergraben |
| HH_99304 | Krohnstieg (RHB) / Tarpenbek |
| HH_99306 | An der Steinbek / Glinder Au |
| HH_99313 | Neuenfelder Fährdeich / Liedenkummer Wettern |
| HH_99328 | Torfhuder Stieg / Ammersbek |
| HH_99329 | Berner Heerweg / Berner Au |
| HH_99341 | Wandsbeker Allee / Wandse |
Expand All @@ -1856,13 +1870,19 @@
| HH_99353 | Bäckerbrücke / Alster |
| HH_99387 | Neuenfelder Hinterdeich / Moorwettern |
| HH_99390 | An der Falkenbek / Falkengraben |
| HH_99391 | Dierksstegel / Scheidebach |
| HH_99410 | Am Osdorfer Born / Düpenau |
| HH_99421 | Jakobsberg (Einlagedeich) / Rethwettern |
| HH_99422 | Siedenfelder Weg / Bewässerungsgraben |
| HH_99428 | Grellkamp / Bornbach |
| HH_99486 | Lohe / Diekbek |
| HH_99487 | Horster Damm / Brookwetterung |
| HH_99559 | Jakobsberg (Jakobsweg) / Stillhorner Wettern |
| HH_99561 | Moldauweg / Neue Höder Wettern |
| HH_99562 | Wagenwerkweg / Seeve-Kanal |
| HH_99605 | Außenmühlenweg / Engelbach |
| HH_99636 | RHB Brügkamp / Ammersbek |
| HH_99642 | Karl-Arnold-Ring / Stübenhofer Wettern |
| HH_99643 | Allerm. Deich, Sportzentrum / Dove-Elbe |
| HH_99652 | Möllers Kamp / Schulenbrooksbek |
| MV_03127.0 | Bodstedt / Bodstedter Bodden |
Expand Down Expand Up @@ -2863,6 +2883,7 @@
| RP_4250640 | Epinal / Mosel |
| RP_5730610 | Toul / Mosel |
| RP_6051020 | Saint-Die / Meurthe |
| RP_6330 | Ouren / Our |
| RP_676101001 | Damelevières / Meurthe |
| RP_7 | Mersch / Alzette |
| RP_7010610 | Custines / Mosel |
Expand All @@ -2874,6 +2895,8 @@
| RP_9372050 | Bliesbruck / Blies |
| RP_9372053 | Frauenberg / Blies |
| RP_9402110 | Bousseviller / Hornbach |
| RP_9914 | Reuland / Our |
| RP_9926 | Schönberg / Our |
| SH_110005 | Wyk Foehr / Nordsee |
| SH_110006 | Hooge-Anleger / Nordsee |
| SH_110007 | Schlüttsiel AP / Nordsee |
Expand Down Expand Up @@ -3099,6 +3122,7 @@
| SN_10001580 | Kleinvoigtsberg 1 / Freiberger Mulde |
| SN_10001720 | Raschau 1 / Weiße Elster |
| SN_10001860 | Burgneudorf 1 / Kleine Spree |
| SN_10002000 | Flößberg / Eula |
| SN_1100001 | Rosenthal 1 / Lausitzer Neiße |
| SN_1100002 | Jänkendorf 1 / Schwarzer Schöps |
| SN_1100003 | Hartau 1 / Lausitzer Neiße |
Expand Down
28 changes: 12 additions & 16 deletions docs/update_pegel_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,22 +226,18 @@ def get_he_stations() -> tuple[str, str]:
def get_hh_stations() -> tuple[str, str]:
"""Get all available stations for Hamburg."""
stations = []
data = fetch_soup("https://www.wabiha.de/karte.html")
tooltipwrapper = data.find("div", id="tooltipwrapper")
divs = tooltipwrapper.find_all("div", class_="tooltip-content")
for div in divs:
spans = div.find_all("span")
if len(spans) == 8:
ident = "HH_" + div["id"].split("-")[-1]
text = div.getText()
name = text[: text.find("Gewässer:")].strip()
name = (
name
+ " / "
+ text[
text.find("Gewässer:") + 9 : text.find("Niederschlagsvorhersage")
].strip()
)
data = fetch_soup("https://www.wabiha.de/pegel.html")
table = data.find_all("table", id="pegeltabelle")[0]
tbody = table.find_all("tbody")[0]
trs = tbody.find_all("tr")
for row in trs:
tds = row.find_all("td")
if len(tds) > 4:
river = tds[0].find("span").text.strip()
pegel_span = tds[1].find("span")
pegel_name = pegel_span.text.strip()
ident = "HH_" + pegel_span.get("title").split()[1]
name = pegel_name + " / " + river
stations.append((ident, name))
return stations

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "lhpapi"
version = "1.0.10"
version = "1.0.11"
authors = [
{ name="stephan192", email="stephan192@outlook.com" },
]
Expand Down
81 changes: 38 additions & 43 deletions src/lhpapi/hh_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,19 @@ def init_HH(ident: str) -> StaticData: # pylint: disable=invalid-name
"""Init data for Hamburg."""
try:
# Get data
soup = fetch_soup("https://www.wabiha.de/karte.html")
tooltipwrapper = soup.find("div", id="tooltipwrapper")
div = tooltipwrapper.find_next("div", id="tooltip-content-" + ident[3:])
spans = div.find_all("span")
# Parse data
if len(spans) == 8:
text = div.getText()
name = text[: text.find("Gewässer:")].strip()
name = (
name
+ " / "
+ text[
text.find("Gewässer:") + 9 : text.find("Niederschlagsvorhersage")
].strip()
)
url = "https://www.wabiha.de/grafik-" + ident[3:] + ".html"
return StaticData(ident=ident, name=name, url=url)
soup = fetch_soup("https://www.wabiha.de/pegel.html")
table = soup.find_all("table", id="pegeltabelle")[0]
tbody = table.find_all("tbody")[0]
trs = tbody.find_all("tr")
for row in trs:
span = row.find(id="tooltip-target-" + ident[3:])
if span:
td_prev = span.find_parent("td").find_previous_sibling("td")
river = td_prev.find("span").text.strip()
pegel_name = span.text.strip()
name = pegel_name + " / " + river
url = "https://www.wabiha.de/grafik-" + ident[3:] + ".html"
return StaticData(ident=ident, name=name, url=url)
return StaticData(ident=ident)
except Exception as err:
raise LHPError(err, "hh_api.py: init_HH()") from err
Expand All @@ -43,33 +39,32 @@ def update_HH(static_data: StaticData) -> DynamicData: # pylint: disable=invali
"""Update data for Hamburg."""
try:
# Get data
soup = fetch_soup("https://www.wabiha.de/karte.html")
tooltipwrapper = soup.find("div", id="tooltipwrapper")
div = tooltipwrapper.find_next(
"div", id="tooltip-content-" + static_data.ident[3:]
)
spans = div.find_all("span")
soup = fetch_soup("https://www.wabiha.de/pegel.html")
table = soup.find_all("table", id="pegeltabelle")[0]
tbody = table.find_all("tbody")[0]
trs = tbody.find_all("tr")
# Parse data
if len(spans) == 8:
text = div.getText()
level = convert_to_float(
text[
text.find("Wasserstand") + 11 : text.find("[NHN\u00a0+/-\u00a0cm]")
]
.replace(".", "")
.strip()
)
last_update = convert_to_datetime(
text[
text.find("\u00a0\u00a0\u00a0 um") + 6 : text.find("Trend")
].strip(),
"%d.%m.%Y %H:%M",
)
stage = convert_to_int(spans[7].attrs["class"][-1].split("_")[-1])
if stage == 2:
# Special case for Hamburg, see https://www.hochwasserzentralen.de/info
stage = 3
return DynamicData(level=level, stage=stage, last_update=last_update)
for row in trs:
span = row.find(id="tooltip-target-" + static_data.ident[3:])
if span:
td_next = span.find_parent("td").find_next_sibling("td")
level = convert_to_float(
td_next.find("span").text.replace(".", "").strip()
)
td_next2 = td_next.find_next_sibling("td")
last_update = convert_to_datetime(
td_next2.find(string=True, recursive=False).text.strip(),
"%d.%m.%y %H:%M",
)
td_next4 = td_next2.find_next_sibling("td").find_next_sibling("td")
if "--" in td_next4.attrs["class"][-1]:
stage = None
else:
stage = convert_to_int(td_next4.attrs["class"][-1].split("-")[-1])
if stage == 2:
# Special case for Hamburg, see https://www.hochwasserzentralen.de/info
stage = 3
return DynamicData(level=level, stage=stage, last_update=last_update)
return DynamicData()
except Exception as err:
raise LHPError(err, "hh_api.py: update_HH()") from err