Klienta puses tīmekļa nokasīšana ar JavaScript, izmantojot jQuery un Regex

Kad veidoju savu pirmo atvērtā pirmkoda projektu codeBadges, es domāju, ka būs viegli iegūt lietotāja profila datus no visām galvenajām kodu apguves vietnēm.

Es biju pazīstams ar API izsaukumiem un pieprasījumu saņemšanu. Es domāju, ka es varētu vienkārši izmantot jQuery, lai ielādētu datus no dažādiem API un tos izmantotu.

var name = 'codemzy'; $.get('//api.github.com/users/' + name, function(response) { var followers = response.followers;});

Nu, tas bija viegli. Bet izrādās, ka ne katrai vietnei ir publiska API, kuru varat vienkārši paķert vēlamos datus.

Bet tas, ka nav publiskas API, nenozīmē, ka jums ir jāatsakās! Datu sagrābšanai varat izmantot tīmekļa nokasīšanu, veicot tikai nelielu papildu darbu .

Apskatīsim, kā mēs varam izmantot klienta puses tīmekļa nokasīšanu ar JavaScript.

Piemēram, es paņemšu savu lietotāja informāciju no sava publiskā freeCodeCamp profila. Bet šīs darbības varat izmantot jebkurā publiskā HTML lapā.

Pirmais datu nokasīšanas solis ir visas lapas HTML sagrābšana, izmantojot jQuery .getpieprasījumu.

var name = "codemzy";$.get('//www.freecodecamp.com/' + name, function(response) { console.log(response);});

Lieliski, viss lapas avota kods tikko pieteicās konsolē.

Piezīme. Ja šajā posmā tiek parādīta kļūda pēc No ‘Access-Control-Allow-Origin’ header is present on the requested resourcenesatraucies. Ritiniet uz leju līdz šīs ziņas sadaļai Neļaujiet CORS pārtraukt jūs .

Tas bija viegli. Izmantojot JavaScript un jQuery, iepriekš minētais kods pieprasa lapu no www.freecodecamp.org, kā to darītu pārlūks. Un freeCodeCamp atbild ar lapu. Tā vietā, lai pārlūks palaistu kodu, lai parādītu lapu, mēs iegūstam HTML kodu.

Un tas ir tas, kas ir tīmekļa nokasīšana, iegūstot datus no vietnēm.

Labi, atbilde nav gluži tik glīta kā dati, kurus mēs atgūstam no API.

Bet ... mums ir dati, kaut kur tur.

Kad esam ieguvuši nepieciešamo informāciju, avota kods mums ir jāķer tikai pie mums vajadzīgajiem datiem!

Mēs varam meklēt, izmantojot atbildi, lai atrastu nepieciešamos elementus.

Pieņemsim, ka mēs vēlamies uzzināt, cik daudz izaicinājumu lietotājs ir veicis, ņemot vērā atbildi uz lietotāja profilu.

Rakstīšanas laikā kempera izpildītie izaicinājumi ir sakārtoti tabulās lietotāja profilā. Tātad, lai sasniegtu kopējo izaicinājumu skaitu, mēs varam saskaitīt rindu skaitu.

Viens veids ir ietvert visu atbildi jQuery objektā, lai mēs varētu izmantot jQuery metodes, piemēram, .find()lai iegūtu datus.

// number of challenges completedvar challenges = $(response).find('tbody tr').length;

Tas darbojas lieliski - mēs iegūstam pareizo rezultātu. Bet tas nav labs veids, kā iegūt rezultātu, pēc kura mēs vēlamies. Pārvēršot atbildi jQuery objektā, faktiski tiek ielādēta visa lapa, ieskaitot visus šīs lapas ārējos skriptus, fontus un stila lapas ... Ak, oh!

Mums ir nepieciešami daži datu biti. Mums patiešām nav nepieciešama lapas ielāde, un noteikti ne visi ar to saistītie ārējie resursi.

Mēs varētu noņemt skripta tagus un pēc tam palaist pārējo atbildi caur jQuery. Lai to izdarītu, mēs varētu izmantot Regex, lai meklētu skriptu modeļus tekstā un tos noņemtu.

Vai vēl labāk, kāpēc neizmantot Regex, lai vispirms atrastu to, ko meklējam?

// number of challenges completedvar challenges = response.replace(/[\s|\S]*?/g).match(//g).length;

Un tas darbojas! Izmantojot iepriekš minēto Regex kodu, mēs izvelkam tabulas galviņu rindas (kurās nebija nekādu izaicinājumu), un pēc tam sakārtojam visas tabulas rindas, lai skaitītu pabeigto izaicinājumu skaitu.

Tas ir vēl vieglāk, ja vēlamie dati ir tikai atbildē vienkāršā tekstā. Rakstīšanas laikā lietotāju punkti bija līdzīgi html

[ 1498 ]

tikai gaida, kad tiks nokasīts.

var points = response.match(/

\[ ([\d]*?) \]/)[1];

Iepriekš minētajā Regex modelī mēs saskaņojam meklēto h1 elementu, ieskaitot to, [ ]kas ieskauj punktus, un grupējam jebkuru skaitli iekšpusē ar ([\d]*?).Mēs iegūstam masīvu atpakaļ, pirmais [0]elements ir visa spēle un otrais [1]ir mūsu grupas mačs (mūsu punkti ).

Regex ir noderīgs visu veidu modeļu saskaņošanai virknēs, un tas ir lieliski piemērots meklēšanai, izmantojot mūsu atbildi, lai iegūtu nepieciešamos datus.

You can use the same 3 step process to scrape profile data from a variety of websites:

  1. Use client-side JavaScript
  2. Use jQuery to scrape the data
  3. Use Regex to filter the data for the relevant information

Until I hit a problem, CORS.

Don’t Let CORS Stop You!

CORS or Cross-Origin Resource Sharing, can be a real problem with client-side web scraping.

For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. And because we are using client-side Javascript on the front end for web scraping, CORS errors can occur.

Here’s an example trying to scrape profile data from CodeWars…

var name = "codemzy";$.get('//www.codewars.com/users/' + name, function(response) { console.log(response);});

At the time of writing, running the above code gives you a CORS related error.

If there is noAccess-Control-Allow-Origin header from the place you’re scraping, you can run into problems.

Sliktā ziņa ir tā, ka, lai apietu šo problēmu, jums ir jāizpilda šāda veida pieprasījumi servera pusē.

Whaaaaaaaat, tas it kā ir klienta puses tīmekļa nokasīšana ?!

Labās ziņas ir tādas, ka, pateicoties daudziem citiem brīnišķīgiem izstrādātājiem, kuri saskārušies ar vieniem un tiem pašiem jautājumiem, jums pašiem nav jāpieskaras aizmugurējai daļai.

Stingri ievērojot mūsu priekšējā skripta robežas, mēs varam izmantot starpdomēnu rīkus, piemēram, Any Origin, Whatever Origin, All Origins, crossorigin un, iespējams, daudz ko citu. Es atklāju, ka jums bieži ir jāpārbauda daži no šiem, lai atrastu to, kas darbosies vietnē, kuru mēģināt nokasīt.

Atgriežoties pie mūsu CodeWars piemēra, mēs varam nosūtīt pieprasījumu, izmantojot starpdomēnu rīku, lai apietu CORS problēmu.

var name = "codemzy";var url = "//anyorigin.com/go?url=" + encodeURIComponent("//www.codewars.com/users/") + name + "&callback=?";$.get(url, function(response) { console.log(response);});

Un tāpat kā maģija, mums ir sava atbilde.