Limit
Na LinkedIn existuje také toto omezení — . Je velmi pravděpodobné, že vy, stejně jako já donedávna, jste se s ním nikdy nesetkali a neslyšeli o něm.

Podstata omezení spočívá v tom, že pokud příliš často používáte vyhledávání lidí mimo vaše kontakty (neexistují žádné přesné metriky, rozhoduje algoritmus na základě vašich akcí — jak často a mnoho jste vyhledávali, přidávali lidi), výsledek vyhledávání bude omezen na tři profily místo 1000 (standardně 100 stránek po 10 profilech na stránku). Limit se resetuje na začátku každého měsíce. Pochopitelně, .
Ale nedávno, pro jeden pet-projekt, jsem začal hodně experimentovat s vyhledáváním na LinkedIn a náhle jsem dostal toto omezení. Pochopitelně, to se mi příliš nelíbilo, neboť jsem ho nepoužil k žádným komerčním účelům, takže první myšlenkou bylo prozkoumat omezení a pokusit se ho obejít.
[Důležité upřesnění — materiály v článku jsou prezentovány výhradně pro informační a vzdělávací účely. Autor nenabádá k jejich použití k komerčním účelům.]
Zkoumáme problém
Máme: místo deseti profilů s paginací, vyhledávání zobrazuje pouze tři, za nimiž následuje blok s "doporučením" prémiového účtu a níže jsou rozmazané a neklikatelné profily.
Okamžitě saháme po konzoli vývojáře, abychom se podívali na tyto skryté profily — možná můžeme odstranit nějaké styly, které způsobují rozmazání, nebo vytáhnout informace z bloku v markup. Ale, jak se dalo očekávat, tyto profily jsou pouze a žádné informace neukrývají.

Dobře, nyní se podívejme na záložku Síť a zkontrolujme, zda skutečně dochází k alternativnímu vracení výsledků vyhledávání, které vrací pouze tři profily. Najdeme náš zajímavý dotaz na “/api/search/blended” a podíváme se na odpověď.

Profily přicházejí v poli `included`, ale entit v něm je hned 15. V tomto případě, první tři z nich jsou objekty s doplňujícími informacemi, každý objekt obsahuje informace o konkrétním profilu (například zda je profil prémiový).

Nasledujúcich 12 sú skutočné profily — výsledky vyhľadávania, z ktorých nám ukážu len tri. Ako už možno uhádnuť, ukazuje iba tých, na ktorých prichádza dodatočná informácia (prvé tri objekty). Napríklad, ak vezmeme odpoveď z profilu bez limitu, prídu 28 entít — 10 objektov s doplňujúcou informáciou a 18 profilov.
Odpoveď pre profil bez limitu

Prečo prichádza viac profilov ako 10, hoci sa žiada práve 10, a nijak sa nezúčastňujú na zobrazení, ani na ďalšej stránke ich nebude — zatiaľ neviem. Ak analyzujeme URL požiadavky, môžeme vidieť, že count=10 (koľko profilov vráti v odpovedi, maximálne 49).
Budem rád za akékoľvek komentáre k tomu.
Experimentujeme
Dobre, najdôležitejšie je, že teraz presne vieme — profilov prichádza v odpovedi viac, ako nám ukazujú. Znamená to, že môžeme získať viac údajov, bez ohľadu na limit. Skúsme vyvolať API sami, priamo z konzoly, pomocou fetch.

Očakávane, dostávame chybu, 403. To súvisí s bezpečnosťou, tu neodosielame CSRF token (. Ak to zjednodušíme — k každej požiadavke sa pridáva jedinečný token, ktorý sa na serveri overuje na pravosť).

Môže sa skopírovať z akéhokoľvek iného úspešného požiadavky alebo z cookies, kde sa uchováva v poli ‘JSESSIONID’.
Kde nájsť tokenZahlavie inej požiadavky:

Alebo z cookies, priamo cez konzolu:

Skúšame znova, tentoraz posielame do fetch nastavenia, v ktorých špecifikujeme parameter v hlavičke náš csrf-token.

