MatteoScript commited on
Commit
f5f36ae
·
verified ·
1 Parent(s): 29768e8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -57
app.py CHANGED
@@ -7,6 +7,7 @@ from io import BytesIO
7
  from collections import namedtuple
8
  import numpy as np
9
  import streamlit as st
 
10
 
11
  def clean_text(text):
12
  return re.sub(r'\s+', ' ', text).strip()
@@ -78,7 +79,11 @@ def extract_info(provincia, comune, prezzo_medio_mq, listing):
78
  def scrape_immobiliare(provincia, comune, prezzo_medio_mq, prezzo_minimo, prezzo_massimo, locali_minimo, locali_massimo):
79
  print(provincia + " " + comune + " " + prezzo_medio_mq)
80
  comune_url = comune.replace(" ", "-")
81
- base_url = f"https://www.immobiliare.it/vendita-case/{comune_url}/?prezzoMinimo={prezzo_minimo}&prezzoMassimo={prezzo_massimo}&localiMinimo={locali_minimo}&localiMassimo={locali_massimo}&random=123456"
 
 
 
 
82
  results = []
83
  page = 1
84
  url = base_url
@@ -120,11 +125,9 @@ def get_elenco_comuni(provincia):
120
  'comune': comune,
121
  'prezzo': prezzo_vendita
122
  })
123
-
124
  return results
125
 
126
  st.set_page_config(layout="wide")
127
-
128
  st.title('🏠 Immobiliare A.I. ')
129
  st.write("##### Il tuo assistente di intelligenza artificiale per la ricerca di occasioni immobiliari")
130
  with st.expander("Informazioni"):
@@ -134,8 +137,14 @@ cerca_premuto = False
134
  comuni_provincia = {}
135
 
136
  with st.sidebar:
137
- comuni_provincia = get_elenco_comuni('Brescia')
 
 
 
 
138
  st.title("Filtri")
 
 
139
  elenco = [d['comune'] for d in comuni_provincia]
140
  comune_input = st.multiselect(
141
  "Comuni",
@@ -143,51 +152,63 @@ with st.sidebar:
143
  )
144
  prezzo_minimo = st.sidebar.slider("Prezzo Minimo", min_value=0, max_value=1000, value=200)
145
  prezzo_massimo = st.sidebar.slider("Prezzo Massimo", min_value=0, max_value=1000, value=230)
146
-
147
  locali = list(range(1, 21)) # Intervallo da 1 a 10
148
-
149
- # Select slider unico per selezionare l'intervallo del numero di locali
150
  locali_range = st.sidebar.select_slider(
151
  "Locali",
152
  options=locali,
153
  value=(locali[2], locali[4]) # Valore iniziale, da 1 a 5 locali
154
  )
 
 
155
 
156
- # Dividi il range in minimo e massimo numero di locali
157
  locali_minimo, locali_massimo = locali_range
158
  prezzo_minimo = prezzo_minimo*1000
159
  prezzo_massimo = prezzo_massimo*1000
160
  cerca_premuto = st.button("Cerca", use_container_width=True, type='primary')
161
 
162
- #
163
- #if __name__ == "__main__":
164
- # print(df)
165
-
166
- def scrivi_dataframe(output):
167
  if len(output) > 0:
 
 
 
168
  df = pd.DataFrame(output)
169
  df_originale = df.sort_values(by=["Vantaggio", "PrezzoMq"], ascending=[False, True])
170
- columns_to_display = ["Vantaggioso", "Vantaggio", "Immagine", "Comune", "Titolo", "PrezzoMq", "Prezzo", "Superficie", "Locali", "PrezzoMedioMq", "Link"]
 
 
 
 
171
  df = df_originale[columns_to_display]
172
  df = df.style.format(thousands='.')
173
-
174
- col0, col1, col2, col4 = st.columns(4, gap="large")
175
 
