edb-noumea 0.3.5__py3-none-any.whl → 0.3.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edb_noumea/details.py +45 -28
- {edb_noumea-0.3.5.dist-info → edb_noumea-0.3.6.dist-info}/METADATA +2 -1
- edb_noumea-0.3.6.dist-info/RECORD +8 -0
- {edb_noumea-0.3.5.dist-info → edb_noumea-0.3.6.dist-info}/WHEEL +1 -1
- edb_noumea-0.3.5.dist-info/RECORD +0 -8
- {edb_noumea-0.3.5.dist-info → edb_noumea-0.3.6.dist-info}/licenses/LICENSE +0 -0
- {edb_noumea-0.3.5.dist-info → edb_noumea-0.3.6.dist-info}/top_level.txt +0 -0
edb_noumea/details.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
|
+
import requests
|
|
3
|
+
from bs4 import BeautifulSoup
|
|
4
|
+
import camelot
|
|
5
|
+
import tempfile
|
|
6
|
+
import os
|
|
2
7
|
|
|
3
8
|
@staticmethod
|
|
4
9
|
def get_sites():
|
|
@@ -14,22 +19,16 @@ def get_sites():
|
|
|
14
19
|
{"site": "PLAGE DU KUENDU BEACH", "plage": "Plage du Kuendu Beach", "gmaps_url": "https://maps.app.goo.gl/oGY6Hy4KCXJWxqfL9"},
|
|
15
20
|
]
|
|
16
21
|
return pd.DataFrame(data)
|
|
22
|
+
|
|
17
23
|
def get_pdf_url():
|
|
18
24
|
"""
|
|
19
25
|
Alias public pour obtenir l'URL du dernier PDF d'analyses détaillées.
|
|
20
26
|
"""
|
|
21
27
|
return get_latest_pdf_url()
|
|
22
28
|
|
|
23
|
-
import pandas as pd
|
|
24
|
-
import pdfplumber
|
|
25
|
-
import requests
|
|
26
|
-
import io
|
|
27
|
-
from bs4 import BeautifulSoup
|
|
28
|
-
|
|
29
29
|
# URL de la page officielle contenant le lien vers le PDF
|
|
30
30
|
PAGE_URL = "https://www.noumea.nc/noumea-pratique/salubrite-publique/qualite-eaux-baignade"
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
def get_latest_pdf_url():
|
|
34
33
|
"""
|
|
35
34
|
Récupère dynamiquement l'URL du dernier PDF d'analyses détaillées depuis la page officielle.
|
|
@@ -58,7 +57,7 @@ def get_latest_pdf_url():
|
|
|
58
57
|
def get_detailed_results():
|
|
59
58
|
"""
|
|
60
59
|
Télécharge dynamiquement le PDF des résultats détaillés, en extrait le premier tableau
|
|
61
|
-
et le retourne sous forme de DataFrame pandas.
|
|
60
|
+
avec Camelot et le retourne sous forme de DataFrame pandas.
|
|
62
61
|
"""
|
|
63
62
|
pdf_url = get_latest_pdf_url()
|
|
64
63
|
if not pdf_url:
|
|
@@ -73,31 +72,49 @@ def get_detailed_results():
|
|
|
73
72
|
print(f"❌ Erreur lors du téléchargement du fichier PDF : {e}")
|
|
74
73
|
return None
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
# Utiliser un fichier temporaire pour que Camelot puisse le lire
|
|
76
|
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_pdf:
|
|
77
|
+
temp_pdf.write(response.content)
|
|
78
|
+
temp_pdf_path = temp_pdf.name
|
|
77
79
|
|
|
78
80
|
try:
|
|
79
|
-
print("🔍 Extraction des tableaux du PDF avec
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
first_page = pdf.pages[0]
|
|
86
|
-
tables = first_page.extract_tables()
|
|
87
|
-
|
|
88
|
-
if not tables:
|
|
89
|
-
print("❌ Aucun tableau n'a été trouvé dans le PDF.")
|
|
90
|
-
return None
|
|
91
|
-
|
|
92
|
-
print(f"✅ {len(tables)} tableau(x) trouvé(s) sur la première page.")
|
|
93
|
-
# Convertir le premier tableau en DataFrame
|
|
94
|
-
table_data = tables[0]
|
|
95
|
-
df = pd.DataFrame(table_data[1:], columns=table_data[0])
|
|
81
|
+
print("🔍 Extraction des tableaux du PDF avec Camelot (flavor='stream')...")
|
|
82
|
+
tables = camelot.read_pdf(temp_pdf_path, flavor='stream', pages='1')
|
|
83
|
+
|
|
84
|
+
if not tables:
|
|
85
|
+
print("❌ Aucun tableau n'a été trouvé dans le PDF avec Camelot.")
|
|
86
|
+
return None
|
|
96
87
|
|
|
88
|
+
print(f"✅ {len(tables)} tableau(x) trouvé(s) sur la première page.")
|
|
89
|
+
# Le DataFrame est directement accessible avec .df
|
|
90
|
+
df = tables[0].df
|
|
91
|
+
|
|
92
|
+
# The header is messy. Let's explicitly define the columns we expect.
|
|
93
|
+
new_columns = [
|
|
94
|
+
"Nom du site de baignade",
|
|
95
|
+
"Point de prélèvement",
|
|
96
|
+
"Date du prélèvement",
|
|
97
|
+
"Heure du prélèvement",
|
|
98
|
+
"Escherichia coli (NPP/100ml)",
|
|
99
|
+
"Entérocoques intestinaux (NPP/100ml)"
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# The data from camelot has 6 columns, which matches our expected columns.
|
|
103
|
+
# Let's assign these names.
|
|
104
|
+
df.columns = new_columns
|
|
105
|
+
|
|
106
|
+
# Now, we need to find where the actual data starts.
|
|
107
|
+
# It seems to start at index 6 in the camelot df.
|
|
108
|
+
df = df.iloc[6:].reset_index(drop=True)
|
|
109
|
+
|
|
97
110
|
except Exception as e:
|
|
98
|
-
print(f"❌ Une erreur est survenue lors de l'extraction des données du PDF.")
|
|
111
|
+
print(f"❌ Une erreur est survenue lors de l'extraction des données du PDF avec Camelot.")
|
|
99
112
|
print(f" Erreur originale : {e}")
|
|
100
113
|
return None
|
|
114
|
+
finally:
|
|
115
|
+
# Nettoyer le fichier temporaire
|
|
116
|
+
if 'temp_pdf_path' in locals() and os.path.exists(temp_pdf_path):
|
|
117
|
+
os.remove(temp_pdf_path)
|
|
101
118
|
|
|
102
119
|
print("\n--- Aperçu du tableau extrait (toutes colonnes) ---")
|
|
103
120
|
with pd.option_context('display.max_columns', None):
|
|
@@ -182,4 +199,4 @@ if __name__ == "__main__":
|
|
|
182
199
|
]])
|
|
183
200
|
# Export CSV
|
|
184
201
|
detailed_df.to_csv("details_dernier_releve.csv", index=False)
|
|
185
|
-
print("\n✅ Export CSV : details_dernier_releve.csv")
|
|
202
|
+
print("\n✅ Export CSV : details_dernier_releve.csv")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: edb-noumea
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: Scraper pour la qualité des eaux de baignade à Nouméa.
|
|
5
5
|
Project-URL: Homepage, https://github.com/adriens/edb-noumea
|
|
6
6
|
Project-URL: Repository, https://github.com/adriens/edb-noumea
|
|
@@ -11,6 +11,7 @@ Requires-Dist: beautifulsoup4
|
|
|
11
11
|
Requires-Dist: pandas
|
|
12
12
|
Requires-Dist: lxml
|
|
13
13
|
Requires-Dist: pdfplumber
|
|
14
|
+
Requires-Dist: camelot-py[cv]
|
|
14
15
|
Requires-Dist: matplotlib
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
edb_noumea/__init__.py,sha256=G7WKTGLsr2wtW1E2jYpqq4miZLoSGhTifSE36CGNkLo,60
|
|
2
|
+
edb_noumea/details.py,sha256=n9FgkNPzEAZf9HQxTlU7OWjyofi57O00zIqQghyarE8,8821
|
|
3
|
+
edb_noumea/main.py,sha256=ekx8XF7b3-w63AuVrZqVPg7IKHRL0cZGYmudsHa6DTk,2137
|
|
4
|
+
edb_noumea-0.3.6.dist-info/licenses/LICENSE,sha256=mNQ0SS064BtPKYHabMRg2yM3m-GDX4MgDQ6ZnDFiueI,1100
|
|
5
|
+
edb_noumea-0.3.6.dist-info/METADATA,sha256=xAqPGKMwfOvz_HF65QvBcWvyrK8iwGTY5QwwcJmMmYU,7126
|
|
6
|
+
edb_noumea-0.3.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
7
|
+
edb_noumea-0.3.6.dist-info/top_level.txt,sha256=Dj3JusM0b5H9_f9yZeO-IwucCZzI1OHSjLMKtvRjq6k,11
|
|
8
|
+
edb_noumea-0.3.6.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
edb_noumea/__init__.py,sha256=G7WKTGLsr2wtW1E2jYpqq4miZLoSGhTifSE36CGNkLo,60
|
|
2
|
-
edb_noumea/details.py,sha256=R0lnEeYL1C-BKPaJhySq3N1H1sFZ4yNOkEcKP3g59dg,8026
|
|
3
|
-
edb_noumea/main.py,sha256=ekx8XF7b3-w63AuVrZqVPg7IKHRL0cZGYmudsHa6DTk,2137
|
|
4
|
-
edb_noumea-0.3.5.dist-info/licenses/LICENSE,sha256=mNQ0SS064BtPKYHabMRg2yM3m-GDX4MgDQ6ZnDFiueI,1100
|
|
5
|
-
edb_noumea-0.3.5.dist-info/METADATA,sha256=SnI96WODEikpxdeanz-fqC4rJoJWthwAXVjloh6pVIw,7096
|
|
6
|
-
edb_noumea-0.3.5.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
7
|
-
edb_noumea-0.3.5.dist-info/top_level.txt,sha256=Dj3JusM0b5H9_f9yZeO-IwucCZzI1OHSjLMKtvRjq6k,11
|
|
8
|
-
edb_noumea-0.3.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|