Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions README.es-ES.md
Original file line number Diff line number Diff line change
@@ -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 `<code>`.
3. Desplázate hacia abajo hasta el **elemento adyacente siguiente**, que será otra etiqueta `<code>`, probablemente con un `id` que se vea algo como
```html
<code style="display: none" id="datalet-bpr-guid-3900675">
{"request":"/voyager/api/identity/profiles/tom-quirk/profileView","status":200,"body":"bpr-guid-3900675"}
</code>
```
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).