176
- with col1:
177
- vantaggioso_count = df_originale["Vantaggioso"].sum()
178
- total_rows = df_originale.shape[0]
179
- st.metric("Numero Immobili", int(total_rows), int(vantaggioso_count))
180
- st.write('Locali')
181
- immobili_per_locali = df_originale.sort_values(by=["Locali"], ascending=[True]).groupby("Locali").size()
182
- st.bar_chart(immobili_per_locali, color = "#ffb7b7", height=120)
183
-
184
- with col2:
185
- vantaggioso_count = df_originale["Vantaggioso"].sum()
186
- total_rows = df_originale.shape[0]
187
- st.metric("Numero Immobili", int(total_rows), int(vantaggioso_count))
188
- st.write('Prezzo')
189
- chart_data = df_originale["Prezzo"]
190
- st.line_chart(chart_data, color = "#FF4B4B", height=120)
 
 
 
 
 
 
 
 
 
 
 
191
  st.dataframe(df, hide_index=True, use_container_width=True,
192
  column_config ={
193
  "Vantaggioso": st.column_config.CheckboxColumn("Vantaggioso"),
@@ -211,31 +232,61 @@ def scrivi_dataframe(output):
211
  "Locali": "Locali",
212
  "Link": st.column_config.LinkColumn("App URL")
213
  })
214
-
 
215
 
216
 
217
- if cerca_premuto and len(comune_input)>0:
218
- comuni_selezionati = comune_input
219
- comuni_selezionati = [comune.upper() for comune in comuni_selezionati]
220
- output = []
221
- output_singolo = []
222
- for comune_provincia in comuni_provincia:
223
- if comune_provincia['comune'].upper() in comuni_selezionati:
224
- with st.spinner(f"Ricerca Immobili Comune: {comune_provincia['comune']}"):
225
- output_singolo = json.loads(scrape_immobiliare(comune_provincia['provincia'],
226
- comune_provincia['comune'],
227
- comune_provincia['prezzo'],
228
- prezzo_minimo,
229
- prezzo_massimo,
230
- locali_minimo,
231
- locali_massimo))
232
- st.write(f"### {comune_provincia['comune']}")
233
- scrivi_dataframe(output_singolo)
234
- st.divider()
235
- output += output_singolo
236
- if len(comuni_selezionati)>1:
237
- st.write(f"### Comuni Selezionati")
238
- scrivi_dataframe(output)
239
- st.success("Elaborazione Completata")
240
- else:
241
- st.error("Per favore, inserisci il nome di un comune.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  from collections import namedtuple
8
  import numpy as np
9
  import streamlit as st
10
+ from groq import Groq
11
 
12
  def clean_text(text):
13
  return re.sub(r'\s+', ' ', text).strip()
 
79
  def scrape_immobiliare(provincia, comune, prezzo_medio_mq, prezzo_minimo, prezzo_massimo, locali_minimo, locali_massimo):
80
  print(provincia + " " + comune + " " + prezzo_medio_mq)
81
  comune_url = comune.replace(" ", "-")
82
+ if tipologia_case == "Asta Immobiliare":
83
+ tipologia_url = "aste-immobiliari"
84
+ else:
85
+ tipologia_url = "vendita-case"
86
+ base_url = f"https://www.immobiliare.it/{tipologia_url}/{comune_url}/?prezzoMinimo={prezzo_minimo}&prezzoMassimo={prezzo_massimo}&localiMinimo={locali_minimo}&localiMassimo={locali_massimo}&random=123456"
87
  results = []
88
  page = 1
89
  url = base_url
 
125
  'comune': comune,
126
  'prezzo': prezzo_vendita
127
  })
 
128
  return results
129
 
130
  st.set_page_config(layout="wide")
 
131
  st.title('🏠 Immobiliare A.I. ')
132
  st.write("##### Il tuo assistente di intelligenza artificiale per la ricerca di occasioni immobiliari")
133
  with st.expander("Informazioni"):
 
137
  comuni_provincia = {}
138
 
139
  with st.sidebar:
140
+ if "numero_immobili_validi" not in st.session_state:
141
+ st.numero_immobili_validi = 0
142
+ comuni_provincia_Brescia = get_elenco_comuni('Brescia')
143
+ comuni_provincia_Bergamo = get_elenco_comuni('Bergamo')
144
+ comuni_provincia = comuni_provincia_Brescia + comuni_provincia_Bergamo
145
  st.title("Filtri")
146
+
147
+ tipologia_case = st.selectbox("Tipologia", ("Acquisto Immobile", "Asta Immobiliare"))
148
  elenco = [d['comune'] for d in comuni_provincia]
149
  comune_input = st.multiselect(
150
  "Comuni",
 
152
  )
