Python instala los paquetes en un sitio que sorprende a casi todo el mundo la primera vez, y conviene entenderlo antes de instalar nada.
La diferencia que importa
pip install — pip es el instalador de paquetes de Python — no escribe dentro del proyecto. Escribe en el Python global del sistema. Instalas algo para un proyecto y se lo acabas metiendo a todos los demás — y a macOS, que usa su propio Python para sus cosas.
Quien venga de Node reconocerá el contraste: allí npm install escribe en el node_modules/ de la carpeta en la que estás, así que el aislamiento sale gratis y sin pedirlo. En Python hay que pedirlo.
El entorno virtual (venv) existe para eso: una copia aislada del intérprete y sus paquetes, dentro del proyecto.
Si el vocabulario de Node sirve de referencia, el mapa completo es este:
| En Node | En Python |
|---|---|
node_modules/ | .venv/ |
npm | pip |
package.json | requirements.txt |
package-lock.json | el mismo requirements.txt, con versiones fijadas |
Crear el entorno
No uses el Python del sistema (en macOS suele ser un 3.9 antiguo). Instala uno moderno con Homebrew y crea el entorno con él:
brew install python@3.14
# crea la carpeta .venv/ con un interprete aislado
/opt/homebrew/bin/python3.14 -m venv .venv
.venv/bin/python --version
# Python 3.14.7Verás en todas partes source .venv/bin/activate. Funciona, pero deja estado invisible en tu shell: abres otra pestaña, se te olvida, y acabas instalando en el Python global sin enterarte.
Llama al binario directamente — .venv/bin/python, .venv/bin/pip. Siempre correcto, nunca ambiguo.
Instalar y fijar las dependencias
Para el scraper solo hacen falta dos paquetes:
.venv/bin/pip install httpx beautifulsoup4Y se anotan en requirements.txt con la versión exacta:
httpx==0.28.1 # cliente HTTP (el fetch/axios de Python)
beautifulsoup4==4.15.0 # parseo de HTML (el cheerio de Python)== y no >=Python no genera lockfile por su cuenta. Ese fichero hace de lista de dependencias y de cierre de versiones a la vez — en Node harían falta package.json y package-lock.json para lo mismo. Con >=, dentro de tres meses pip install -r instalará otra versión y no sabrás por qué se rompió.
Estructura y .gitignore
perico-translator/
├── .venv/ # interprete aislado — NO se versiona
├── requirements.txt
├── data/
│ ├── raw/ # volcado del scraper — NO se versiona
│ ├── archive/ # texto crudo extraido — SI se versiona
│ └── clean/ # corpus procesado — SI se versiona
├── src/
└── docs/Las tres carpetas de data/ no son manía organizativa: son las tres fases por las que pasa todo pipeline de datos, y conviene fijarlas ya. raw/ es el volcado tal cual llega de la fuente, sin tocar ni un carácter. archive/ es el texto ya extraído de ese volcado pero sin filtrar: la copia de seguridad de una fuente que puede desaparecer mañana. clean/ es el corpus procesado, el único que consume el resto del proyecto.
Cada paso lee de una carpeta y escribe en la siguiente, y nunca sobrescribe la anterior. Eso es lo que te deja cambiar de criterio sobre qué es una frase buena y reejecutar en un segundo, en vez de volver a bajarlo todo.
Que data/raw/ no vaya a git y que data/archive/ y data/clean/ sí vayan es deliberado, y la regla de detrás sirve para cualquier proyecto de datos: se versiona lo que no puedas volver a conseguir.
raw/ es el volcado en bruto. Ocupa mucho y, mientras la fuente siga viva, se recupera con un comando. archive/ y clean/ son texto ya extraído, y ahí está el matiz que lo decide todo: las fuentes se pudren. Los vídeos se borran y las webs se caen, y el día que eso pasa el volcado ya no se puede regenerar. El corpus procesado es el activo real del proyecto.
Dicho corto: capturar es caro e irrepetible, procesar es barato e infinito. Es la misma regla que en la etapa 6 decide que no se filtre nada durante la captura.
Comprobar que funciona
Nunca des por bueno un entorno sin ejecutar algo real en él:
.venv/bin/python -c "
import httpx, bs4
r = httpx.get('https://example.com', timeout=10)
soup = bs4.BeautifulSoup(r.text, 'html.parser')
print(r.status_code, soup.find('h1').text)
"
# 200 Example Domain