Quant0 commited on
Commit
9bb3deb
·
verified ·
1 Parent(s): 68188cc

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +149 -0
utils.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import requests
3
+ import pandas as pd
4
+ import numpy as np
5
+ from bs4 import BeautifulSoup
6
+ from fuzzywuzzy import process
7
+ from datetime import datetime, timedelta
8
+ from config import tickers_to_ids
9
+ from config import api_key, api_url
10
+
11
+
12
+ # -----------------------------------------------
13
+ # HERRAMIENTAS DE FROMATO
14
+ # -----------------------------------------------
15
+
16
+ def limpiar_texto(texto):
17
+ """Elimina caracteres especiales y espacios extra."""
18
+ texto_limpio_parcial = re.sub(r'[^a-zA-Z0-9.,\s]', '', texto)
19
+ texto_final = texto_limpio_parcial.strip()
20
+ return texto_final
21
+
22
+ def expand_money(val):
23
+ """Convierte strings de dinero (ej. '$1.2B') a valores flotantes."""
24
+ if pd.isna(val):
25
+ return np.nan
26
+ val = str(val).replace('$', '').replace(',','').upper()
27
+ try:
28
+ if 'B' in val:
29
+ return float(val.replace('B', '')) * 1_000_000_000
30
+ elif 'M' in val:
31
+ return float(val.replace('M', '')) * 1_000_000
32
+ elif 'K' in val:
33
+ return float(val.replace('K', '')) * 1_000
34
+ else:
35
+ return float(val)
36
+ except:
37
+ return np.nan
38
+
39
+
40
+ # -----------------------------------------------
41
+ # FUNCIÓN DE SCRAPER API
42
+ # -----------------------------------------------
43
+
44
+
45
+ def descargar_tabla_web(url, indice_tabla=0):
46
+ """
47
+ Descarga una tabla de una URL usando ScraperAPI para evitar bloqueos.
48
+ """
49
+ api_url = f"http://api.scraperapi.com?api_key={api_key}&url={url}"
50
+
51
+ try:
52
+ response = requests.get(api_url)
53
+ response.raise_for_status()
54
+
55
+ soup = BeautifulSoup(response.text, 'html.parser')
56
+ tables = soup.find_all('table')
57
+
58
+ if len(tables) > indice_tabla:
59
+ table = tables[indice_tabla]
60
+ else:
61
+ print(f"No se encontró la tabla con índice {indice_tabla} en la página: {url}.")
62
+ return None
63
+
64
+ # El resto del código para extraer los datos de la tabla sigue igual
65
+ headers = [th.text.strip() for th in table.find_all('th')]
66
+ data = []
67
+ for row in table.find_all('tr'):
68
+ cols = row.find_all('td')
69
+ cols = [ele.text.strip() for ele in cols]
70
+ if cols:
71
+ data.append(cols)
72
+
73
+ if headers and data and len(headers) == len(data[0]):
74
+ df = pd.DataFrame(data, columns=headers)
75
+ else:
76
+ df = pd.DataFrame(data)
77
+ return df
78
+
79
+ except requests.exceptions.RequestException as e:
80
+ print(f"Error al acceder a la URL: {e}")
81
+ return None
82
+ except Exception as e:
83
+ print(f"Ocurrió un error inesperado: {e}")
84
+ return None
85
+
86
+
87
+ # -----------------------------------------------
88
+ # FUNCIÓN PARA LEER LA PLANTILLA
89
+ # -----------------------------------------------
90
+
91
+
92
+ def extract_file_id(url):
93
+ """Extrae el ID del archivo de una URL de Google Drive."""
94
+ match = re.search(r'/d/([a-zA-Z0-9_-]+)', url)
95
+ if match:
96
+ return match.group(1)
97
+ return None
98
+
99
+
100
+ # -----------------------------------------------
101
+ # FUNCIÓN PARA EL CUADRO DE BÚSQUEDA
102
+ # -----------------------------------------------
103
+
104
+ # Lista de tickers prioritarios
105
+ priority_tickers = tickers_to_ids.copy()
106
+
107
+ def find_company_online(query):
108
+ query_clean = query.strip()
109
+
110
+ # Petición a la API de Yahoo Finance
111
+ url = f"https://query1.finance.yahoo.com/v1/finance/search?q={query_clean}&quotesCount=10&newsCount=0"
112
+ headers = {"User-Agent": "Mozilla/5.0"}
113
+ r = requests.get(url, headers=headers)
114
+ data = r.json()
115
+
116
+ if "quotes" not in data or not data["quotes"]:
117
+ return None, None
118
+
119
+ # Lista de resultados: (nombre, ticker)
120
+ results = [
121
+ (item.get("shortname") or item.get("longname") or item.get("symbol"), item["symbol"])
122
+ for item in data["quotes"]
123
+ if "symbol" in item
124
+ ]
125
+
126
+ # Priorizar tickers de la lista
127
+ for name, ticker in results:
128
+ if ticker in priority_tickers:
129
+ return name, ticker
130
+
131
+ # Buscar coincidencia exacta/aproximada por ticker
132
+ tickers = [sym for _, sym in results]
133
+ best_ticker_match = process.extractOne(query_clean.upper(), tickers, score_cutoff=80)
134
+ if best_ticker_match:
135
+ ticker = best_ticker_match[0]
136
+ name = next(name for name, sym in results if sym == ticker)
137
+ return name, ticker
138
+
139
+ # Buscar coincidencia por nombre
140
+ names = [name for name, _ in results]
141
+ best_name_match = process.extractOne(query_clean, names, score_cutoff=60)
142
+ if best_name_match:
143
+ name = best_name_match[0]
144
+ ticker = next(sym for nm, sym in results if nm == name)
145
+ return name, ticker
146
+
147
+ # Si no hay nada claro, devolver el primer resultado
148
+ return results[0] if results else (None, None)
149
+