Piirang
LinkedIn'is on selline piirang — . Äärmiselt tõenäoliselt ei ole te, nagu mina veel hiljuti, kunagi sellise olukorraga kokku puutunud ega sellest kuulnud.

Piirangu olemus seisneb selles, et kui te otsite inimesi väljaspool oma kontakte liiga tihti (täpseid mõõdikke pole, algoritm otsustab teie tegevuste põhjal — kui sageli ja kui palju olete inimesi otsinud ja lisanud), siis otsingutulemus piirdub kolme profiiliga, asemel 1000 (eelnevalt 100 lehte, 10 profiili lehe kohta). Piirang taastatakse iga kuu alguses. Loomulikult, .
Kuid mitte nii kaua aega tagasi, ühe väikese projekti raames, hakkasin LinkedInis palju otsima ja ühel hetkel sain selle piirangu. Loomulikult ei meeldinud see mulle, kuna ma ei kasutanud seda mingitel äriliselt eesmärkidel, seega oli esimeseks mõtteks uurida piirangut ja proovida seda mööda hiilida.
[Oluline täpsustus — artiklis esitatud materjalid on mõeldud ainult tutvumiseks ja harimiseks. Autor ei julgustada nende kasutamist äriliseks otstarbeks.]
Uurime probleemi
Meil on: kümne profiili asemel, mis lehekülgede kaupa, pole otsingust saadud ainult kolm, pärast mida kuvatakse plokk "soovitus" premium kontole ning allpool on hägused ja mitte klikkitavad profiilid.
Käsi sirutub kohe arendaja konsooli, et vaadata neid peidetud profiile — võib-olla saame eemaldada mõned stiilid, mis teevad häguseks, või hankida teavet plokist näitesees. Aga, nagu oodata võis, need profiilid on lihtsalt ja ei hoia mingit teavet.

Hea, nüüd vaatame jaotises Network ja kontrollime, kas tõepoolest toimub alternatiivne otsingu tulemuste toomine, mis naaseb ainult kolm profiili. Leidsime huvipakkuva päringu "\/api\/search\/blended" ja vaatame vastust.

Profiilid tulevad massiividest `included`, kuid nendes on kokku 15 objekti. Antud juhul on esimesed kolm neist — objektid täiendava informatsiooniga, iga objekt sisaldab konkreetse profiili teavet (näiteks, kas profiil on premium).

Järgmised 12 on tegelikud profiilid — otsingutulemid, millest me näitame ainult kolme. Nagu juba võib arvata, näitab see ainult neid, kelle kohta tuleb täiendavat teavet (esimesed kolm objekti). Näiteks, kui võtta vastus piiranguta profiililt, siis tuleb 28 üksust — 10 objekti täiendava teabega ja 18 profiili.
Vastus piiranguta profiili jaoks

Miks profiile saabub rohkem kui 10, kuigi küsitakse just 10, ja nad ei osale kuvamises, isegi järgmisel lehel neid ei ole — hetkel ei tea. Kui analüüsida päringu URL-i, siis saab näha, et count=10 (kui palju profiile vastuses tagastada, maksimum 49).
Olen igasuguste kommentaaride eest tänulik.
Eksperimenteerime
Hea on, et me teame nüüd täpselt — profiile tuleb vastuses rohkem, kui meile näidatakse. See tähendab, et me saame rohkem andmeid saada, hoolimata piirangutest. Proovime ise API-d kutsuda, otse konsoolist, kasutades fetch'i.

Ootuspäraselt saame vea, 403. See on seotud turvalisusega, siin me ei saada CSRF tokenit (. Lihtsalt öeldes — iga päringule lisatakse ainulaadne token, mida kontrollitakse serveris autentimise jaoks).

Seda saab kopeerida igast muust edukast päringust või küpsistest, kus see on salvestatud väljaandes 'JSESSIONID'.
Kust leida tokenitTeise päringu päis:

Või küpsistest, otse konsooli kaudu:

Proovime veel kord, seekord edastame fetch'i seadistustes, kus määrame päises meie csrf-token.

Edu, saame kõik 10 profiili. :tada:
Pealkirjade erinevuse tõttu on vastuse struktuur natuke erinev sellest, mis tuleb originaalses päringus. Saame sama struktuuri, kui lisame 'Accept: 'application/vnd.linkedin.normalized+json+2.1', meie objekti, koos csrf-tokeniga.
Näide vastusest lisatud päisega
Mis edasi?
Edasi saab redigeerida (käega või automatiseeritud) parameetrit `start`, mis näitab indeksit, millest alates me saame 10 profiili (vaikimisi = 0) kogu otsingu tulemusest. Teise sõnaga, suurendades seda 10 võrra pärast igat päringut, saame tavalise lehtede esituse, 10 profiili korraga.
Selles etapis oli mul piisavalt andmeid ja vabadust, et jätkata oma pet-projektiga. Kuid oleks patt neid andmeid kohapeal tõlgendada, kui need on käepärast. Ember, mida kasutatakse esiküljel, ei puutu asjasse. Veebilehel oli ühendatud jQuery ja meenutades baassüntaksit, saab mõne minutiga luua järgmist.
Kood jQuery's
/* рендер блока, принимаем данные профиля и вставляем блок в список профилей используя эти данные */
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="/et/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="/et/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">Laadi rohkem</button>');
// lisame nupu funktsionaalsuse
$('#load-more').addClass('artdeco-button').on('click', fetchProfiles);
// määrame vaikimisi profiili indeksi päringuks
window.nextItemIndex = 0;
Kui seda otse otsingulehe konsoolis käivitada, lisab see nupu, mis laadib iga kord 10 uut profiili ja kuvab need loendis. Loomulikult tuleb enne vahetada token ja URL vajalikeks. Profiiliblokk sisaldab nime, ametinimetust, asukohta, lingi profiilile ja pildi-ettepanekut.

Kokkuvõte
Nii suutsime minimaalsete pingutustega leida haavatava koha ja taastada piiranguteta otsingu. Piisavalt oli andmeid analüüsida ja vaadata päringut.
Ma ei saa öelda, et see oleks LinkedInile tõsine probleem, kuna see ei kujuta mingit ohtu. Maksimaalselt on see kadunud kasum selliste "ringide" tõttu, mis võimaldavad mitte maksta premium'i eest. Võib-olla on selline serveri vastus vajalik teiste veebisaidi osade korrektseks toimimiseks, või siis on see lihtsalt arendajate laiskus, mis tuleneb ressursside puudumisest, et teha asju korralikult. (Piirang kehtestati jaanuarist 2015, enne seda polnud mingit limiiti).
P.S.
Loomulikult on jQuery kood üsna primitiivne näide võimalustest. Hetkel olen loonud oma vajadustele vastava brauseri laienduse. See lisab juhtnuppe ja renderdab täisprofiile koos piltide, kutseknupuga ja ühiste kontaktidega. Samuti kogub see dünaamiliselt asukohti, ettevõtte filtreid ja muud, tõmmates tokeni küpsistest. Nii et pole vaja enam midagi kõvasti kodeerida. Ja see lisab lisaseade välja, nagu "kui palju profiile korraga küsida, kuni 49."

Selle täienduse kallal töötan endiselt ja plaanin selle avalikuks teha. Kirjutage, kui olete huvitatud.
Allikas: habr.com