153
  prezzo_minimo = st.sidebar.slider("Prezzo Minimo", min_value=0, max_value=1000, value=200)
154
  prezzo_massimo = st.sidebar.slider("Prezzo Massimo", min_value=0, max_value=1000, value=230)
 
155
  locali = list(range(1, 21)) # Intervallo da 1 a 10
 
 
156
  locali_range = st.sidebar.select_slider(
157
  "Locali",
158
  options=locali,
159
  value=(locali[2], locali[4]) # Valore iniziale, da 1 a 5 locali
160
  )
161
+ mostra_grafici = st.toggle("Mostra grafici", value = True)
162
+ analisi_ai = st.toggle("Analizza i dati tramite l'A.I.", value = True)
163
 
 
164
  locali_minimo, locali_massimo = locali_range
165
  prezzo_minimo = prezzo_minimo*1000
166
  prezzo_massimo = prezzo_massimo*1000
167
  cerca_premuto = st.button("Cerca", use_container_width=True, type='primary')
168
 
169
+ def scrivi_dataframe(output, riepilogo):
 
 
 
 
170
  if len(output) > 0:
171
+ st.numero_immobili_validi = st.numero_immobili_validi + 1
172
+ if not riepilogo:
173
+ st.write(f"### {comune_provincia['comune']}")
174
  df = pd.DataFrame(output)
175
  df_originale = df.sort_values(by=["Vantaggio", "PrezzoMq"], ascending=[False, True])
176
+ if not riepilogo:
177
+ columns_to_display = ["Vantaggioso", "Vantaggio", "Immagine", "Titolo", "PrezzoMq", "Prezzo", "Superficie", "Locali", "PrezzoMedioMq", "Link"]
178
+ else:
179
+ columns_to_display = ["Vantaggioso", "Vantaggio", "Immagine", "Comune", "Titolo", "PrezzoMq", "Prezzo", "Superficie", "Locali", "PrezzoMedioMq", "Link"]
180
+
181
  df = df_originale[columns_to_display]
182
  df = df.style.format(thousands='.')
183
+ vantaggioso_count = df_originale["Vantaggioso"].sum()
184
+ total_rows = df_originale.shape[0]
185
 
