Limits
There is a restriction on LinkedIn ā . It's highly likely that you, like me until recently, have never encountered or heard of it.

The essence of the limit is that if you search for people outside your contacts too frequently (there are no exact metrics, it's determined by an algorithm based on your actions ā how often and how many people you've searched for and added), the search results will be limited to three profiles, instead of the default 1000 (100 pages with 10 profiles per page). The limit resets at the beginning of each month. Naturally, .
However, not long ago, for a pet project, I started experimenting a lot with LinkedIn searches and suddenly encountered this limitation. Naturally, I was not pleased, as I wasn't using it for any commercial purposes, so my first thought was to research the limit and try to bypass it.
[Important clarification ā the materials in the article are presented solely for informational and educational purposes. The author does not encourage their use for commercial purposes.]
Investigating the issue
We have: instead of ten profiles with pagination, the search only returns three, after which there is a block suggesting a premium account, and below are blurred and non-clickable profiles.
Immediately, one reaches for the developer console to check these hidden profiles ā perhaps we can remove some styles that apply the blur, or extract information from the block in the markup. But, quite predictably, these profiles are just and do not store any information.

Okay, now let's look in the Network tab and check if the alternative search result returns only three profiles. We find the request to "/api/search/blended" and look at the response.

Profiles come in the `included` array, but there are actually 15 entities in it. In this case, the first three are objects with additional information, each object contains information about a specific profile (for example, whether the profile is premium).

NÄkamie 12 ir reÄli profili ā meklÄÅ”anas rezultÄti, no kuriem mums rÄdÄ«s tikai trÄ«s. KÄ jau var nojaust, parÄdÄ«s tikai tos, par kuriem nÄk papildus informÄcija (pirmie trÄ«s objekti). PiemÄram, ja Åem vÄrÄ atbildi no profila bez limita, tad saÅemsim 28 entitÄtes ā 10 objektus ar papildu informÄciju un 18 profilus.
Atbilde profilam bez limita

KÄpÄc profilu nÄk vairÄk nekÄ 10, lai gan tiek pieprasÄ«ti tieÅ”i 10, un tie nekÄdÄ veidÄ nepiedalÄs attÄloÅ”anÄ, pat nÄkamajÄ lapÄ to nebÅ«s ā pagaidÄm nezinu. Ja analizÄjam pieprasÄ«juma URL, tad var redzÄt, ka count=10 (cik profilu atgriezt atbildÄ, maksimÄli 49).
BūŔu priecÄ«gs par jebkÄdiem komentÄriem Å”ajÄ jautÄjumÄ.
EksperimentÄjam
Labi, vissvarÄ«gÄkais, ko tagad noteikti zinÄm ā profilu atnÄk vairÄk, nekÄ mums parÄda. Tas nozÄ«mÄ, ka varam iegÅ«t vairÄk datus, neskatoties uz limitu. MÄÄ£inÄsim izsist API paÅ”i, tieÅ”i no konsoles, ar fetch palÄ«dzÄ«bu.

GaidoÅ”i, saÅemam kļūdu, 403. Tas saistÄ«ts ar droŔību, Å”eit mÄs nesÅ«tÄm CSRF tokenu (. Ja divos vÄrdos ā katram pieprasÄ«jumam pievieno unikÄlu tokenu, kuru pÄrbauda serverÄ« uz autentiskumu).

To var nokopÄt no jebkura cita veiksmÄ«ga pieprasÄ«juma vai arÄ« no sÄ«kdatnÄm, kur tas tiek glabÄts laukÄ 'JSESSIONID'.
Kur atrast tokenuCita pieprasījuma galvene:

Vai no sÄ«kdatnÄm, tieÅ”i caur konsoli:

MÄÄ£inÄm vÄlreiz, Å”oreiz pÄrsÅ«tÄm fetch iestatÄ«jumus, kuros norÄdÄm parametrÄ galvenÄ mÅ«su csrf-token.

