Walaupun tidak semestinya dikaitkan dengan baris arahan, merangkak web sering digunakan dalam domain masalah tertentu seperti ujian fungsi automatik dan pengesanan defacement. Tutorial ini menunjukkan bagaimana untuk melaksanakan rangka kerja CLI ringan yang disokong tindakannya berkisar di sekitar web merangkak. Mudah-mudahan, ini akan membawa jus kreatif anda mengalir, sama ada minat anda khusus untuk merangkak atau ke baris arahan. Teknologi yang dilindungi termasuk node.js, phantomjs, dan pelbagai pakej NPM yang berkaitan dengan kedua -dua Crawling dan CLI.
Kod sumber untuk tutorial ini boleh didapati di GitHub. Untuk menjalankan contoh -contoh, anda perlu mempunyai kedua -dua Node.js dan Phantomjs dipasang. Arahan untuk memuat turun dan memasangnya boleh didapati di sini: node.js, phantomjs.
menyediakan kerangka baris arahan asas
Komander membolehkan anda menentukan hujah -hujah yang disokong, sementara Prompt membolehkan anda (cukup tepat) meminta pengguna untuk input pada masa runtime. Hasil akhirnya adalah antara muka sintaktik yang manis untuk melakukan pelbagai tindakan dengan tingkah laku dinamik berdasarkan beberapa data yang dibekalkan pengguna.
Katakanlah, sebagai contoh, kami mahu perintah kami kelihatan seperti ini:
$ <span>node run.js -x hello_world </span>
titik masuk kami (run.js) mentakrifkan argumen yang mungkin seperti ini:
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
dan mentakrifkan pelbagai kes input pengguna seperti ini:
<span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>
Pada ketika ini, kami telah menentukan laluan asas yang mana kami dapat menentukan tindakan untuk melakukan, dan telah menambah petunjuk untuk menerima URL. Kami hanya perlu menambah modul untuk mengendalikan logik yang khusus untuk tindakan ini. Kita boleh melakukan ini dengan menambahkan fail bernama hello_world.js ke direktori tindakan:
<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>
Seperti yang anda lihat, modul ini dijangka dibekalkan dengan contoh objek PhantomJS (Phantominstance) dan URL (URL). Kami akan masuk ke dalam spesifik untuk menentukan contoh Phantomjs seketika, tetapi sekarang sudah cukup untuk melihat bahawa kami telah meletakkan asas untuk mencetuskan tindakan tertentu. Sekarang kita telah meletakkan konvensyen di tempat, kita dapat dengan mudah menambah tindakan baru dengan cara yang jelas dan waras.
Horseman adalah pakej Node.js yang menyediakan antara muka yang kuat untuk membuat dan berinteraksi dengan proses PhantomJS. Penjelasan yang komprehensif tentang Horseman dan ciri -cirinya akan menjamin artikelnya sendiri, tetapi cukup untuk mengatakan bahawa ia membolehkan anda dengan mudah mensimulasikan hampir apa -apa tingkah laku yang pengguna manusia mungkin dipamerkan dalam penyemak imbas mereka. Horseman menyediakan pelbagai pilihan konfigurasi, termasuk perkara seperti menyuntikkan jQuery secara automatik dan mengabaikan amaran sijil SSL. Ia juga menyediakan ciri -ciri untuk pengendalian kuki dan mengambil tangkapan skrin.
Setiap kali kita mencetuskan tindakan melalui kerangka CLI kami, skrip kemasukan kami (run.js) meneliti contoh penunggang kuda dan melewati modul tindakan yang ditentukan. Dalam kod pseudo ia kelihatan seperti ini:
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
Sekarang apabila kita menjalankan perintah kita, contoh penunggang kuda dan url input akan dihantar ke modul hello_world, menyebabkan Phantomjs meminta URL, menangkap kod statusnya, dan mencetak status ke konsol. Kami baru sahaja menjalankan Crawl Bona Fide pertama kami menggunakan Horseman. Giddyup!
Sila ambil perhatian: Contoh ini semata -mata untuk tujuan demonstrasi dan tidak boleh dianggap sebagai kaedah yang sesuai untuk mewujudkan repositori GitHub. Ia hanyalah satu contoh bagaimana seseorang boleh menggunakan Horseman untuk berinteraksi dengan aplikasi web. Anda harus menggunakan API GitHub rasmi jika anda berminat untuk membuat repositori dalam fesyen automatik.
marilah kita anggap bahawa merangkak baru akan dicetuskan seperti:
$ <span>node run.js -x hello_world </span>
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
Sebelum mana -mana yang boleh berlaku walaupun, kita perlu menambah logik untuk dijalankan.js untuk mencetuskan segera dan menangkap data. Kami melakukan ini dengan menambahkan kes ke pernyataan suis utama kami:
<span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>
Bagi logik merangkak create_repo itu sendiri, kami menggunakan pelbagai kaedah Horseman untuk menavigasi ke halaman log masuk GitHub, masukkan nama pengguna dan kata laluan yang dibekalkan, dan serahkan borang:
<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
$ <span>node run.js -x create_repo </span>
module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>
<span>switch (program.actionToPerform) { </span> <span>case 'create_repo': </span> prompt<span>.get([{ </span> <span>name: 'repository', </span> <span>description: 'Enter repository name', </span> <span>required: true </span> <span>}, { </span> <span>name: 'username', </span> <span>description: 'Enter GitHub username', </span> <span>required: true </span> <span>}, { </span> <span>name: 'password', </span> <span>description: 'Enter GitHub password', </span> <span>hidden: true, </span> <span>required: true </span> <span>}], function (err<span>, result</span>) { </span> <span>performAction( </span> phantomInstance<span>, </span> result<span>.username, </span> result<span>.password, </span> result<span>.repository </span> <span>); </span> <span>}); </span> <span>break; </span> <span>... </span>
phantomInstance <span>.open('https://github.com/login') </span> <span>.type('input[name="login"]', username) </span> <span>.type('input[name="password"]', password) </span> <span>.click('input[name="commit"]') </span>
<span>.waitForNextPage() </span>
<span>.evaluate(function () { </span> $ <span>= window.$ || window.jQuery; </span> <span>var fullHtml = $('body').html(); </span> <span>return !fullHtml.match(<span>/Incorrect username or password/</span>); </span><span>}) </span><span>.then(function (isLoggedIn) { </span> <span>if (!isLoggedIn) { </span> <span>throw 'Login failed'; </span> <span>} </span><span>}) </span>
.click('a:contains("Your profile")')
<span>.waitForNextPage()
</span>
<span>.click('nav[role="navigation"] a:nth-child(2)') </span><span>.waitForSelector('a.new-repo') </span>
merangkak untuk mengumpulkan data
Pendekatan ini berguna untuk corak struktur dan tingkah laku tertentu yang diketahui terlebih dahulu, bagaimanapun, anda mungkin mendapati bahawa anda perlu melaksanakan skrip yang lebih fleksibel pada satu ketika. Ini mungkin berlaku jika urutan tindakan anda mempunyai potensi untuk berbeza -beza secara meluas berdasarkan konteks atau menghasilkan pelbagai hasil yang berbeza. Ia juga akan berlaku jika anda perlu mengekstrak data dari dom.
Dalam kes sedemikian, anda boleh menggunakan kaedah Horseman (), yang membolehkan anda melaksanakan interaksi bentuk bebas dalam penyemak imbas dengan menyuntik sama ada JavaScript yang berkaitan dengan luaran atau luaran.
Bahagian ini menunjukkan contoh mengekstrak data asas dari halaman (pautan anchor, dalam kes ini). Satu senario di mana ini mungkin perlu membina crawler pengesanan defacement untuk memukul setiap URL di domain.
Seperti contoh terakhir kita, kita perlu menambah modul baru ke direktori Tindakan:
$ <span>node run.js -x hello_world </span>
dan kemudian tambahkan cangkuk untuk tindakan baru dalam run.js:
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
Sekarang bahawa kod ini ada, kita boleh menjalankan merangkak untuk mengekstrak pautan dari mana -mana halaman yang diberikan dengan menjalankan arahan berikut:
<span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>
Tindakan ini menunjukkan pengekstrakan data dari halaman, dan tidak menggunakan sebarang tindakan penyemak imbas yang dibina oleh Horseman. Ia secara langsung melaksanakan apa sahaja JavaScript yang anda masukkan ke dalam kaedah menilai (), dan berbuat demikian seolah -olah ia berjalan secara asli dalam persekitaran penyemak imbas.
Satu perkara terakhir harus diperhatikan dalam bahagian ini, yang disebutkan sebelumnya: Bukan sahaja anda boleh melaksanakan JavaScript tersuai dalam penyemak imbas menggunakan kaedah Evaluasi (), tetapi anda juga boleh menyuntik skrip luaran ke dalam persekitaran runtime sebelum berjalan logik penilaian anda. Ini boleh dilakukan seperti:
<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>
Dengan memperluaskan logik di atas, anda boleh melakukan hampir apa -apa tindakan di mana -mana laman web.
Kes penggunaan akhir yang saya ingin tunjukkan adalah bagaimana anda akan menggunakan Horseman untuk mengambil tangkapan skrin. Kita boleh melakukan ini dengan kaedah screenshotbase64 () Horseman, yang mengembalikan rentetan yang dikodkan oleh Base64 yang mewakili tangkapan skrin.
Seperti contoh sebelumnya, kita perlu menambah modul baru ke direktori tindakan:
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
dan kemudian tambahkan cangkuk untuk tindakan baru dalam run.js:
$ <span>node run.js -x create_repo </span>
Sekarang anda boleh mengambil tangkapan skrin dengan arahan berikut:
module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>
Alasan untuk menggunakan rentetan yang dikodkan Base64 (dan tidak, sebagai contoh, menyimpan imej sebenar) adalah bahawa mereka adalah cara yang mudah untuk mewakili data imej mentah. Jawapan StackOverflow ini lebih terperinci.
Jika anda ingin menyimpan imej sebenar, anda akan menggunakan kaedah screenshot ().
Tutorial ini telah cuba untuk menunjukkan kedua -dua microframework CLI adat dan beberapa logik asas untuk merangkak dalam node.js, menggunakan pakej Horseman untuk memanfaatkan Phantomjs. Semasa menggunakan kerangka CLI kemungkinan akan memberi manfaat kepada banyak projek, penggunaan merangkak biasanya terhad kepada domain masalah yang sangat spesifik. Satu kawasan yang sama adalah jaminan kualiti (QA), di mana merangkak boleh digunakan untuk ujian antara muka fungsional dan pengguna. Kawasan lain adalah keselamatan di mana, sebagai contoh, anda mungkin mahu merangkak laman web anda secara berkala untuk mengesan jika ia telah rosak atau sebaliknya dikompromikan.
Apa pun yang mungkin untuk projek anda, pastikan anda menentukan matlamat anda dengan jelas dan tidak dapat mengganggu yang mungkin. Dapatkan kebenaran apabila anda boleh, bersikap sopan sehingga tahap maksimum yang anda boleh, dan berhati -hati untuk tidak DDOS tapak. Jika anda mengesyaki bahawa anda menjana banyak trafik automatik maka anda mungkin, dan mungkin akan menilai semula matlamat, pelaksanaan, atau tahap kebenaran anda.
Bolehkah saya merangkak laman web yang memerlukan log masuk dengan Node.js dan Phantomjs Horseman? > Ya, dengan Phantomjs Horseman, anda boleh mengautomasikan proses pembalakan ke laman web. Ini membolehkan anda merangkak halaman yang hanya boleh diakses selepas log masuk. Walau bagaimanapun, anda harus sedar bahawa ini mungkin melanggar syarat perkhidmatan laman web. Crawler web hanya menghuraikan HTML statik halaman web. Walau bagaimanapun, dengan alat seperti Phantomjs Horseman, anda boleh membuat JavaScript dan berinteraksi dengan kandungan dinamik seperti pengguna manusia. Ini membolehkan anda merangkak dan mengekstrak data dari laman web yang sangat bergantung pada JavaScript untuk penjanaan kandungan.
Atas ialah kandungan terperinci Web merangkak dengan nod, phantomjs dan penunggang kuda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!