Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Membatasi

Ada batasan seperti itu di LinkedIn - Batas penggunaan komersial. Kemungkinan besar Anda, seperti saya hingga saat ini, belum pernah menjumpai atau mendengarnya.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Inti dari batasannya adalah jika Anda terlalu sering menggunakan pencarian orang di luar kontak Anda (tidak ada metrik pasti, algoritme memutuskan berdasarkan tindakan Anda - seberapa sering dan seberapa banyak Anda mencari, menambahkan orang), maka hasil pencarian akan dibatasi pada tiga profil, bukan 1000 (default 100 halaman, 10 profil per halaman). Batasnya disetel ulang setiap awal bulan. Tentu saja, akun premium tidak memiliki batasan ini.

Namun belum lama ini, untuk proyek kesayangan, saya mulai banyak bermain-main dengan pencarian LinkedIn dan tiba-tiba mendapat batasan ini. Tentu saja, saya tidak terlalu menyukainya, karena saya tidak menggunakannya untuk tujuan komersial apa pun, jadi pikiran pertama saya adalah mempelajari batasannya dan mencoba menyiasatinya.

[Klarifikasi penting: materi dalam artikel disajikan semata-mata untuk tujuan informasi dan pendidikan. Penulis tidak menganjurkan penggunaannya untuk tujuan komersial.]

Kami sedang mempelajari masalahnya

Kami memiliki: alih-alih sepuluh profil dengan penomoran halaman, pencarian hanya menghasilkan tiga, setelah itu blok dengan "rekomendasi" akun premium dimasukkan dan di bawahnya adalah profil buram dan tidak dapat diklik.

Segera, tangan tersebut menjangkau konsol pengembang untuk melihat profil tersembunyi ini - mungkin kita dapat menghapus beberapa gaya buram, atau mengekstrak informasi dari blok di markup. Tapi, seperti yang diharapkan, profil-profil ini adil gambar pengganti dan tidak ada informasi yang disimpan.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Oke, sekarang mari kita lihat tab Jaringan dan periksa apakah hasil pencarian alternatif yang hanya menghasilkan tiga profil benar-benar berfungsi. Kami menemukan permintaan yang kami minati untuk β€œ/api/search/blended” dan melihat responsnya.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Profil datang dalam array `termasuk`, tetapi sudah ada 15 entitas di dalamnya. Dalam hal ini, tiga yang pertama adalah objek dengan informasi tambahan, setiap objek berisi informasi tentang profil tertentu (misalnya, apakah profil tersebut premium ).

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

12 berikutnya adalah profil nyata - hasil pencarian, yang hanya tiga yang akan ditampilkan kepada kami. Seperti yang sudah bisa Anda tebak, ini hanya menampilkan mereka yang menerima informasi tambahan (tiga objek pertama). Misalnya, jika Anda mengambil jawaban dari profil tanpa batas, Anda akan menerima 28 entitas - 10 objek dengan tambahan. informasi dan 18 profil.

Jawab untuk profil tanpa batasMelewati batas pencarian LinkedIn dengan bermain-main dengan API
Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Mengapa lebih dari 10 profil tiba, meskipun tepat 10 yang diminta, dan mereka tidak berpartisipasi dalam tampilan dengan cara apa pun, bahkan di halaman berikutnya tidak akan ada - saya belum tahu. Jika Anda menganalisis URL permintaan, Anda dapat melihat jumlah tersebut=10 (berapa banyak profil yang dikembalikan sebagai respons, maksimum 49).

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Saya akan dengan senang hati menerima komentar apa pun mengenai masalah ini.

Mari kita bereksperimen

Oke, hal terpenting yang sekarang kita ketahui dengan pasti adalah bahwa ada lebih banyak profil dalam tanggapan daripada yang ditunjukkan kepada kita. Artinya kita bisa mendapatkan lebih banyak data, meski ada batasannya. Mari kita coba menarik API sendiri, langsung dari konsol, menggunakan pengambilan.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Seperti yang diharapkan, kami mendapatkan error 403. Ini karena keamanan, di sini kami tidak mengirimkan token CSRF (CSRF di Wikipedia. Singkatnya, token unik ditambahkan ke setiap permintaan, yang diperiksa keasliannya di server).

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Itu dapat disalin dari permintaan lain yang berhasil atau dari cookie, yang disimpan di bidang 'JSESSIONID'.