VeiksmÄ«gi, mÄs saÅemam visus 10 profilus. :tada:
SakarÄ ar atŔķirÄ«bu galvenÄs atbildes struktÅ«ra nedaudz atŔķiras no tÄs, kas nÄk oriÄ£inÄlajÄ pieprasÄ«jumÄ. Var iegÅ«t tÄdu paÅ”u struktÅ«ru, ja pievieno 'Accept: 'application/vnd.linkedin.normalized+json+2.1', mÅ«su objektam, blakus csrf tokenam.
Atbildes piemÄrs ar pievienoto galveni
Kas tÄlÄk?
TÄlÄk var rediÄ£Ät (ar roku vai automatizÄt) parametru `start`, kas norÄda uz indeksu, sÄkot no kura mums atdos 10 profilus (noklusÄjuma = 0) no visa meklÄÅ”anas rezultÄta. Citiem vÄrdiem sakot, palielinot to par 10 pÄc katra pieprasÄ«juma, mums iegÅ«st klasisku lapu izsniegÅ”anu, pa 10 profiliem katrÄ reizÄ.
Å ajÄ posmÄ man bija pietiekami daudz datu un brÄ«vÄ«bas, lai turpinÄtu darbu pie sava pet-projekta. Bet bÅ«tu grÄks neizmantot Å”os datus tieÅ”i vietÄ, ja tie ir pieejami. Ember, kas tiek izmantots frontendÄ, netiks skarts. VietnÄ bija pieslÄgts jQuery, un, atsaucoties uz atmiÅÄ saglabÄtajÄm pamatzinÄÅ”anÄm, var dažu minūŔu laikÄ izveidot sekojoÅ”o.
Kods uz 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="/lv/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="/lv/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>`
);
};
// izsaucam API, iegūstam datus un izveidojam profilus
const fetchProfiles = () => {
// token
const csrf = 'ajax:9082932176494192209';
// objekts ar pieprasījuma iestatījumiem, nododam tokenu
const settings = { headers: { 'csrf-token': csrf } }
// pieprasÄ«juma URL, ar dinamisku sÄkuma indeksu beigÄs
const url = `https://www.linkedin.com/voyager/api/search/blended?count=10&filters=List(geoRegion-jp0,network-S,resultType-PEOPLE)&origin=FACETED_SEARCH&q=all&queryContext=List(spellCorrectionEnabled-true,relatedSearchesEnabled-true)&start=${nextItemIndex}`;
/* veicam pieprasÄ«jumu, katram profilam atbildÄ izsaucam bloka izveides funkciju, un pÄc tam inkrementÄjam sÄkuma indeksu par 10 */
fetch(url, settings).then(response => response.json()).then(data => {
data.elements[0].elements.forEach(createProfileBlock);
nextItemIndex += 10;
});
};
// dzÄšam visus profilus no saraksta
$('.search-results__list').find('li').remove();
// ievietojam profilu ielÄdes pogu
$('.search-results__list').after('<button id="load-more">IelÄdÄt vairÄk</button>');
// pievienojam funkcionalitÄti pogai
$('#load-more').addClass('artdeco-button').on('click', fetchProfiles);
// iestata noklusÄjuma profila indeksu pieprasÄ«jumam
window.nextItemIndex = 0;
Ja to izpildÄ«s tieÅ”i lapas meklÄÅ”anas konsolÄ, tas pievienos pogu, kas ielÄdÄ 10 jaunus profilus katru reizi, kad tÄ tiek nospiesta, un izsauc tos sarakstÄ. Protams, pirms tam ir jÄmaina piekļuves tokens un URL uz vajadzÄ«go. Profila bloks saturÄs vÄrdu, amatu, atraÅ”anÄs vietu, saiti uz profilu un attÄlu-zemÅ«dens attÄlu.

SecinÄjums
TÄdÄjÄdi ar minimÄlu piepÅ«li mÄs spÄjam atrast ievainojamÄ«bu un atgriezt meklÄÅ”anu bez ierobežojumiem. Bija jÄanalizÄ dati un to ceļŔ, jÄiekļūst paÅ”Ä pieprasÄ«jumÄ.
Es nevaru teikt, ka tas ir nopietns problÄmas jautÄjums LinkedIn, jo tas nerada nekÄdas briesmas. Maksimums, tas ir pazaudÄta peļÅa no Å”Ädiem "apmÄriem", kas ļauj nemaksÄt par premium. IespÄjams, Å”Äda servera atbilde ir nepiecieÅ”ama citu vietnes daļu normÄlai darbÄ«bai, vai varbÅ«t tas ir vienkÄrÅ”i izstrÄdÄtÄju nevÄrÄ«ba, viÅu resursu trÅ«kums neļauj izdarÄ«t labu darbu. (Ierobežojums parÄdÄ«jÄs no 2015. gada janvÄra, pirms tam ierobežojumu nebija.).
P.S.
Protams, kods uz jQuery ir diezgan primitÄ«vs Å”Ädu iespÄju piemÄrs. Å obrÄ«d esmu izveidojis pÄrlÅ«kprogrammas paplaÅ”inÄjumu savÄm vajadzÄ«bÄm. Tas pievieno kontroles pogas un renderÄ pilnvÄrtÄ«gus profilus ar attÄliem, uzaicinÄjuma pogu un kopÄjiem savienojumiem. Plus, tas dinamiski vÄc atraÅ”anÄs vietu, uzÅÄmumu un citu filtru datus, iegÅ«st token no sÄ«kdatnÄm. TÄdÄjÄdi nav nepiecieÅ”ams nekÄdas koda Ā«grÅ«tiĀ». Un pievieno papildu iestatÄ«jumu laukus, piemÄram, "cik profilus pieprasÄ«t vienlaicÄ«gi, lÄ«dz 49".

Es joprojÄm strÄdÄju pie Ŕī papildinÄjuma un plÄnoju to izdot publiskai pieejamÄ«bai. Rakstiet, ja jums tas interesÄ.
Avots: habr.com


