diff --git a/README.es-ES.md b/README.es-ES.md new file mode 100644 index 00000000..81743996 --- /dev/null +++ b/README.es-ES.md @@ -0,0 +1,129 @@ + + +# linkedin_api + +👨‍💼 Envoltorio (Wrapper) de Python para la API de Linkedin + +> ¡No se requiere acceso "oficial", solo usa una cuenta válida de Linkedin! + +### ÚSALO BAJO TU PROPIA RESPONSABILIDAD 😉 +Este proyecto debe utilizarse únicamente como un proyecto de aprendizaje. Su uso violaría los Términos de Uso de Linkedin. No me hago responsable de que tu cuenta sea bloqueada (y definitivamente lo harán. Consejo: **no uses tu cuenta personal de Linkedin**) + +## Descripción general + +Este proyecto intenta proporcionar una interfaz sencilla de Python para la API de Linkedin. + +> ¿Te refieres a la [API legítima de Linkedin](https://developer.linkedin.com/)? + +¡NO! Para recuperar datos estructurados, el [sitio web de Linkedin](https://linkedin.com) utiliza un servicio al que llaman **Voyager**. Los puntos finales (endpoints) de Voyager nos dan acceso a prácticamente todo lo que podríamos desear de Linkedin: perfiles, empresas, conexiones, mensajes, etc. + +Por lo tanto, específicamente, este proyecto tiene como objetivo proporcionar cobertura completa para Voyager. + +[¿Cómo lo hacemos?](#in-depth-overview) + +### ¿Quieres contribuir? +[¿Cómo encuentro los puntos finales (endpoints)?](to-find-endpoints) + +## Instalación +``` +$ pip install linkedin-api +``` + +### Ejemplo de uso + +```python +from linkedin_api import Linkedin + +# Autentícate usando las credenciales de cualquier cuenta de Linkedin +api = Linkedin('reedhoffman@linkedin.com', 'iheartmicrosoft') + +# OBTENER un perfil +profile = api.get_profile('billy-g') + +# OBTENER información de contacto de un perfil +contact_info = api.get_profile_contact_info('billy-g') + +# OBTENER todos los perfiles conectados (de 1er, 2do y 3er grado) de un perfil dado +connections = api.get_profile_connections('1234asc12304', max_connections=200) +``` + +## Documentación +Para ver la documentación de referencia completa, consulta el [DOCS.md](https://github.com/tomquirk/linkedin-api/blob/master/DOCS.md) + +## Configuración + +### Dependencias + +* Python 3 +* Una cuenta de usuario válida de Linkedin (no uses tu cuenta personal, si es posible) +* Pipenv (opcional) + +1. Usando pipenv... + + ``` + $ pipenv install + $ pipenv shell + ``` + +## Descripción detallada + +Los puntos finales (endpoints) de Voyager se ven así: +``` +https://www.linkedin.com/voyager/api/identity/profileView/tom-quirk +``` + +O, más claramente +``` + ___________________________________ _______________________________ +| base path | resource | +https://www.linkedin.com/voyager/api /identity/profileView/tom-quirk +``` + +Se autentican con una cookie simple, la cual enviamos con cada solicitud, junto con una serie de encabezados (headers). + +Para obtener una cookie, enviamos (POST) un nombre de usuario y contraseña dados (de una cuenta válida de Linkedin) a `https://www.linkedin.com/uas/authenticate`. + +### Para encontrar los puntos finales (endpoints)... + +Estamos viendo el sitio web de Linkedin y encontramos algunos datos que queremos. ¿Qué hacemos ahora? + +El método más confiable para encontrar el punto final relevante es: +1. `view source` +2. `command-f`/buscar en la página alguna palabra clave en los datos. Esto existirá dentro de una etiqueta ``. +3. Desplázate hacia abajo hasta el **elemento adyacente siguiente**, que será otra etiqueta ``, probablemente con un `id` que se vea algo como + ```html + + ``` +4. ¡El valor de `request` es la URL! :woot: + +También puedes usar la pestaña `network` en las herramientas de desarrollador de tu navegador, pero obtendrás resultados inconsistentes. + +### Cómo los clientes consultan Voyager + +Parece que Linkedin ha desarrollado un lenguaje/sintaxis de consulta interno donde los clientes (es decir, front-ends como linkedin.com) especifican qué datos desean (similar al concepto de GraphQL). **Si alguien sabe qué es esto, ¡me encantaría saberlo!** + +Aquí hay un ejemplo de una solicitud para obtener el `name` y `groups` de una organización (los grupos de Linkedin que administra): + +``` +/voyager/api/organization/companies?decoration=(name,groups*~(entityUrn,largeLogo,groupName,memberCount,websiteUrl,url))&q=universalName&universalName=linkedin +``` + +La "consulta" ocurre en el parámetro `decoration`, que se ve así: +``` +( + name, + groups*~(entityUrn,largeLogo,groupName,memberCount,websiteUrl,url) +) +``` +Así que aquí, solicitamos el nombre de una organización y una lista de grupos, donde para cada grupo queremos `largeLogo`, `groupName`, etc. + +Diferentes puntos finales (endpoints) utilizan diferentes parámetros (y quizás incluso sintaxis distintas) para especificar estas consultas. Observa que la consulta anterior tenía un parámetro `q` cuyo valor era `universalName`; la consulta se especificaba luego con el parámetro `decoration`. + +En cambio, el punto final `/search/cluster` utiliza `q=guided`, y especifica su consulta con el parámetro `guided`, cuyo valor es algo como +``` +List(v->PEOPLE) +``` + +Podría ser posible documentar (e implementar una buena interfaz para) este lenguaje de consulta; a medida que agreguemos más puntos finales a este proyecto, estoy seguro de que quedará más claro si algo así sería posible (y si vale la pena).