Pada masa kini, rangkak web adalah teknologi yang terkenal, tetapi masih terdapat banyak kerumitan perangkak web mudah masih sukar untuk mengatasi pelbagai teknologi kompleks seperti latihan putaran Ajax, XMLHttpRequest, WebSockets, Flash Sockets, dll. Dibangunkan moden. laman web.
Mari kita ambil keperluan asas kami pada projek Hubdoc sebagai contoh Dalam projek ini, kami mengikis jumlah bil, tarikh akhir, nombor akaun, dan yang paling penting, daripada tapak web bank, utiliti dan syarikat kad kredit. pdf bil terkini. Untuk projek ini, saya bermula dengan penyelesaian yang sangat mudah (tidak menggunakan produk komersil mahal yang kami nilai buat masa ini) - projek perangkak mudah yang telah saya lakukan sebelum menggunakan Perl di MessageLab/Symantec. Tetapi hasilnya adalah malapetaka. Spammers mencipta tapak web yang jauh lebih mudah daripada laman web bank dan syarikat utiliti.
Jadi bagaimana untuk menyelesaikan masalah ini? Kami terutamanya bermula dengan menggunakan perpustakaan permintaan yang sangat baik yang dibangunkan oleh Mikea. Buat permintaan dalam penyemak imbas, semak dalam tetingkap Rangkaian pengepala permintaan yang dihantar dan kemudian salin pengepala permintaan ini ke dalam kod. Prosesnya mudah sahaja. Ia hanya menjejaki proses daripada log masuk hingga memuat turun fail PDF, dan kemudian mensimulasikan semua permintaan dalam proses ini. Untuk memudahkan pengendalian perkara yang serupa dan membenarkan pembangun web menulis program perangkak dengan lebih rasional, saya mengeksport kaedah mendapatkan hasil daripada HTML ke dalam jQuery (menggunakan perpustakaan cheerio ringan), yang menjadikan serupa tugas mudah, dan juga memudahkan penggunaan pemilih CSS untuk memilih elemen pada halaman. Keseluruhan proses dibungkus ke dalam rangka kerja dan rangka kerja ini juga boleh melakukan kerja tambahan, seperti mengambil sijil daripada pangkalan data, memuatkan robot individu dan berkomunikasi dengan UI melalui socket.io.
Ini berfungsi untuk sesetengah tapak web, tetapi ia hanyalah skrip JS, bukan kod node.js saya yang syarikat ini letakkan di tapak mereka. Mereka telah menyusun isu warisan pada kerumitan, menjadikannya sangat sukar untuk memikirkan perkara yang perlu dilakukan untuk mendapatkan titik maklumat log masuk. Saya cuba selama beberapa hari untuk mendapatkan beberapa tapak dengan menggabungkan dengan perpustakaan request(), tetapi masih sia-sia.
Selepas hampir ranap, saya menemui node-phantomjs, perpustakaan yang membolehkan saya mengawal phantomjs pelayar webkit tanpa kepala daripada nod (Nota Penterjemah: Saya tidak mempunyai Pemikiran ini daripada kata nama yang sepadan, tanpa kepala di sini bermakna pemaparan halaman selesai di latar belakang tanpa peranti paparan). Ini kelihatan seperti penyelesaian yang mudah, tetapi masih terdapat beberapa masalah yang tidak dapat dielakkan dengan phantomj yang perlu diselesaikan:
1. PhantomJS hanya boleh memberitahu anda sama ada halaman telah dimuatkan, tetapi anda tidak boleh menentukan sama ada terdapat ubah hala melalui JavaScript atau teg meta dalam proses. Terutama apabila JavaScript menggunakan setTimeout() untuk menangguhkan panggilan.
2.PhantomJS memberikan anda cangkuk pageLoadStarted yang membolehkan anda mengendalikan isu yang dinyatakan di atas, tetapi fungsi ini hanya boleh digunakan apabila anda menentukan bilangan halaman yang akan dimuatkan dan apabila setiap halaman dimuatkan. dan menyediakan pengendalian untuk kemungkinan tamat masa (kerana ini tidak selalu berlaku) supaya apabila nombor anda berkurangan kepada 0, fungsi panggil balik anda dipanggil. Pendekatan ini berfungsi, tetapi ia sentiasa terasa seperti godam.
3. PhantomJS memerlukan proses bebas yang lengkap untuk setiap halaman yang dirangkak, kerana jika tidak, kuki antara setiap halaman tidak boleh dipisahkan. Jika anda menggunakan proses phantomjs yang sama, sesi dalam halaman log masuk akan dihantar ke halaman lain.
4. Tidak dapat memuat turun sumber menggunakan PhantomJS - anda hanya boleh menyimpan halaman sebagai png atau pdf. Ini berguna, tetapi ini bermakna kita perlu menggunakan request() untuk memuat turun pdf.
5. Disebabkan sebab di atas, saya mesti mencari cara untuk mengedarkan kuki daripada sesi PhantomJS ke perpustakaan sesi permintaan(). Hanya edarkan rentetan document.cookie, menghuraikannya dan menyuntiknya ke dalam balang kuki request().
6 Menyuntik pembolehubah ke dalam sesi pelayar bukanlah mudah. Untuk melakukan ini, saya perlu mencipta rentetan untuk mencipta fungsi Javascript.
8. Einige Websites sind immer voller Codes wie console.log() und müssen neu definiert und an den gewünschten Ort ausgegeben werden. Um dies zu erreichen, mache ich Folgendes:
10. Ich muss außerdem die maximale Parallelität von Browsersitzungen begrenzen, um sicherzustellen, dass wir den Server nicht in die Luft jagen. Allerdings liegt diese Grenze weit über dem, was teure kommerzielle Lösungen bieten können. (Anmerkung des Übersetzers: Die kommerzielle Lösung weist eine größere Parallelität auf als diese Lösung)
Nachdem die ganze Arbeit erledigt ist, habe ich eine anständige PhantomJS-Anfrage-Crawler-Lösung. Sie müssen sich mit PhantomJS anmelden, bevor Sie zur Anfrage()-Anfrage zurückkehren können. Dabei wird das in PhantomJS gesetzte Cookie verwendet, um die angemeldete Sitzung zu authentifizieren. Dies ist ein großer Gewinn, da wir den Stream von request() verwenden können, um die PDF-Datei herunterzuladen.
Der gesamte Plan besteht darin, es Webentwicklern relativ einfach zu machen, zu verstehen, wie man mit jQuery und CSS-Selektoren Crawler für verschiedene Websites erstellt. Ich habe noch nicht erfolgreich bewiesen, dass diese Idee machbar ist, aber ich glaube, dass dies bald der Fall sein wird .