186
+ if mostra_grafici:
187
+ col1, col2, col3 = st.columns(3)
188
+ with col1:
189
+ vantaggioso_count = df_originale["Vantaggioso"].sum()
190
+ total_rows = df_originale.shape[0]
191
+ st.metric("Numero Immobili", int(total_rows), int(vantaggioso_count))
192
+ st.write('Prezzo Totale')
193
+ chart_data = df_originale["Prezzo"]
194
+ st.line_chart(chart_data, color = "#FF4B4B", height=110)
195
+
196
+ with col2:
197
+ vantaggioso_count = df_originale["Vantaggioso"].sum()
198
+ total_rows = df_originale.shape[0]
199
+ st.metric("% Immobili Vantaggiosi", int((vantaggioso_count/total_rows)* 100), 100-int((vantaggioso_count/total_rows)* 100))
200
+ st.write('Locali')
201
+ immobili_per_locali = df_originale.sort_values(by=["Locali"], ascending=[True]).groupby("Locali").size()
202
+ st.bar_chart(immobili_per_locali, color = "#ffb7b7", height=110)
203
+
204
+ with col3:
205
+ superficie_count = df_originale["Superficie"].sum()
206
+ total_rows = df_originale.shape[0]
207
+ st.metric("Media Superficie", int(superficie_count//total_rows), int(superficie_count))
208
+ st.write('Prezzo Medio al Metro Quadro')
209
+ chart_data = df_originale["PrezzoMq"]
210
+ st.area_chart(chart_data, color = "#FF4B4B", height=110)
211
+
212
  st.dataframe(df, hide_index=True, use_container_width=True,
213
  column_config ={
214
  "Vantaggioso": st.column_config.CheckboxColumn("Vantaggioso"),
 
232
  "Locali": "Locali",
233
  "Link": st.column_config.LinkColumn("App URL")
234
  })
235
+ st.write(f"Riepilogando nel comune {comune_provincia['comune']} sono presenti **{vantaggioso_count} Immobili vantaggiosi** rispetto ai {total_rows} totali")
236
+ st.divider()
237
 
238
 
239
+ def analizza_dati_ai(output):
240
+ Ak = "XXXXgsk_COQPhsuaXqvuCkKPryiQWGdyb3FYCHBSIcn30wk3ZZay8WYC6tpIXXXX"
241
+ client = Groq(api_key=Ak)
242
+ prompt_messages = [
243
+ {
244
+ "role": "system",
245
+ "content": "Sei un'assistente virtuale specializzata nel supporto agli investitori immobiliari. Il tuo compito è analizzare i dati di un file CSV contenente un elenco di immobili e fornire consigli, idee e analisi dettagliate per massimizzare il profitto attraverso la riqualificazione e rivendita degli stessi. Devi considerare vari fattori come la posizione degli immobili, il prezzo di acquisto, il potenziale valore di mercato post-riqualificazione, i costi stimati per la ristrutturazione e altri dati pertinenti. Il tuo obiettivo è offrire suggerimenti strategici basati sui dati, evidenziare le migliori opportunità di investimento, identificare eventuali rischi, e fornire consigli pratici per ottimizzare i profitti. Rispondi in modo chiaro, conciso e professionale."
246
+ },
247
+ {
248
+ "role": "user",
249
+ "content": f"Ho un file CSV con un elenco di immobili che sto considerando per un investimento. Vorrei che tu analizzassi i dati e mi fornissi consigli dettagliati su come posso massimizzare il mio profitto attraverso la riqualificazione e la rivendita di questi immobili. Per ogni immobile, per favore prendi in considerazione i seguenti aspetti:\n\n1. Valore attuale: Quanto vale l'immobile al momento dell'acquisto?\n2. Costi di riqualificazione stimati: Quanto potrebbe costare la ristrutturazione o la riqualificazione?\n3. Valore di mercato potenziale: Quanto potrebbe valere l'immobile una volta riqualificato?\n4. Rendimento potenziale: Qual è il margine di profitto previsto, tenendo conto dei costi totali?\n5. Tempistica di rivendita: In quanto tempo è probabile che l'immobile venga venduto una volta riqualificato?\n6. Analisi del mercato locale: Qual è la situazione del mercato immobiliare nella zona specifica? Ci sono trend emergenti?\n7. Rischi potenziali: Quali sono i possibili rischi o svantaggi legati a ciascun immobile?\nInfine, suggeriscimi le migliori opportunità di investimento tra gli immobili elencati, con una breve spiegazione del motivo per cui questi immobili sono i più promettenti.\n\n{output}"
250
+ }
251
+ ]
252
+ response_area = st.empty()
253
+ completion = client.chat.completions.create(
254
+ model="llama-3.1-70b-versatile",
255
+ messages=prompt_messages,
256
+ temperature=1,
257
+ max_tokens=1024,
258
+ top_p=1,
259
+ stream=True,
260
+ stop=None,
261
+ )
262
+ response_text = ""
263
+ for chunk in completion:
264
+ response_text += chunk.choices[0].delta.content or ""
265
+ response_area.text(response_text)
266
+
267
+ if cerca_premuto:
268
+ if len(comune_input)>0:
269
+ comuni_selezionati = comune_input
270
+ comuni_selezionati = [comune.upper() for comune in comuni_selezionati]
271
+ output = []
272
+ output_singolo = []
273
+ for comune_provincia in comuni_provincia:
274
+ if comune_provincia['comune'].upper() in comuni_selezionati:
275
+ with st.spinner(f"Ricerca Immobili Comune: {comune_provincia['comune']}"):
276
+ output_singolo = json.loads(scrape_immobiliare(comune_provincia['provincia'],
277
+ comune_provincia['comune'],
278
+ comune_provincia['prezzo'],
279
+ prezzo_minimo,
280
+ prezzo_massimo,
281
+ locali_minimo,
282
+ locali_massimo))
283
+ scrivi_dataframe(output_singolo, False)
284
+ output += output_singolo
285
+ if len(comuni_selezionati)>1 and st.numero_immobili_validi>1:
286
+ st.write(f"### Comuni Selezionati")
287
+ scrivi_dataframe(output, True)
288
+ if st.numero_immobili_validi > 0 and analisi_ai:
289
+ analizza_dati_ai(output)
290
+ st.success("Elaborazione Completata")
291
+ else:
292
+ st.error("Per favore, inserisci il nome di un comune.")