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

Limite


Il existe une telle restriction sur LinkedIn - la limite d'utilisation commerciale . Il est trÚs probable que, comme moi, jusqu'à récemment, vous ne l'avez jamais rencontré ni entendu parler de lui.



L'essence de la limite est que si vous utilisez trop souvent la recherche de personnes en dehors de vos contacts (il n'y a pas de mesures exactes, l'algorithme décide, en fonction de vos actions - à quelle fréquence vous avez recherché et ajouté des personnes), le résultat de la recherche sera limité à trois profils, au lieu de 1000 ( 100 pages par défaut, 10 profils par page). La limite est réinitialisée au début de chaque mois. Naturellement, les comptes premium n'ont pas une telle restriction .

Mais il n'y a pas si longtemps, pour un projet pour animaux de compagnie, j'ai commencé à jouer beaucoup avec la recherche sur LinkedIn et j'ai soudainement eu cette restriction. Naturellement, je n'aimais pas beaucoup cela, car je ne l'ai pas utilisé à des fins commerciales, donc la premiÚre pensée a été d'étudier la restriction et d'essayer de la contourner.

[ Précision importante - les éléments contenus dans l'article sont présentés à titre informatif et éducatif uniquement. L'auteur n'encourage pas leur utilisation à des fins commerciales. ]

Mise à jour importante - LinkedIn a pris en compte la vulnérabilité et l'a récemment corrigée. Le bypass et le plugin ne fonctionnent plus.



Nous étudions le problÚme


Nous avons: au lieu de dix profils avec pagination, la recherche n'en renvoie que trois, aprÚs quoi un bloc avec la «recommandation» d'un compte premium est inséré et ci-dessous sont des profils flous et non cliquables.

ImmĂ©diatement, une main atteint la console du dĂ©veloppeur pour voir ces profils cachĂ©s - peut-ĂȘtre pouvons-nous supprimer certains styles qui mettent des bleus, ou extraire des informations du bloc dans le balisage. Mais, comme prĂ©vu, ces profils ne sont que des images tronquĂ©es et ne stockent aucune information.



Ok, regardons maintenant l'onglet RĂ©seau et voyons si les rĂ©sultats de la recherche alternative ont renvoyĂ© qui ne retournent que trois profils fonctionnent rĂ©ellement. Nous trouvons la requĂȘte qui nous intĂ©resse «/ api / search / blended» et regardons la rĂ©ponse.



Les profils entrent dans le tableau «inclus», mais il y a déjà 15 entités. Dans ce cas, les trois premiers d'entre eux sont des objets avec des informations supplémentaires, chaque objet contient des informations sur un profil spécifique (par exemple, le profil est-il une prime).



Les 12 suivants sont de vrais profils - résultats de recherche, dont seulement trois nous seront montrés. Comme vous pouvez déjà le deviner, il ne montre que ceux qui reçoivent des informations supplémentaires (les trois premiers objets). Par exemple, si vous prenez la réponse du profil sans limite, alors 28 entités viendront - 10 objets avec ext. informations et 18 profils.

Répondre au profil sans limite



Pourquoi il y a plus de 10 profils, bien que 10 soient demandĂ©s, et ils ne participent pas Ă  l'affichage, mĂȘme sur la page suivante, ils ne le seront pas - je ne sais pas encore. Si vous analysez l'URL de la demande, vous pouvez voir que count = 10 (combien de profils renvoyer dans la rĂ©ponse, un maximum de 49).



Je serai heureux de tout commentaire Ă  ce sujet.

Expérimenter


Eh bien, la chose la plus importante que nous savons maintenant avec certitude - plus de profils viennent dans la rĂ©ponse qu'ils ne nous en montrent. Nous pouvons donc obtenir plus de donnĂ©es, malgrĂ© la limite. Essayons de tirer l'api nous-mĂȘmes, directement depuis la console, en utilisant fetch.



On s'attend à ce que nous obtenions une erreur 403. Ceci est dû à la sécurité, ici nous n'envoyons pas le jeton CSRF ( CSRF sur Wikipedia . En bref, un jeton unique est ajouté à chaque demande, dont l'authenticité est vérifiée sur le serveur).



Il peut ĂȘtre copiĂ© Ă  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 d'une autre demande:



Ou Ă  partir des cookies, directement via la console:



Nous essayons Ă  nouveau, cette fois, passons les paramĂštres Ă  rĂ©cupĂ©rer, dans lesquels nous spĂ©cifions notre jeton csrf comme paramĂštre dans l'en-tĂȘte.



SuccĂšs, nous obtenons les 10 profils. : tada:

En raison de la diffĂ©rence dans les en-tĂȘtes, la structure de la rĂ©ponse est lĂ©gĂšrement diffĂ©rente de celle fournie dans la demande d'origine. Vous pouvez obtenir la mĂȘme structure si vous ajoutez 'Accept:' application / vnd.linkedin.normalized + json + 2.1 'Ă  notre objet, Ă  cĂŽtĂ© du jeton csrf.
Exemple de rĂ©ponse avec en-tĂȘte ajoutĂ©


En savoir plus sur l'en-tĂȘte Accept

Et ensuite?


Ensuite, vous pouvez éditer (avec vos mains ou automatiser) le paramÚtre `start`, en indiquant l'index, à partir duquel nous recevrons 10 profils (par défaut = 0) à partir 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 la pagination habituelle, 10 profils à la fois.

À ce stade, j'avais suffisamment de donnĂ©es et de libertĂ© pour continuer Ă  travailler sur le projet pour animaux de compagnie. Mais c'Ă©tait un pĂ©chĂ© de ne pas essayer d'afficher ces donnĂ©es directement sur place, car elles sont Ă  portĂ©e de main. Dans Ember, qui est utilisĂ© Ă  l'avant, nous ne grimperons pas. JQuery Ă©tait connectĂ© au site, et en creusant la connaissance de la syntaxe de base en mĂ©moire, vous pouvez crĂ©er ce qui suit en quelques minutes.

Code JQuery
/*  ,             */ 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>` ); }; //  ,      const fetchProfiles = () => { //  const csrf = 'ajax:9082932176494192209'; //    ,   const settings = { headers: { 'csrf-token': csrf } } //  ,       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}`; /*  ,        ,       10 */ fetch(url, settings).then(response => response.json()).then(data => { data.elements[0].elements.forEach(createProfileBlock); nextItemIndex += 10; }); }; //      $('.search-results__list').find('li').remove(); //     $('.search-results__list').after('<button id="load-more">Load More</button>'); //     $('#load-more').addClass('artdeco-button').on('click', fetchProfiles); //        window.nextItemIndex = 0; 


Si vous faites cela directement dans la console sur la page de recherche, il ajoutera un bouton qui charge 10 nouveaux profils chaque fois que vous cliquez et les rend une liste. Bien sûr, jeton et URL avant ce changement au besoin. Le bloc de profil contiendra un nom, une position, un emplacement, un lien vers le profil et une image de talon.



Conclusion


Ainsi, avec un minimum d'effort, nous avons pu trouver un point faible et reprendre notre recherche sans restrictions. Il suffisait d'analyser les donnĂ©es et leur chemin, de se pencher sur 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 maximum est le manque Ă  gagner dĂ» Ă  de tels "tours", ce qui permet de ne pas payer la prime. Peut-ĂȘtre qu'une telle rĂ©ponse du serveur est nĂ©cessaire pour que les autres parties du site fonctionnent correctement, ou est-ce simplement la paresse des dĂ©veloppeurs, le manque de ressources qui ne permet pas de bien faire. (La restriction est apparue en janvier 2015, avant que cette limite ne l'Ă©tait pas).

