Ștergerea ecranului cu Node.js

Este posibil să fi folosit NodeJS ca server web, dar ați știut că îl puteți utiliza și pentru răzuirea web? În acest tutorial, vom examina modul în care puteți să răsturnați pagini web statice - și acele pagube cu conținut dinamic - cu ajutorul NodeJS și câteva module NPM utile.



Un pic despre scraping Web

Înlăturarea paginilor web a avut întotdeauna o conotație negativă în lumea dezvoltării web - și pentru un motiv bun. În dezvoltarea modernă, API-urile sunt prezente pentru cele mai populare servicii și ar trebui să fie folosite pentru a prelua date mai degrabă decât pentru a le șterge. Problema inerentă cu răzuirea este aceea că se bazează pe structura vizuală a paginii răzuite. Ori de câte ori modificările HTML se modifică - indiferent de cât de mică ar putea fi schimbarea - aceasta vă poate sparge complet codul.

În ciuda acestor deficiențe, este important să învățăm un pic despre răzuirea web și despre unele dintre instrumentele disponibile pentru a ajuta la această sarcină. Atunci când un site nu dezvăluie un API sau un feed de sindicalizare (RSS / Atom, etc), singura opțiune pe care o avem pentru a obține acel conținut ... este răzuirea.

Notă: Dacă nu puteți obține informațiile pe care le solicitați printr-un API sau un feed, este un semn bun că proprietarul nu dorește ca aceste informații să fie accesibile. Cu toate acestea, există excepții.


De ce să folosiți NodeJS?

Răzuitoarele pot fi scrise în orice limbă, într-adevăr. Motivul pentru care îmi place să folosesc nodul este din cauza naturii sale asincrone, ceea ce înseamnă că codul meu nu este blocat în nici un moment al procesului. Sunt destul de familiarizat cu JavaScript, deci este un bonus suplimentar. În cele din urmă, există câteva module noi care au fost scrise pentru NodeJS, care facilitează ștergerea site-urilor într-o manieră sigură (bine, la fel de fiabile ca și răzuirea!). Să începem!


Simplu răzuire cu YQL

Să începem cu cazul simplu de utilizare: pagini web statice. Acestea sunt paginile dvs. standard de tip "run-of-the-mill". Pentru acestea, Yahoo! Query Language (YQL) ar trebui să facă treaba foarte bine. Pentru cei care nu sunt familiarizați cu YQL, este o sintaxă asemănătoare SQL care poate fi folosită pentru a lucra cu API-uri diferite într-o manieră consecventă.

YQL are câteva tabele excelente pentru a ajuta dezvoltatorii să obțină HTML de pe o pagină. Cele pe care vreau să le evidențiez sunt:

  • html
  • data.html.cssselect
  • htmlstring

Să trecem prin fiecare dintre ele și să analizăm cum să le implementăm în NodeJS.

html masa

html tabel este modul cel mai de bază de a șterge HTML-ul dintr-o adresă URL. O interogare obișnuită utilizând acest tabel arată astfel:

selectați * din html unde url = "http://finance.yahoo.com/q?s=yhoo" și xpath = "// div [@ id =" yfi_headlines "] / div [2] / ul / li / a "

Această interogare constă în doi parametri: "url" și "xpath". Adresa URL este auto-explicativă. XPath constă dintr-un șir XPath care spune YQL ce secțiune a HTML-ului ar trebui returnată. Încercați această interogare aici.

Parametrii suplimentari pe care îi puteți utiliza includ browser- (Boolean), charset (șir) și compat (şir). Nu am fost nevoiți să folosesc acești parametri, ci să vă referiți la documentație dacă aveți nevoi specifice.

Nu este confortabil cu XPath?

Din păcate, XPath nu este un mod foarte popular de a traversa structura arborelui HTML. Poate fi complicat citirea și scrierea pentru începători.

Să ne uităm la tabelul următor, care face același lucru, dar vă permite să utilizați în schimb CSS

data.html.cssselect masa

data.html.cssselect Tabelul este modul meu preferat de a scoate HTML-ul dintr-o pagină. Funcționează în același mod ca și html dar vă permite să utilizați CSS în loc de XPath. În practică, acest tabel convertește CSS în XPath sub capotă și apoi îl apelează html tabel, deci este puțin mai lent. Diferența ar trebui să fie neglijabilă pentru nevoile de răzuire.

O interogare obișnuită care utilizează acest tabel arată astfel:

selectați * din date.html.cssselect unde url = "www.yahoo.com" și css = "# news a"

După cum puteți vedea, este mult mai curat. Vă recomandăm să încercați mai întâi această metodă atunci când încercați să ștergeți codul HTML folosind YQL. Încercați această interogare aici.

htmlstring masa

