Omitiendo el límite de búsqueda de LinkedIn jugando con API

[Debido a que mi extensión recibió mucha atención de la audiencia extranjera, traduje mi artículo original al inglés] .

Límite


Al ser una red profesional de primer nivel, LinkedIn, desafortunadamente, para cuentas gratuitas, tiene una limitación como el Límite de uso comercial (CUL). Lo más probable es que usted, al igual que yo hasta hace poco, nunca se haya encontrado y nunca haya oído hablar de esto.

imagen

El objetivo del CUL es que cuando busca personas fuera de sus conexiones / red con demasiada frecuencia, sus resultados de búsqueda estarán limitados con solo 3 perfiles en lugar de 1000 (100 páginas con 10 perfiles por página por defecto). La frecuencia con que se mide nadie lo sabe, no hay métricas precisas; el algoritmo lo decide en función de sus acciones: con qué frecuencia ha estado buscando y cuántas conexiones ha estado agregando. El CUL gratuito se reinicia a la medianoche PST el 1 de cada mes calendario, y obtienes tus 1000 resultados de búsqueda nuevamente, por quién sabe cuánto tiempo. Por supuesto, las cuentas Premium no tienen dicho límite .

Sin embargo, no hace mucho tiempo, comencé a jugar con LinkedIn buscando algún proyecto para mascotas, y de repente me quedé atrapado con este CUL. Obviamente, no me gustó tanto; después de todo, no he estado usando la búsqueda con fines comerciales. Entonces, mi primer pensamiento fue explorar este límite e intentar evitarlo.

[Aclaración importante: todos los materiales fuente de este artículo se presentan únicamente con fines informativos y educativos. El autor no fomenta su uso con fines comerciales.]


Actualización importante: LinkedIn tuvo en cuenta esta puerta trasera y recientemente la han solucionado. La puerta trasera y el complemento ya no funcionan.



Estudiando el problema


Lo que obtuvimos: en lugar de 10 perfiles con paginación, la herramienta de búsqueda muestra solo 3, seguidos de una 'recomendación' para comprar una cuenta Premium y luego verá otros perfiles borrosos que no se pueden hacer clic.

Lo primero que tiene como desarrollador es abrir las Herramientas de desarrollo del navegador para examinar esos perfiles ocultos / borrosos; tal vez podría eliminar algunos estilos responsables del desenfoque o extraer los datos del bloque de diseño / marcado. Pero, como podría esperarse, estos perfiles se muestran solo como imágenes de marcador de posición y no contienen ningún dato.

imagen

Bien, ahora vayamos a la pestaña Red y verifiquemos si los resultados de búsqueda alternativos realmente devuelven solo 3 perfiles. Entonces, encontramos la consulta que nos interesa - "/ api / search / blended" - y miramos la respuesta.

imagen

Los perfiles están contenidos en la matriz `incluida`, pero también ya hay 15 entidades en ella. En este caso, los primeros 3 de ellos son los objetos con datos adicionales: cada objeto contiene información sobre un perfil particular (por ejemplo, si el perfil es Premium).

Los siguientes 12 perfiles son reales: en realidad son esos resultados de búsqueda, de los cuales solo se nos mostrarán 3. Como ya puede adivinar, LinkedIn muestra solo aquellos perfiles que recibieron la información adicional (los primeros 3 objetos). Por ejemplo, si explora la respuesta de búsqueda desde el perfil sin límite, se devolverán 28 entidades, 10 objetos con información adicional y 18 perfiles.

Respuesta para un perfil sin límite
imagen

imagen

Todavía no estoy seguro de por qué se devuelven más de 10 perfiles, mientras que se solicitan 10 y no se muestran a un usuario; no los verá ni en la página siguiente. Si analiza la URL de la solicitud, verá que cuenta = 10 (cuántos perfiles devolver en la respuesta, 49 es el máximo).

imagen

Cualquier comentario sobre este tema sería muy apreciado.

La experimentación


Bien, ahora sabemos con certeza lo más importante: la respuesta viene con más perfiles de los que LinkedIn nos muestra. Entonces, podemos obtener más datos, a pesar del CUL. Intentemos extraer la API nosotros mismos directamente de la consola, usando fetch.

imagen

Como se esperaba, obtenemos el error 403. Este es un problema de seguridad: aquí no enviamos un token CSRF ( CSRF en Wikipedia ). En pocas palabras, es un token único que se agrega a cada solicitud, que se verifica en el lado del servidor para garantizar su autenticidad.

imagen

Puede copiarlo desde cualquier otra solicitud exitosa o desde cookies, donde se almacena en el campo 'JSESSIONID'.

Dónde encontrar una ficha
Encabezado de cualquier otra solicitud:

imagen

Desde las cookies, hasta la consola:

imagen

Intentemos nuevamente; esta vez, pasamos la configuración para buscar. En la configuración, especificamos nuestro token CSRF como parámetro en el encabezado.

imagen

Éxito, se devuelven los 10 perfiles. : tada:
Debido a la diferencia en los encabezados, la estructura de respuesta difiere ligeramente de lo que viene en la solicitud original. Puede obtener la misma estructura exacta si agrega 'Aceptar:' application / vnd.linkedin.normalized + json + 2.1 'en nuestro objeto, junto al token CSRF.

Muestra de una respuesta con el encabezado agregado
imagen

Más información sobre el encabezado Aceptar

¿Qué sigue?


Ahora puede editar (manual o automáticamente) el parámetro `start` que especifica el índice, a partir del cual podemos recibir 10 perfiles (por defecto = 0) del resultado de búsqueda completo. En otras palabras, incrementándolo en 10 después de cada solicitud, obtenemos nuestra paginación habitual, 10 perfiles por página.