PS


Vieux PS
Naturellement, le code jQuery est un exemple assez primitif de fonctionnalités. Pour le moment, j'ai créé une extension pour le 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 générales. De plus, il collecte dynamiquement des filtres d'emplacements, d'entreprises et d'autres choses, prend un jeton de cookies. Vous n'avez donc pas besoin de coder en dur quoi que ce soit. Eh bien, il ajoute des champs de paramÚtres supplémentaires, comme "combien de profils demander à la fois, jusqu'à 49".



Je travaille toujours sur ce module complĂ©mentaire et je prĂ©vois de le mettre dans le domaine public. Écrivez si vous ĂȘtes intĂ©ressĂ©.


À la demande gĂ©nĂ©rale, j'ai mis l'add-on en accĂšs libre, j'ai créé un add-on pour le navigateur et je l'ai postĂ© pour un usage gĂ©nĂ©ral (gratuit et mĂȘme sans mineurs). LĂ , non seulement la fonctionnalitĂ© de contournement limite est implĂ©mentĂ©e, mais aussi d'autres commoditĂ©s. Voir et tĂ©lĂ©charger ici - adam4leos.imtqy.com

Comme il s'agit d'une version alpha, n'hĂ©sitez pas Ă  m'Ă©crire sur les bugs, les idĂ©es et mĂȘme une interface utilisateur stupide et chic. Je continue de dĂ©velopper l'add-on et publierai pĂ©riodiquement de nouvelles versions.

Mise à jour importante - LinkedIn a pris en compte la vulnérabilité et l'a récemment corrigée. Le bypass et le plugin ne fonctionnent plus.

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


All Articles