htmlstring tabelul este util pentru cazurile în care încercați să răsturnați o bucată mare de text formatat dintr-o pagină web.

Utilizarea acestui tabel vă permite să preluați întregul conținut HTML al acelei pagini într-un singur șir, mai degrabă decât ca JSON care este împărțit pe baza structurii DOM.

De exemplu, un răspuns JSON obișnuit care scarpină un mesaj eticheta arată astfel:

"rezultate": "a": "href": "...", "target": "_blank", "content": "Chief Executive Apple Cook To Climb pe o nouă scenă"

Vedeți cum sunt definite atributele ca proprietăți? În schimb, răspunsul din partea htmlstring tabel ar arata astfel:

"rezultate": "rezultat": "directorul executiv al Apple Cook să urce pe o nouă scenă

Deci, de ce ai folosi asta? Ei bine, din experiența mea, acest lucru este foarte util atunci când încercați să răsturnați o mare cantitate de text formatat. De exemplu, luați în considerare următorul fragment:

Lorem ipsum dolor sta amet, consectetur adipiscing elit.

Proin nec diam magna. Sediu non lorem un nisi portitor pharetra et non arcu.

Prin utilizarea funcției htmlstring tabel, puteți obține acest HTML ca un șir și utilizați regex pentru a elimina etichetele HTML, care vă lasă doar cu textul. Aceasta este o sarcină mai ușoară decât iterarea prin JSON care a fost împărțită în proprietăți și obiecte copil bazate pe structura DOM a paginii.


Folosind YQL cu NodeJS

Acum, când știm câte ceva despre unele dintre mesele disponibile în YQL, să implementăm o rachetă web folosind YQL și NodeJS. Din fericire, acest lucru este foarte simplu, datorită nod-YQL modul de către Derek Gathright.

Putem instala modulul folosind NPM:

npm install yql

Modulul este extrem de simplu, constând dintr - o singură metodă: YQL.exec () metodă. Se definește după cum urmează:

funcția exec (șir de interogare [, callback funcție] [, paramule de obiect] [, obiect httpOptions])

Putem să o folosim cerând-o și sunând YQL.exec (). De exemplu, să presupunem că dorim să răsturnăm titlurile din toate postările de pe pagina principală Nettuts:

var YQL = necesită ("yql"); nou YQL.exec ('select * din data.html.cssselect unde url = "http://net.tutsplus.com/" și css = ". post_title a"', funcția (răspunsul) // răspunsul constă din JSON pe care îl puteți parsa);

Lucrul minunat despre YQL este capacitatea sa de a testa interogările dvs. și de a determina ce JSON primiți înapoi în timp real. Accesați consola pentru a încerca această interogare sau faceți clic aici pentru a vedea JSON-ul brut.

params și httpOptions obiectele sunt opționale. Parametrii pot conține proprietăți precum env (indiferent dacă utilizați un mediu specific pentru mese) și format (xml sau json). Toate proprietățile au trecut params sunt codate URI și atașate la șirul de interogare. httpOptions obiect este trecut în antetul cererii. Aici puteți specifica dacă doriți să activați SSL, de exemplu.

Fișierul JavaScript, numit yqlServer.js, conține codul minim necesar pentru răzuirea folosind YQL. Puteți rula prin emiterea următoarei comenzi în terminalul dvs.:

nodul yqlServer.js

Excepții și alte instrumente notabile

YQL este alegerea mea preferată de a scoate conținutul din paginile web statice, deoarece este ușor de citit și ușor de utilizat. Cu toate acestea, YQL va eșua dacă pagina web are o a robots.txt fișier care neagă un răspuns la acesta. În acest caz, puteți să consultați unele dintre utilitățile menționate mai jos sau să utilizați PhantomJS, pe care o vom acoperi în secțiunea următoare.

Node.io este un utilitar Util util care este special conceput pentru răzuirea datelor. Aveți posibilitatea să creați locuri de muncă care să ia intrare, să o proceseze și să returneze o anumită ieșire. Node.io este bine urmărit pe Github și are câteva exemple utile pentru a începe.

JSDOM este un proiect foarte popular care implementează DOM-ul W3C în JavaScript. Când este furnizat codul HTML, acesta poate construi un DOM cu care puteți interacționa. Consultați documentația pentru a vedea cum puteți utiliza împreună JSDOM și orice bibliotecă JS (cum ar fi jQuery) pentru a elimina datele de pe paginile web.


Ștergerea paginilor cu conținut dinamic

Până în prezent, am analizat câteva instrumente care ne pot ajuta să răsturnăm paginile web cu conținut static. Cu YQL, este relativ ușor. Din păcate, ne sunt adesea prezentate pagini cu conținut încărcat dinamic cu JavaScript. În aceste cazuri, pagina este adesea goală inițial, iar apoi conținutul este adăugat ulterior. Cum putem face acest lucru?

Un exemplu

Permiteți-mi să vă dau un exemplu despre ceea ce vreau să spun; Am încărcat un fișier HTML simplu pe propriul site web, care adaugă un anumit conținut, prin JavaScript, la două secunde după document.ready () se numește funcția. Puteți să verificați pagina aici. Iată ce arată sursa:

   Pagina de testare cu conținut adăugat după încărcarea paginii   Conținutul de pe această pagină este atașat DOM după încărcarea paginii. 

Acum, să încercăm să ștergem textul înăuntru

folosind YQL.

var YQL = necesită ("yql"); noul YQL.exec ('select * din data.html.cssselect unde url = "http://tilomitra.com/repository/screenscrape/ajax.html" și css = "# content"', funcția (răspunsul) // Acest lucru se va întoarce undefined! Rezolvarea a fost nereușită console.log (response.results);));

Veți observa că YQL revine nedefinit deoarece, atunci când pagina este încărcată,

este gol. Conținutul nu a fost încă adăugat. Puteți încerca să interogați aici aici.

Să ne uităm la modul în care putem aborda această problemă!

Introduceți PhantomJS

PhantomJS poate încărca pagini web și poate imita un browser bazat pe Webkit fără GUI.

Metoda preferată de răzuire a informațiilor din aceste site-uri este de a utiliza PhantomJS. PhantomJS se descrie ca un "Webkit fără cap" cu un API JavaScript.În termeni simpli, aceasta înseamnă că PhantomJS poate încărca pagini web și poate imita un browser bazat pe Webkit fără GUI.În calitate de dezvoltator, putem apela la metode specifice pe care le oferă PhantomJS executați codul pe pagină. Deoarece se comportă ca un browser, scripturile de pe pagina Web se execută așa cum ar fi într-un browser obișnuit.

Pentru a obține date de pe pagina noastră, vom folosi PhantomJS-Node, un mic proiect cu o sursă deschisă care leagă PhantomJS cu NodeJS. Sub capota, acest modul rulează PhantomJS ca proces copil.

Instalarea PhantomJS

Înainte de a putea instala modulul PhantomJS-Node NPM, trebuie să instalați PhantomJS. Instalarea și construirea PhantomJS poate fi puțin complicată.

În primul rând, mergeți la PhantomJS.org și descărcați versiunea corespunzătoare pentru sistemul dvs. de operare. În cazul meu, a fost Mac OSX.

După descărcare, dezarhivați-l undeva, cum ar fi / Aplicații /. Apoi, doriți să o adăugați la dvs. CALE:

sudo ln -s /Aplicații/phantomjs-1.5.0/bin/phantomjs / usr / local / bin /

A inlocui 1.5.0 cu versiunea descărcată a PhantomJS. Fiți informat că nu vor avea toate sistemele / Usr / local / bin /. Unele sisteme vor avea: / Usr / bin /, /cos/, sau usr / X11 / bin in schimb.

Pentru utilizatorii Windows, consultați tutorialul scurt aici. Veți ști că sunteți pregătiți când deschideți Terminalul și scrieți phantomjs, și nu veți primi erori.

Dacă sunteți inconfortabil de editare dvs. CALE, faceți o notă de unde ați dezarhivat PhantomJS și voi arăta o altă modalitate de ao seta în secțiunea următoare, deși vă recomandăm să vă editați CALE.

Instalarea nodului PhantomJS

Setarea PhantomJS-Node este mult mai ușoară. Cu condiția să aveți instalat NodeJS, puteți instala prin npm:

npm instalează phantom

Dacă nu ți-ai editat-o CALE în etapa anterioară când instalați PhantomJS, puteți intra în fantomă/ director tras în jos de npm și editați această linie în phantom.js.

ps = child.spawn ("phantomjs", args.concat ([__ dirname + '/shim.js', port]));

Schimbați calea către:

ps = child.spawn ('/ cale / către / phantomjs-1.5.0 / bin / phantomjs', args.concat ([__ dirname + '/shim.js', port]));

Odată ce ați terminat, puteți să-l testați executând acest cod:

 var phantom = necesită ("phantom"); phantom.create (funcția (ph) return ph.createPage (funcția (pagina) return pagina.open ("http://www.google.com", funcția (status) console.log ()), funcția (rezultat) console.log ('Titlul paginii este' + rezultat '); returnați ph.exit ();); );););

Făcând acest lucru pe linia de comandă ar trebui să aducă următoarele:

a deschis Google? succes Titlul paginii este Google

Dacă ai asta, ești pregătit și pregătit să pleci. Dacă nu, postați un comentariu și voi încerca să vă ajut!

Folosind nodul PhantomJS

Pentru a vă ușura, am inclus un fișier JS, numit phantomServer.js în descărcarea care utilizează unele dintre API-ul PhantomJS pentru a încărca o pagină Web. Se așteaptă timp de 5 secunde înainte de a executa JavaScript care scarpineste pagina. Puteți să o rulați navigând la director și eliberând următoarea comandă în terminalul dvs.:

 nod phantomServer.js

Voi oferi o imagine de ansamblu asupra modului în care funcționează aici. În primul rând, avem nevoie de PhantomJS:

 var phantom = necesită ("phantom");

Apoi implementăm câteva metode din API. Anume, vom crea o instanță de pagină și apoi vom apela deschis() metodă:

 phantom.create (funcția (ph) return ph.createPage (funcția (pagina) // De aici încolo, putem folosi metodele API ale PhantomJS return page.open ("http://tilomitra.com/repository/screenscrape /ajax.html ", funcția (status) // Pagina este acum deschisă console.log (" site deschis? ", status);))););

Odată ce pagina este deschisă, putem injecta niște JavaScript în pagină. Să injectăm jQuery prin page.injectJs () metodă:

 phantom.create (funcția (ph) return ph.createPage (funcția (pagina) return pagina.open ("http://tilomitra.com/repository/screenscrape/ajax.html", funcția (status) console.log ("site deschis?", status); page.injectJs ('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function () // jQuery Loaded // Putem folosi lucruri precum $ ("body"). Html () aici.););););

jQuery este încărcat acum, dar nu știm dacă conținutul dinamic din pagină a fost încărcat încă. Pentru a ține cont de acest lucru, de obicei, îmi pun codul de răzuire în interiorul lui setTimeout () funcția care se execută după un anumit interval de timp. Dacă doriți o soluție mai dinamică, API-ul PhantomJS vă permite să ascultați și să emulați anumite evenimente. Să mergem cu cazul simplu:

 setTimeout (function () return page.evaluate (function () // Obtineti ceea ce doriti din pagina folosind jQuery. // O modalitate buna este de a popula un obiect cu toate comenzile jQuery de care aveti nevoie si apoi sa returnati obiectul (h2), var h2Arr = [], // array care păstrează toate html pentru elementele h2 pArr = []; // array care păstrează toate html pentru elementele p // Populați cele două array $ ('h2'). h2Arr.push ($ (this) .html ());)); $ ('p') fiecare (funcția () pArr.push ($ (this) .html ());); Returnați această retur de date h2: h2Arr, p: pArr, funcția (rezultatul) console.log (rezultat); // Deconectați datele ph.exit (););, 5000);

Punându-le pe toate, pe noi phantomServer.js fișierul arată astfel:

 var phantom = necesită ("phantom"); phantom.create (funcția (ph) return ph.createPage (funcția (pagina) return pagina.open ("http://tilomitra.com/repository/screenscrape/ajax.html", funcția (status) console.log ("site deschis?", status); page.injectJs ('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function () // jQuery Loaded () () Retur pagina.evaluate (function () // Obtineti ceea ce doriti din pagina folosind jQuery O metodă bună este să populați un obiect cu toate comenzile jQuery de care aveți nevoie și apoi să returnați obiectul var h2Arr = [], pArr = []; $ ('h2') fiecare (funcția () h2Arr.push ($ (this) .html ());)); $ ('p') fiecare (function () pArr.push ($ (this) p: pArr;, funcția (rezultatul) console.log (rezultat); ph.exit (););, 5000);););););

Această implementare este puțin brută și dezorganizată, dar face acest lucru. Folosind PhantomJS, suntem capabili să răsturnăm o pagină care are conținut dinamic! Consolă dvs. ar trebui să emită următoarele:

 → nodul phantomServer.js a deschis site-ul? succesul h2: ["articolul 1", "articolul 2", "articolul 3"], pct. "[lorem ipsum dolor sit amet, consectetur adipiscing elit", "Ut sed nulla turpis, in faucibus ante. Vivamus ut malesuada est. Curabitur vel enim eget purus pharetra tempor id in tellus. ',' Curabitur euismod hendrerit quam ut euismod. Ut leo sem, viverra nec gravida nec, tristique nec arcu. " ]

Concluzie

În acest tutorial, am revizuit două modalități diferite de a efectua răsturnarea web. În cazul răsturnării de pe o pagină web statică, putem profita de YQL, care este ușor de configurat și utilizat. Pe de altă parte, pentru site-urile dinamice, putem folosi PhantomJS. Este ceva mai greu de configurat, dar oferă mai multe capabilități. Rețineți: puteți utiliza PhantomJS și pentru site-uri statice!

Dacă aveți întrebări pe această temă, nu ezitați să întrebați mai jos și voi face tot posibilul pentru a vă ajuta.