Contourner la limite de recherche LinkedIn en jouant avec l'API

[Parce que mon extension a retenu l'attention du public étranger, j'ai traduit mon article original en anglais] .

Limite


Étant un réseau professionnel de premier ordre, LinkedIn, malheureusement, pour les comptes gratuits, a une limitation telle que la limite d' utilisation commerciale (CUL). Très probablement, vous, comme moi jusqu'à récemment, n'avez jamais rencontré et jamais entendu parler de cette chose.

image

Le point de la CUL est que lorsque vous recherchez trop souvent des personnes en dehors de vos connexions / réseaux, vos résultats de recherche seront limités avec seulement 3 profils affichés au lieu de 1000 (100 pages avec 10 profils par page par défaut). Combien de fois est mesuré personne ne sait, il n'y a pas de paramètres précis; l'algorithme le décide en fonction de vos actions - à quelle fréquence vous avez cherché et combien de connexions vous avez ajoutées. Le CUL gratuit se réinitialise à minuit PST le 1er de chaque mois civil, et vous obtenez à nouveau vos 1000 résultats de recherche, pour qui sait combien de temps. Bien sûr, les comptes Premium n'ont pas de telle limite en place .

Cependant, il n'y a pas si longtemps, j'ai commencé à jouer avec la recherche de LinkedIn pour certains projets pour animaux de compagnie, et je me suis soudainement retrouvé coincé avec ce CUL. Évidemment, je n'aimais pas tellement ça; après tout, je n'ai pas utilisé la recherche à des fins commerciales. Donc, ma première pensée a été d'explorer cette limite et d'essayer de la contourner.

[Précision importante - tous les documents sources de cet article sont présentés uniquement à des fins d'information et d'éducation. L'auteur n'encourage pas leur utilisation à des fins commerciales.]


Mise à jour importante - LinkedIn a pris en compte cette porte dérobée et a récemment été corrigée. La porte dérobée et le plugin ne fonctionnent plus.



Étudier le problème


Ce que nous avons obtenu: au lieu de 10 profils avec pagination, l'outil de recherche n'affiche que 3, qui sont suivis d'une `` recommandation '' pour acheter un compte Premium, puis vous voyez d'autres profils floues non cliquables.

Le premier que vous ayez en tant que développeur consiste à ouvrir les outils de développement du navigateur pour examiner ces profils cachés / flous - vous pouvez peut-être supprimer certains styles responsables du flou ou extraire les données du bloc de mise en page / balisage. Mais, comme on pouvait s'y attendre, ces profils ne sont présentés que comme des images d'espace réservé et ne contiennent aucune donnée.

image

Bon, passons maintenant à un onglet Réseau et vérifions si les résultats de recherche alternatifs ne renvoient vraiment que 3 profils. Donc, nous trouvons la requête qui nous intéresse - "/ api / search / blended" - et regardons la réponse.

image

Les profils sont contenus dans le tableau «inclus», mais il contient également déjà 15 entités. Dans ce cas, les 3 premiers d'entre eux sont les objets avec des données supplémentaires - chaque objet contient des informations sur un profil particulier (par exemple, si le profil est Premium).

Les 12 profils suivants sont réels - ce sont en fait ces résultats de recherche, dont seulement 3 nous seront montrés. Comme vous pouvez déjà le deviner, LinkedIn affiche uniquement les profils qui ont reçu les informations supplémentaires (les 3 premiers objets). Par exemple, si vous explorez la réponse de recherche du profil sans limite, 28 entités seront retournées - 10 objets avec des informations supplémentaires et 18 profils.

Réponse pour un profil sans limite
image

image

Je ne sais pas encore pourquoi il y a plus de 10 profils retournés, alors que 10 sont demandés, et ils ne sont pas affichés pour un utilisateur - vous ne les verrez pas même sur la page suivante. Si vous analysez l'URL de la demande, vous verriez que count = 10 (combien de profils renvoyer dans la réponse, 49 est le maximum).

image

Tout commentaire à ce sujet serait très apprécié.

Expérimentation


D'accord, nous savons maintenant la chose la plus importante, la réponse est fournie avec plus de profils que LinkedIn ne nous en montre. Ainsi, nous pouvons obtenir plus de données, malgré le CUL. Essayons de tirer l'API nous-mêmes directement depuis la console, en utilisant fetch.

image

Comme prévu, nous obtenons l'erreur 403. Il s'agit d'un problème de sécurité - ici, nous n'envoyons pas de jeton CSRF ( CSRF sur Wikipedia ). En un mot, c'est un jeton unique qui est ajouté à chaque demande, dont l'authenticité est vérifiée côté serveur.

image

Vous pouvez le copier à partir de toute autre demande réussie ou à partir de cookies, où il est stocké dans le champ 'JSESSIONID'.

Où trouver un jeton
En-tête de toute autre demande:

image

Depuis les cookies, directement via la console:

image

Essayons encore; cette fois, nous passons les paramètres à récupérer. Dans les paramètres, nous spécifions notre jeton CSRF comme paramètre dans l'en-tête.

image

Succès, les 10 profils sont retournés. : tada:
En raison de la différence dans les en-têtes, la structure de réponse diffère légèrement de celle fournie dans la demande d'origine. Vous pouvez obtenir la même structure exacte si vous ajoutez 'Accept:' application / vnd.linkedin.normalized + json + 2.1 'dans notre objet, à côté du jeton CSRF.

Exemple de réponse avec en-tête ajouté
image

En savoir plus sur l'en-tête Accept

Et ensuite?


Vous pouvez maintenant éditer (manuellement ou automatiquement) le paramètre `start` qui spécifie l'index, à partir duquel nous pouvons recevoir 10 profils (par défaut = 0) de l'ensemble du résultat de la recherche. En d'autres termes, en l'incrémentant de 10 après chaque demande, nous obtenons notre pagination habituelle, 10 profils par page.

À ce stade, j'ai suffisamment de données et de liberté pour continuer à travailler sur le projet pour animaux de compagnie. Mais ce serait un péché de ne pas essayer d'afficher ces données tout de suite car elles étaient entre mes mains. Nous ne plongerons pas dans l'Ember utilisé pour le frontend. Comme JQuery a été intégré sur le site Web, vous pouvez extraire de votre mémoire la connaissance de la syntaxe de base et créer la chose suivante en quelques minutes.

Code 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 vous effectuez ces actions directement dans la console sur la page de recherche, vous ajouterez un bouton qui charge 10 nouveaux profils chaque fois que vous cliquez dessus et les rend sous forme de liste. Bien sûr, vous devrez remplacer un jeton et une URL de manière appropriée par ceux nécessaires. Le bloc de profil contiendra un nom, un poste, un emplacement, un lien vers le profil et une image d'espace réservé.

image

Conclusion
Par conséquent, avec un minimum d'effort, nous avons pu trouver un point faible et retrouver notre option de recherche sans aucune limitation. Il suffisait d'analyser les données et leur chemin et d'examiner la requête elle-même.

Je ne peux pas dire que c'est un problème grave pour LinkedIn car il ne représente aucune menace. Le pire qui pourrait arriver est une perte de profit en raison d'un tel «contournement», qui vous permet de ne pas acheter de compte Premium. Peut-être, la réponse de ce serveur est nécessaire pour que les autres parties du site Web fonctionnent correctement, ou c'est simplement la paresse du manque de ressources des développeurs, ce qui ne permet pas de faire mieux (Le CUL est apparu en janvier 2015, avant qu'il n'y ait pas de limite pas du tout).

PS


Vieux ps
Bien sûr, le code jQuery est un exemple assez primitif de capacités. Actuellement, j'ai créé une extension de navigateur pour répondre à mes besoins. Il ajoute des boutons de contrôle et rend des profils complets avec des images, un bouton d'invitation et des connexions mutuelles. De plus, il collecte dynamiquement des filtres d'emplacements, d'entreprises et d'autres choses, et extrait un jeton des cookies. Vous n'avez donc rien à coder en dur. De plus, l'extension ajoute des champs de paramètres supplémentaires, par exemple «combien de profils demander en même temps, jusqu'à 49».

exemple

Je travaille toujours sur cette extension et je prévois de la rendre publique.
Envoyez-moi un message si vous êtes intéressé.

À la demande générale de publier cette extension en tant que produit open source, j'ai créé une extension de navigateur et l'ai publiée pour une utilisation publique (gratuite et même sans mineurs). Il a non seulement la fonctionnalité de contournement de limite, mais aussi d'autres fonctionnalités. Vous pouvez le consulter et le télécharger ici - adam4leos.imtqy.com

Comme il s'agit d'une version alpha, n'hésitez pas à me faire part de bugs, de vos idées, ou même d'un
lapidé UI cool. Je continue d'améliorer l'extension et publierai de nouvelles versions de temps en temps.

Mise à jour importante - LinkedIn a pris en compte cette porte dérobée et a récemment été corrigée. La porte dérobée et le plugin ne fonctionnent plus.

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


All Articles