Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

Limit

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

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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ě, prémiové účty toto omezení nemají..

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 obrázky-záplaty a žádné informace neukrývají.

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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ěď.

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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ý).

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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 limituObchádzame limit vyhľadávania LinkedIn, hraním sa s API
Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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).

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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.

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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:

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

Alebo z cookies, priamo cez konzolu:

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

Ú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čkouObchádzame limit vyhľadávania LinkedIn, hraním sa s API

Viac o hlavičke Accept

Č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 = () =&gt; {
 // 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&amp;filters=List(geoRegion-jp0,network-S,resultType-PEOPLE)&amp;origin=FACETED_SEARCH&amp;q=all&amp;queryContext=List(spellCorrectionEnabled-true,relatedSearchesEnabled-true)&amp;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 =&gt; response.json()).then(data =&gt; {
 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.

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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“.

Obchádzame limit vyhľadávania LinkedIn, hraním sa s API

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

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster