„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Apriboti

„LinkedIn“ yra toks apribojimas – Komercinio naudojimo apribojimas. Labai tikėtina, kad jūs, kaip ir aš iki šiol, niekada apie tai neteko susidurti ir negirdėti.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Ribos esmė ta, kad jei per dažnai naudojate žmonių, nepriklausančių jūsų kontaktams, paiešką (tikslių metrikų nėra, algoritmas sprendžia pagal jūsų veiksmus – kaip dažnai ir kiek ieškojote, įtraukėte žmonių), tada paieškos rezultatas bus apribotas iki trijų profilių, o ne 1000 (numatytasis 100 puslapių, 10 profilių puslapyje). Limitas nustatomas iš naujo kiekvieno mėnesio pradžioje. Natūralu, „Premium“ sąskaitose šis apribojimas netaikomas.

Tačiau visai neseniai dėl naminių gyvūnėlių projekto pradėjau daug žaisti su LinkedIn paieška ir staiga gavau šį apribojimą. Natūralu, kad man tai labai nepatiko, nes jokiais komerciniais tikslais jo nenaudojau, todėl pirma mintis buvo ištirti apribojimą ir pabandyti jį apeiti.

[Svarbus paaiškinimas: straipsnyje pateikta medžiaga pateikiama tik informaciniais ir švietimo tikslais. Autorius neskatina jų naudoti komerciniais tikslais.]

Mes tiriame problemą

Turime: vietoj dešimties profilių su puslapiais, paieška pateikia tik tris, po kurių įterpiamas blokas su „premium“ paskyros „rekomendacija“, o žemiau yra neryškūs ir nespaudžiami profiliai.

Iš karto ranka ištiesia kūrėjo pultą, kad pažiūrėtų į šiuos paslėptus profilius – galbūt galime pašalinti kai kuriuos suliejančius stilius arba išgauti informaciją iš žymėjimo bloko. Tačiau, tikėtina, šie profiliai yra teisingi vietos rezervavimo paveikslėliai ir jokia informacija nesaugoma.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Gerai, dabar pažiūrėkime į skirtuką Tinklas ir patikrinkime, ar alternatyvūs paieškos rezultatai, pateikiantys tik tris profilius, iš tikrųjų veikia. Surandame mus dominančią užklausą „/api/search/blended“ ir žiūrime į atsakymą.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Profiliai yra masyve „įtraukta“, tačiau jame jau yra 15 objektų. Šiuo atveju pirmieji trys iš jų yra objektai su papildoma informacija, kiekviename objekte yra informacija apie konkretų profilį (pavyzdžiui, ar profilis yra aukščiausios kokybės). ).

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Kiti 12 yra tikri profiliai – paieškos rezultatai, iš kurių tik trys bus rodomi mums. Kaip jau spėjote, rodomi tik tie, kurie gauna papildomos informacijos (pirmi trys objektai). Pavyzdžiui, jei paimsite atsakymą iš profilio be apribojimų, gausite 28 objektus – 10 objektų su papildomais. informacija ir 18 profilių.

Atsakymas į profilį be apribojimų„LinkedIn“ paieškos limito aplenkimas žaidžiant su API
„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Kodėl atkeliauja daugiau nei 10 profilių, nors prašoma lygiai 10, ir jie niekaip nedalyvauja ekrane, net kitame puslapyje jų nebus - kol kas nežinau. Jei analizuosite užklausos URL, pamatysite, kad skaičius = 10 (kiek profilių grąžinti atsakyme, daugiausia 49).

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Man būtų malonu gauti bet kokių pastabų šiuo klausimu.

Eksperimentuokime

Gerai, svarbiausias dalykas, kurį dabar tikrai žinome, yra tai, kad atsakyme yra daugiau profilių, nei jie mums rodo. Tai reiškia, kad galime gauti daugiau duomenų, nepaisant apribojimo. Pabandykime patys ištraukti API tiesiai iš konsolės, naudodami „fetch“.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Kaip ir tikėtasi, gauname klaidą 403. Taip yra dėl saugumo, čia mes nesiunčiame CSRF prieigos rakto (CSRF Vikipedijoje. Trumpai tariant, prie kiekvienos užklausos pridedamas unikalus prieigos raktas, kurio autentiškumas tikrinamas serveryje).

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Ją galima nukopijuoti iš bet kurios kitos sėkmingos užklausos arba iš slapukų, kur jis saugomas lauke „JSESSIONID“.

Kur rasti žetonąKitos užklausos antraštė:

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Arba iš slapukų tiesiai per konsolę:

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Pabandykime dar kartą, šį kartą perduodame parametrus gauti, kurių antraštėje kaip parametrą nurodome savo csrf-tokeną.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Sėkmės, gauname visus 10 profilių. :tada:

Dėl skirtingų antraščių atsakymo struktūra šiek tiek skiriasi nuo tos, kuri buvo gauta pradinėje užklausoje. Tą pačią struktūrą galite gauti, jei prie mūsų objekto šalia csrf prieigos rakto pridėsite „Priimti: „application/vnd.linkedin.normalized+json+2.1“.
Atsakymo pavyzdys su pridėta antrašte„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Daugiau apie antraštę Priimti

Kas toliau?

Tada galite redaguoti (rankiniu būdu arba automatizuoti) parametrą `start`, nukreipdami į indeksą, nuo kurio mums bus suteikta 10 profilių (numatytasis = 0) iš viso paieškos rezultato. Kitaip tariant, padidinę jį 10 po kiekvieno užklausos, gauname įprastą kiekvieno puslapio išvestį, 10 profilių vienu metu.

Šiame etape turėjau pakankamai duomenų ir laisvės toliau dirbti su augintinio projektu. Tačiau būtų buvę nuodėmė nebandyti šių duomenų rodyti vietoje, nes jie jau buvo po ranka. Mes nesigilinsime į Ember, kuri naudojama priekyje. „jQuery“ buvo prijungtas prie svetainės, o atmintyje išsėmę pagrindinės sintaksės žinias, per kelias minutes galite sukurti toliau pateiktą informaciją.

jQuery kodas

/* рендер блока, принимаем данные профиля и вставляем блок в список профилей используя эти данные */
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="/lt/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="/lt/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;

Jei tai padarysite tiesiogiai paieškos puslapyje esančioje konsolėje, bus pridėtas mygtukas, kuris su kiekvienu paspaudimu įkelia 10 naujų profilių ir pateikia juos sąraše. Žinoma, prieš tai darydami pakeiskite prieigos raktą ir URL į reikiamą. Profilio bloke bus nurodytas vardas, padėtis, vieta, nuoroda į profilį ir rezervuotos vietos vaizdas.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

išvada

Taigi su minimaliomis pastangomis pavyko rasti silpnąją vietą ir be apribojimų atgauti paieškas. Užteko išanalizuoti duomenis ir jų kelią, pažvelgti į patį užklausą.

Negaliu sakyti, kad tai rimta LinkedIn problema, nes tai nekelia jokios grėsmės. Didžiausias prarastas pelnas dėl tokių „apeitų“, leidžiančių nemokėti už priemoką. Galbūt toks serverio atsakymas reikalingas, kad kitos svetainės dalys tinkamai veiktų, arba tiesiog kūrėjų tingumas ir resursų trūkumas neleidžia to padaryti gerai. (Apribojimas atsirado 2015 m. sausio mėn.; iki tol limito nebuvo).

PS

Natūralu, kad jQuery kodas yra gana primityvus galimybių pavyzdys. Šiuo metu sukūriau savo poreikius atitinkantį naršyklės plėtinį. Jame pridedami valdymo mygtukai ir pateikiami visi profiliai su nuotraukomis, kvietimo mygtukas ir bendrieji ryšiai. Be to, jis dinamiškai renka vietovių, įmonių ir kitų dalykų filtrus ir nuskaito prieigos raktą iš slapukų. Taigi nebereikia nieko koduoti. Na, tai prideda papildomų nustatymų laukų, a la „kiek profilių vienu metu prašyti, iki 49“.

„LinkedIn“ paieškos limito aplenkimas žaidžiant su API

Aš vis dar dirbu su šiuo papildymu ir planuoju jį paskelbti viešai. Rašykite jei domina.

Šaltinis: www.habr.com

Добавить комментарий