Di mana menemukan tokennyaTajuk permintaan lain:

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Atau dari cookie, langsung melalui konsol:

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Mari kita coba lagi, kali ini kita meneruskan pengaturan ke pengambilan, di mana kita menentukan token csrf kita sebagai parameter di header.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Berhasil, kami menerima 10 profil semuanya. :tada:

Karena perbedaan header, struktur respons sedikit berbeda dari yang diterima pada permintaan awal. Anda bisa mendapatkan struktur yang sama jika Anda menambahkan 'Terima: 'application/vnd.linkedin.normalized+json+2.1' ke objek kami, di sebelah token csrf.
Contoh respons dengan header tambahanMelewati batas pencarian LinkedIn dengan bermain-main dengan API

Lebih lanjut tentang header Terima

Apa selanjutnya?

Kemudian Anda dapat mengedit (secara manual atau mengotomatisasi) parameter `start`, menunjuk ke indeks, mulai dari mana kita akan diberikan 10 profil (default = 0) dari keseluruhan hasil pencarian. Dengan kata lain, dengan menambahnya sebanyak 10 setelah setiap permintaan, kita mendapatkan keluaran halaman demi halaman seperti biasa, 10 profil sekaligus.

Pada tahap ini saya memiliki cukup data dan kebebasan untuk terus mengerjakan proyek kesayangan. Namun sayang jika tidak mencoba menampilkan data ini secara langsung, karena data tersebut sudah tersedia. Kami tidak akan membahas Ember, yang digunakan di bagian depan. jQuery telah terhubung ke situs tersebut, dan setelah menggali pengetahuan tentang sintaks dasar di memori, Anda dapat membuat yang berikut ini dalam beberapa menit.

kode 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="/id/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="/id/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;

Jika Anda melakukan ini langsung di konsol pada halaman pencarian, itu akan menambahkan tombol yang memuat 10 profil baru dengan setiap klik dan menampilkannya dalam daftar. Tentu saja, ubah token dan URL ke yang diperlukan sebelum melakukan ini. Blok profil akan berisi nama, posisi, lokasi, link ke profil dan gambar placeholder.

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Kesimpulan

Jadi, dengan sedikit usaha, kami dapat menemukan titik lemah dan mendapatkan kembali pencarian kami tanpa batasan. Cukup menganalisis data dan jalurnya, melihat permintaan itu sendiri.

Saya tidak bisa mengatakan bahwa ini adalah masalah serius bagi LinkedIn, karena tidak menimbulkan ancaman apa pun. Maksimumnya adalah hilangnya keuntungan karena β€œsolusi” tersebut, yang memungkinkan Anda menghindari pembayaran premi. Mungkin respons server seperti itu diperlukan agar bagian lain situs dapat berfungsi dengan benar, atau ini hanyalah kemalasan pengembang dan kurangnya sumber daya yang tidak memungkinkan hal ini dilakukan dengan baik. (Pembatasan muncul pada Januari 2015; sebelumnya tidak ada batasan).

PS

Tentu saja, kode jQuery adalah contoh kemampuan yang agak primitif. Saat ini saya telah membuat ekstensi browser untuk memenuhi kebutuhan saya. Ia menambahkan tombol kontrol dan menampilkan profil lengkap dengan gambar, tombol undangan, dan koneksi umum. Selain itu, ia secara dinamis mengumpulkan filter untuk lokasi, perusahaan, dan hal lainnya, serta mengambil token dari cookie. Jadi tidak perlu lagi melakukan hardcode apa pun. Ya, itu menambahkan bidang pengaturan tambahan, seperti β€œberapa banyak profil yang diminta sekaligus, hingga 49.”

Melewati batas pencarian LinkedIn dengan bermain-main dengan API

Saya masih mengerjakan tambahan ini dan berencana untuk merilisnya ke publik. Tulis jika Anda tertarik.

Sumber: www.habr.com

Tambah komentar