Obcházíme limit hledání LinkedIn pomocí API

Limit

Na LinkedIn existuje takové omezení — Limit komerčního použití. Je velmi pravděpodobné, že jste se, stejně jako já do nedávné doby, s tímto nesetkali a neslyšeli o něm.

Obcházíme limit hledání LinkedIn pomocí API

Podstata limitu spočívá v tom, že pokud často používáte vyhledávání lidí mimo své kontakty (neexistují přesné metriky, rozhoduje algoritmus na základě vašich akcí — jak často a kolik jste hledali, přidávali lidí), tak výsledky hledání budou omezeny 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. Přirozeně, prémiové účty toto omezení nemají..

Ale nedávno jsem pro jeden pet-projekt začal hodně experimentovat s hledáním na LinkedIn a najednou jsem dostal toto omezení. Přirozeně, to se mi moc nelíbilo, protože jsem ho nepoužíval k žádným komerčním účelům, takže prvním myšlenkou bylo prostudovat omezení a pokusit se ho obejít.

[Důležité upřesnění — materiály v článku jsou prezentovány výhradně pro informativní a vzdělávací účely. Autor nepodporuje jejich použití k komerčním účelům.]

Studujeme problém

Máme: místo deseti profilů s paginací, hledání vrací pouze tři, za kterými se objevuje blok s "doporučením" prémiového účtu a níže se nacházejí rozmazané a neklikatelné profily.

Ruka se okamžitě natáhne k nástroji pro vývojáře, aby se podívala na tyto skryté profily — možná můžeme odstranit nějaké styly, které způsobují rozmazání, nebo vytáhnout informace z bloku v značkování. Ale, jak se dalo očekávat, tyto profily jsou pouze obrázky-základky a žádné informace neuchovávají.

Obcházíme limit hledání LinkedIn pomocí API

Dobře, nyní se podíváme na kartu Síť a zkontrolujeme, zda skutečně funguje alternativní výstup výsledků hledání, který vrací pouze tři profily. Najdeme zajímavý dotaz na "/api/search/blended" a podíváme se na odpověď.

Obcházíme limit hledání LinkedIn pomocí API

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

Obcházíme limit hledání LinkedIn pomocí API

Následujících 12 jsou skutečné profily – výsledky vyhledávání, z nichž nám ukážou pouze tři. Jak už lze tušit, zobrazí se pouze ti, na které přichází další informace (první tři objekty). Například, pokud vezmeme odpověď z profilu bez limitu, přijde 28 entit – 10 objektů s doplňkovými informacemi a 18 profilů.

Odpověď pro profil bez limituObcházíme limit hledání LinkedIn pomocí API
Obcházíme limit hledání LinkedIn pomocí API

Proč přichází více než 10 profilů, i když je požadováno právě 10, a nikterak se nezapojí do zobrazení, ani na další stránce je nebudou? – zatím nevím. Pokud analyzujeme URL požadavku, můžeme vidět, že count=10 (kolik profilů vrátit v odpovědi, maximálně 49).

Obcházíme limit hledání LinkedIn pomocí API

Budu rád za jakékoli komentáře k tomu.

Experimentujeme

Dobře, to nejdůležitější, co nyní víme – profilů přichází v odpovědi více, než nám ukazují. To znamená, že můžeme získat více dat, ačkoli máme limit. Zkusme zavolat API sami, přímo z konzole, pomocí fetch.

Obcházíme limit hledání LinkedIn pomocí API

Očekávaně dostáváme chybu, 403. To je spojeno s bezpečností, zde neodesíláme CSRF token (CSRF na Wikipedii. Pokud to shrneme – ke každému požadavku se přidává unikátní token, který se na serveru ověřuje na pravost).

Obcházíme limit hledání LinkedIn pomocí API

Ten lze zkopírovat z jakéhokoli jiného úspěšného požadavku nebo z cookies, kde se ukládá v poli ‘JSESSIONID’.

Kde najít tokenZáhlaví jiného požadavku:

Obcházíme limit hledání LinkedIn pomocí API

Nebo z cookies, přímo přes konzoli:

Obcházíme limit hledání LinkedIn pomocí API