En esta etapa, tengo suficientes datos y libertad para seguir trabajando en el proyecto favorito. Pero sería un pecado no tratar de mostrar esta información de inmediato ya que estaba en mis manos. No nos sumergiremos en el Ember usado para la interfaz. Como JQuery se integró en el sitio web, puede extraer de su memoria el conocimiento de la sintaxis básica y crear lo siguiente en un par de minutos.

Código JQuery
/* render the block, receive profile data, and insert the block in the profiles' list, using this data */ const createProfileBlock = ({ headline, publicIdentifier, subline, title }) => { $('.search-results__list').append( `<li class="search-result search-result__occluded-item ember-view"> <div class="search-entity search-result search-result--person search-result--occlusion-enabled ember-view"> <div class="search-result__wrapper"> <div class="search-result__image-wrapper"> <a class="search-result__result-link ember-view" href="/in/${publicIdentifier}/"> <figure class="search-result__image"> <div class="ivm-image-view-model ember-view"> <img class="lazy-image ivm-view-attr__img--centered EntityPhoto-circle-4 presence-entity__image EntityPhoto-circle-4 loaded" src="http://www.userlogos.org/files/logos/give/Habrahabr3.png" /> </div> </figure> </a> </div> <div class="search-result__info pt3 pb4 ph0"> <a class="search-result__result-link ember-view" href="/in/${publicIdentifier}/"> <h3 class="actor-name-with-distance search-result__title single-line-truncate ember-view"> ${title.text} </h3> </a> <p class="subline-level-1 t-14 t-black t-normal search-result__truncate">${headline.text}</p> <p class="subline-level-2 t-12 t-black--light t-normal search-result__truncate">${subline.text}</p> </div> </div> </div> <li>` ); }; // fetch data and render the profiles const fetchProfiles = () => { // token const csrf = 'ajax:9082932176494192209'; // bject with the request settings, pass the token const settings = { headers: { 'csrf-token': csrf } } // request URL, with a dynamic start index at the end const url = `https://www.linkedin.com/voyager/api/search/blended?count=10&filters=List(geoRegion-%3Ejp%3A0,network-%3ES,resultType-%3EPEOPLE)&origin=FACETED_SEARCH&q=all&queryContext=List(spellCorrectionEnabled-%3Etrue,relatedSearchesEnabled-%3Etrue)&start=${nextItemIndex}`; /* make a request, for each profile in the response call the block rendering, and then increment the starting index by 10 */ fetch(url, settings).then(response => response.json()).then(data => { data.elements[0].elements.forEach(createProfileBlock); nextItemIndex += 10; }); }; // delete all profiles from the list $('.search-results__list').find('li').remove(); // insert the 'download profiles' button $('.search-results__list').after('<button id="load-more">Load More</button>'); // add the functionality to the button $('#load-more').addClass('artdeco-button').on('click', fetchProfiles); // set the default profile index for the request window.nextItemIndex = 0; 

Si realiza estas acciones directamente en la consola en la página de búsqueda, agregará un botón que carga 10 nuevos perfiles cada vez que hace clic en él y los presenta como una lista. Por supuesto, tendrá que cambiar un token y una URL de manera apropiada a los necesarios. El bloque de perfil contendrá un nombre, puesto de trabajo, ubicación, un enlace al perfil y una imagen de marcador de posición.

imagen

Conclusión
Por lo tanto, con un mínimo de esfuerzo, pudimos encontrar un punto débil y recuperar nuestra opción de búsqueda sin ninguna limitación. Fue suficiente para analizar los datos y su ruta y examinar la consulta misma.

No puedo decir que este es un problema grave para LinkedIn porque no representa una amenaza. Lo peor que podría suceder es una pérdida de ganancias debido a esa "omisión", que le permite no comprar una cuenta Premium. Quizás, la respuesta de dicho servidor es necesaria para que las otras partes del sitio web funcionen correctamente, o esto es simplemente la falta de recursos de los desarrolladores, lo que no permite hacerlo mejor (The CUL apareció en enero de 2015, antes de que no hubiera límite en absoluto).

PS


Viejo ps
Claro, el código jQuery es un ejemplo bastante primitivo de capacidades. Actualmente, he creado una extensión de navegador para satisfacer mis necesidades. Agrega botones de control y renderiza perfiles completamente equipados con imágenes, un botón de invitación y conexiones mutuas. Además, recopila dinámicamente filtros de ubicaciones, empresas y otras cosas, y extrae un token de las cookies. Para que no tenga que codificar nada. Además, la extensión agrega campos de configuración adicionales, por ejemplo, "cuántos perfiles solicitar a la vez, hasta 49".

ejemplo

Todavía estoy trabajando en esta extensión, y planeo ponerla a disposición del público.
Envíame un mensaje si estás interesado.

Por demanda popular de lanzar esta extensión como producto de código abierto, creé una extensión de navegador y la publiqué para uso público (gratis e incluso sin mineros). No solo tiene la funcionalidad de límite de derivación, sino también algunas otras características. Puede echarle un vistazo y descargarlo aquí - adam4leos.imtqy.com

Como se trata de una versión alfa, no dude en notificarme sobre errores, sus ideas o incluso sobre
apedreado genial interfaz de usuario Sigo mejorando la extensión y publicaré nuevas versiones de vez en cuando.

Actualización importante: LinkedIn tuvo en cuenta esta puerta trasera y recientemente la han solucionado. La puerta trasera y el complemento ya no funcionan.

Source: https://habr.com/ru/post/466801/


All Articles