Úspech, prichádzajú nám všetky 10 profily. :tada:
Z dôvodu rozdielu v hlavičkách štruktúra odpovede sa trochu líši od toho, čo prichádza v originálnej požiadavke. Môžeme získať rovnakú štruktúru, ak pridáme ‘Accept: ‘application/vnd.linkedin.normalized+json+2.1’ do nášho objektu, vedľa csrf tokenu.
Príklad odpovede s pridanou hlavičkou
Čo ďalej?
Ďalej je možné upraviť (ručne alebo automatizovať) parameter `start`, ktorý označuje index, od ktorého nám odovzdajú 10 profilov (predvolene = 0) z celkového výsledku vyhľadávania. Inými slovami, incrementovaním na 10 po každej požiadavke, dostaneme bežné stránkovanie, po 10 profilov za raz.
V tejto fáze som mal dostatok údajov a slobodu pokračovať v projekte. Ale bola by chyba nevyskúšať tieto údaje zobraziť priamo na mieste, keďže sú k dispozícii. Do Ember, ktorý sa používa na fronte, sa nepustíme. Na stránke bola pripojená jQuery a po vykopaní základného syntaktického vedomia možno za pár minút vytvoriť nasledujúce.
Kód na 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="/sk/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="/sk/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>`
);
};
// načítame API, získavame údaje a vykresľujeme profily
const fetchProfiles = () => {
// token
const csrf = 'ajax:9082932176494192209';
// objekt s nastaveniami požiadavky, posielame token
const settings = { headers: { 'csrf-token': csrf } }
// URL požiadavky, s dynamickým indexom štartu na konci
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}`;
/* robíme požiadavku, pre každý profil v odpovedi voláme vykreslenie bloku, a potom inkrementujeme štartovací index o 10 */
fetch(url, settings).then(response => response.json()).then(data => {
data.elements[0].elements.forEach(createProfileBlock);
nextItemIndex += 10;
});
};
// odstraňujeme všetky profily zo zoznamu
$('.search-results__list').find('li').remove();
// vkladáme tlačidlo na načítanie profilov
$('.search-results__list').after('<button id="load-more">Načítať viac</button>');
// pridávame funkcionalitu na tlačidlo
$('#load-more').addClass('artdeco-button').on('click', fetchProfiles);
// nastavujeme predvolený index profilu pre požiadavku
window.nextItemIndex = 0;
Ak to spustíte priamo v konzole na stránke vyhľadávania, pridá to tlačidlo, ktoré načíta 10 nových profilov pri každom kliknutí a renderuje ich ako zoznam. Samozrejme, token a URL je potrebné predtým zmeniť na potrebné. Blok profilu bude obsahovať meno, pozíciu, lokalitu, odkaz na profil a obrázok ako zástupcu.

Záver
Takto sme pri minimálnom úsilí dokázali nájsť zraniteľné miesto a vrátiť si vyhľadávanie bez obmedzení. Stačilo analyzovať údaje a ich cestu, nahliadnuť do samotného dopytu.
Nemôžem povedať, že by to bol vážny problém pre LinkedIn, pretože to nepredstavuje žiadne ohrozenie. Maximálne, ide o stratený zisk kvôli takýmto "obchádzaniu", ktoré umožňuje neplatiť za prémiu. Možno je takáto reakcia servera potrebná pre správne fungovanie iných častí stránky, alebo je to jednoducho lenivosť vývojárov a nedostatok zdrojov, ktorý im bráni urobiť to poriadne. (Obmedzenie sa objavilo od januára 2015, predtým limit neexistoval).
P.S.
Samozrejme, kód na jQuery je pomerne primitívny príklad možností. V súčasnosti som vytvoril rozšírenie pre prehliadač podľa svojich potrieb. Pridáva kontrolné tlačidlá a renderuje kompletné profily s obrázkami, pozvánkovým tlačidlom a spoločnými kontaktmi. Plus dynamicky zhromažďuje filtre lokalít, spoločností a iného, ťahá token z cookie. Takže už nie je potrebné nič hardkódovať. A pridáva ďalšie nastavenia, ako „koľko profilov požadovať naraz, do 49“.

Na tomto rozšírení stále pracujem a plánujem ho zverejniť pre verejnosť. Napíšte, ak máte záujem.
Zdroj: habr.com