Zkoušíme znovu, tentokrát předáváme ve fetch nastavení, v nichž uvádíme parametr v záhlaví náš csrf-token.

Obcházíme limit hledání LinkedIn pomocí API

Úspěch, dostáváme všech 10 profilů. :tada:

Kvůli rozdílu v hlavičkách se struktura odpovědi mírně liší od toho, co přichází v originálním požadavku. Můžeme získat stejnou strukturu, pokud přidáme ‘Accept: ‘application/vnd.linkedin.normalized+json+2.1’ k našemu objektu vedle csrf tokenu.
Příklad odpovědi s přidanou hlavičkouObcházíme limit hledání LinkedIn pomocí API

Více o hlavičce Accept

Co dál?

Dále lze upravit (ručně nebo automatizovat) parametr `start`, který určuje index, od kterého nám dají 10 profilů (výchozí = 0) z celého výsledku vyhledávání. Jinými slovy, inkrementováním o 10 po každém požadavku, získáme klasické stránkování, po 10 profilech najednou.

V této fázi jsem měl dostatek dat a svobody pokračovat v práci na pet projektu. Bylo by hříchem nezkusit tato data přímo zobrazit, když jsou po ruce. Do Emberu, který se používá na frontendu, se vrtat nebudeme. Na webu byl připojen jQuery, a po vzpomínce na základní syntaxi lze během pár minut vytvořit následující.

Kód v 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="/cs/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="/cs/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>`
 );
};

// voláme API, získáváme data a vykreslujeme profily
const fetchProfiles = () =&gt; {
 // token
 const csrf = 'ajax:9082932176494192209';
 
 // objekt s nastavením žádosti, předáváme token
 const settings = { headers: { 'csrf-token': csrf } }

 // URL žádosti, s dynamickým indexem začátku 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}`; 
 /* provádíme žádost, pro každý profil v odpovědi voláme vykreslovací blok, a poté inkrementujeme počáteční 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šechny profily ze seznamu
$('.search-results__list').find('li').remove();
// vkládáme tlačítko pro načtení profilů
$('.search-results__list').after('<button id="load-more">Načíst více</button>');
// přidáváme funkčnost k tlačítku
$('#load-more').addClass('artdeco-button').on('click', fetchProfiles);

// nastavíme výchozí index profilu pro dotaz
window.nextItemIndex = 0;

Pokud to provedete přímo v konzoli na stránce vyhledávání, přidá to tlačítko, které načte 10 nových profilů s každým kliknutím a zobrazuje je jako seznam. Samozřejmě, token a URL předtím změňte na potřebné. Blok profilu bude obsahovat jméno, pozici, lokaci, odkaz na profil a zástupný obrázek.

Obcházíme limit hledání LinkedIn pomocí API

Závěr

Tímto způsobem jsme s minimem úsilí dokázali najít zranitelné místo a vrátit si neomezené vyhledávání. Stačilo analyzovat data a jejich cestu, nahlédnout do samotného dotazu.

Nemohu říct, že by to představovalo vážný problém pro LinkedIn, protože to nepředstavuje žádné ohrožení. Maximálně jde o ušlou ziskovost kvůli těmto »obejdům«, které umožňují neplatit za premium. Možná je taková odpověď serveru nezbytná pro správnou funkci dalších částí webu, nebo je to prostě lenost vývojářů, nedostatek zdrojů, který neumožňuje udělat to pořádně. (Omezení vzniklo v lednu 2015, předtím žádný limit nebyl).

P.S.

Přirozeně, kód v jQuery je dost primitivní příklad možností. V současnosti jsem vytvořil rozšíření pro prohlížeč podle svých potřeb. Přidává ovládací tlačítka a renderuje plnohodnotné profily s obrázky, tlačítkem pozvání a společnými kontakty. Navíc dynamicky sbírá filtry lokalit, firem a další, získává token z cookies. Takže už není potřeba nic hardcodit. A také přidává další nastavení, jako je »kolik profilů dotazovat najednou, až do 49«.

Obcházíme limit hledání LinkedIn pomocí API

Na tomto dodatku stále pracuji a plánuju ho zveřejnit jako open-source. Napište mi, pokud máte zájem.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster