Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Omejitev

Na LinkedInu obstaja taka omejitev - Omejitev komercialne uporabe. Zelo verjetno je, da se z njim, tako kot jaz do nedavnega, še nikoli niste srečali ali slišali.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Bistvo omejitve je v tem, da če prepogosto uporabljate iskanje ljudi izven vaših stikov (natančne metrike ni, algoritem se odloči glede na vaša dejanja – kako pogosto in koliko ste iskali, dodajali osebe), potem rezultat iskanja bo omejen na tri profile, namesto na 1000 (privzeto 100 strani, 10 profilov na stran). Limit se ponastavi na začetku vsakega meseca. seveda, Premium računi nimajo te omejitve.

Toda nedolgo nazaj sem se za hišni projekt začel veliko igrati z iskanjem LinkedIn in nenadoma sem dobil to omejitev. Seveda mi to ni bilo preveč všeč, saj ga nisem uporabljal v nobene komercialne namene, zato je bila moja prva misel, da preučim omejitev in jo poskušam zaobiti.

[Pomembno pojasnilo: gradiva v članku so predstavljena izključno v informativne in izobraževalne namene. Avtor ne spodbuja njihove uporabe v komercialne namene.]

Preučujemo problem

Imamo: namesto desetih profilov s paginacijo, iskanje vrne samo tri, po katerih se vstavi blok s "priporočilom" premium računa in spodaj so zamegljeni in neklikabilni profili.

Roka takoj seže do konzole za razvijalce, da bi si ogledala te skrite profile - morda lahko odstranimo nekatere sloge zamegljevanja ali izvlečemo informacije iz bloka v označevanju. A povsem pričakovano so ti profili le nadomestne slike in nobena informacija ni shranjena.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

V redu, zdaj pa poglejmo zavihek Omrežje in preverimo, ali alternativni rezultati iskanja, ki vrnejo samo tri profile, dejansko delujejo. Najdemo zahtevo, ki nas zanima za “/api/search/blended” in pogledamo odgovor.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Profili so v `included` matriki, vendar je v njej že 15 entitet. V tem primeru so prve tri objekti z dodatnimi informacijami, vsak objekt vsebuje informacije o določenem profilu (na primer, ali je profil premium). ).

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Naslednjih 12 je pravih profilov – rezultatov iskanja, od katerih se nam bodo prikazali le trije. Kot že ugibate, prikazuje samo tiste, ki prejmejo dodatne informacije (prvi trije objekti). Na primer, če vzamete odgovor iz profila brez omejitve, boste prejeli 28 entitet - 10 objektov z dodatnimi. informacij in 18 profilov.

Odgovor za profil brez omejitevZaobiti LinkedInovo omejitev iskanja z igranjem z API-jem
Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Zakaj pride več kot 10 profilov, čeprav jih je zahtevanih natanko 10, in nikakor ne sodelujejo pri prikazu, tudi na naslednji strani jih ne bo - še ne vem. Če analizirate URL zahteve, lahko vidite, da je count=10 (koliko profilov vrniti v odgovoru, največ 49).

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Vesel bom kakršnih koli komentarjev o tej zadevi.

Eksperimentirajmo

V redu, najpomembnejša stvar, ki jo zdaj zagotovo vemo, je, da je v odzivu več profilov, kot nam jih pokažejo. To pomeni, da lahko kljub omejitvi pridobimo več podatkov. Poskusimo API potegniti sami, neposredno iz konzole, s pomočjo pridobivanja.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Kot je bilo pričakovano, dobimo napako 403. To je zaradi varnosti, tukaj ne pošiljamo žetona CSRF (CSRF na Wikipediji. Na kratko, vsaki zahtevi je dodan edinstven žeton, katerega pristnost se preveri na strežniku).

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Lahko se kopira iz katere koli druge uspešne zahteve ali iz piškotkov, kjer je shranjen v polju 'JSESSIONID'.

Kje najti žetonGlava druge zahteve:

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Ali iz piškotkov, neposredno prek konzole:

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Poskusimo znova, tokrat posredujemo nastavitve za pridobivanje, v katerih kot parameter v glavi določimo naš csrf-token.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Uspelo, prejmemo vseh 10 profilov. :tada:

Zaradi razlike v glavah se struktura odgovora nekoliko razlikuje od prejetega v prvotni zahtevi. Enako strukturo lahko dobite, če dodate »Accept: 'application/vnd.linkedin.normalized+json+2.1' našemu objektu poleg žetona csrf.
Primer odgovora z dodano glavoZaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Več o glavi Accept

Kaj sledi?

Nato lahko uredite (ročno ali avtomatizirano) parameter `začetek`, ki kaže na indeks, od katerega bomo dobili 10 profilov (privzeto = 0) iz celotnega rezultata iskanja. Z drugimi besedami, s povečanjem za 10 po vsaki zahtevi dobimo običajen izpis stran za stranjo, 10 profilov hkrati.

Na tej stopnji sem imel dovolj podatkov in svobode za nadaljevanje dela na projektu hišnega ljubljenčka. A greh bi bil, če teh podatkov ne bi poskušal prikazati kar na licu mesta, saj so že bili pri roki. Ne bomo se spuščali v Ember, ki se uporablja spredaj. jQuery je bil povezan s spletnim mestom in ko ste v spominu izkopali znanje osnovne sintakse, lahko v nekaj minutah ustvarite naslednje.

koda 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="/sl/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="/sl/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;

Če to storite neposredno v konzoli na iskalni strani, bo dodan gumb, ki z vsakim klikom naloži 10 novih profilov in jih prikaže na seznamu. Preden to storite, seveda spremenite žeton in URL na zahtevanega. Blok profila bo vseboval ime, položaj, lokacijo, povezavo do profila in nadomestno sliko.

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Zaključek

Tako nam je z minimalnim trudom uspelo najti šibko točko in ponovno vzpostaviti iskanje brez omejitev. Dovolj je bilo analizirati podatke in njihovo pot, pogledati v samo zahtevo.

Ne morem reči, da je to resen problem za LinkedIn, ker ne predstavlja nobene grožnje. Največ je izgubljeni dobiček zaradi takšnih "obhodnih rešitev", ki vam omogoča, da se izognete plačilu premije. Morda je takšen odziv strežnika nujen za pravilno delovanje drugih delov strani ali pa gre le za lenobo razvijalcev in pomanjkanje sredstev, ki ne omogoča, da bi bilo dobro narejeno. (Omejitev se je pojavila januarja 2015; pred tem omejitve ni bilo).

PS

Seveda je koda jQuery precej primitiven primer zmožnosti. Trenutno sem ustvaril razširitev brskalnika, ki ustreza mojim potrebam. Doda nadzorne gumbe in upodablja polne profile s slikami, gumbom za povabilo in splošnimi povezavami. Poleg tega dinamično zbira filtre za lokacije, podjetja in druge stvari ter pridobi žeton iz piškotkov. Tako ni več treba ničesar trdo kodirati. No, dodaja dodatna polja z nastavitvami, a la "koliko profilov zahtevati hkrati, do 49."

Zaobiti LinkedInovo omejitev iskanja z igranjem z API-jem

Še vedno delam na tem dodatku in nameravam ga objaviti javnosti. Pišite, če vas zanima.

Vir: www.habr.com

Dodaj komentar