Kirjoittaja valitsiIlmainen ja avoimen lähdekoodin rahastovastaanottaa lahjoituksen osanaKirjoita lahjoituksia vartenohjelmoida.
Johdanto
Web-kaappaus on prosessi, jolla automatisoidaan tiedonkeruu verkosta. Prosessi käyttää tyypillisesti "indeksointirobottia", joka surffaa automaattisesti verkossa ja kerää tietoja valituilta sivuilta. On monia syitä, miksi saatat haluta kaapata tietoja. Ensisijaisesti se nopeuttaa tiedonkeruuta huomattavasti eliminoimalla manuaalisen tiedonkeruun. Kaapiminen on ratkaisu myös silloin, kun tiedonkeruuta halutaan tai tarvitaan, mutta sivusto ei tarjoa APIa.
Tässä opetusohjelmassa rakennat verkkokaappaussovelluksen käyttämälläNode.jsjaNukkenäyttelijä. Sovelluksesi monimutkaisuus kasvaa edistyessäsi. Ensin koodaat sovelluksesi avautuvaksiKromija lataa erityinen verkkosivusto, joka on suunniteltu verkkoa kaapivaksi hiekkalaatikoksi:books.toscrape.com. Kahdessa seuraavassa vaiheessa kaikki kirjat kaavitaan yhdelle books.toscrape-sivulle ja sitten kaikki kirjat useille sivuille. Muissa vaiheissa suodatat kaavinta kirjaluokan mukaan ja tallennat sitten tietosi JSON-tiedostona.
Varoitus:Verkkokaappauksen etiikka ja laillisuus ovat erittäin monimutkaisia ja kehittyvät jatkuvasti. Ne vaihtelevat myös sijaintisi, tietojen sijainnin ja kyseessä olevan verkkosivuston mukaan. Tämä opetusohjelma kaappaa erityisen verkkosivuston,books.toscrape.com, joka on erityisesti suunniteltu kaavinsovellusten testaamiseen.Minkä tahansa muun verkkotunnuksen kaapiminen ei kuulu tämän opetusohjelman piiriin.
Edellytykset
- Node.js asennettuna kehityskoneellesi. Tämä opetusohjelma on testattu Node.js-versiolla 12.18.3 ja npm-versiolla 6.14.6.Voit noudattaa tätä opasta asentaaksesi Node.js:n macOS- tai Ubuntu 18.04:ään, tai voitseuraa tätä opasta asentaaksesi Node.js Ubuntu 18.04:ään PPA:n avulla.
Vaihe 1 – Web Scraperin määrittäminen
Kun Node.js on asennettu, voit aloittaa verkkokaavin asennuksen. Ensin luot projektin juurihakemiston ja asennat sitten tarvittavat riippuvuudet. Tämä opetusohjelma vaatii vain yhden riippuvuuden, ja asennat sen käyttämällä Node.js:n oletuspakettien hallintaanpm. npm tulee esiasennettuna Node.js:n kanssa, joten sinun ei tarvitse asentaa sitä.
Luo kansio tälle projektille ja siirry sitten sisään:
- mkdirkirjakaavin
- CDkirjakaavin
Suoritat kaikki seuraavat komennot tästä hakemistosta.
Meidän on asennettava yksi paketti npm:n tai solmun pakettien hallinnan avulla. Alusta ensin npm, jotta voit luoda apackages.json
tiedosto, joka hallitsee projektisi riippuvuuksia ja metatietoja.
Alusta npm projektillesi:
- npmsen sisällä
npm esittää kehotteiden sarjan. Voit painaaTULLA SISÄÄN
jokaiseen kehotteeseen tai voit lisätä mukautettuja kuvauksia. Muista painaaTULLA SISÄÄN
ja jätä oletusarvot paikoilleen pyydettäessäsisääntulopiste:
jatesti komento:
. Vaihtoehtoisesti voit ohittaay
liputtaanpm
—npm init -y
– ja se lähettää kaikki oletusarvot puolestasi.
Tulostuksesi näyttää suunnilleen tältä:
Lähtö
{ "nimi": "sammy_scraper", "versio": "1.0.0", "kuvaus": "verkkokaavin", "main": "index.js", "skriptit": { "testi": "echo \"Virhe: testiä ei määritetty\" && exit 1" }, "keywords": [], "author": "sammy hai", "lisenssi": "ISC"}Onko tämä ok? (kyllä kyllä
TyyppiJoo
ja painaTULLA SISÄÄN
. npm tallentaa tämän tulosteen sinunpackage.json
tiedosto.
Käytä nyt npm:ää Puppeteerin asentamiseen:
- npm Asentaa --Tallentaanukkenäyttelijä
Tämä komento asentaa sekä Puppeteerin että Chromiumin version, jonka Puppeteer-tiimi tietää toimivan niiden API:n kanssa.
Linux-koneissa Puppeteer saattaa vaatia joitain lisäriippuvuuksia.
Jos käytät Ubuntu 18.04:ää,tarkista Puppeteerin vianmääritysdokumenttien Debian-riippuvuudet-valikko kohdasta "Chrome headless ei käynnisty UNIXissa". Voit käyttää seuraavaa komentoa puuttuvien riippuvuuksien löytämiseen:
- ldd kromi| grepei
Kun npm, Puppeteer ja kaikki muut riippuvuudet on asennettu, sinunpackage.json
tiedosto vaatii viimeisen konfiguroinnin ennen koodauksen aloittamista. Tässä opetusohjelmassa käynnistät sovelluksesi komentoriviltänpm ajon aloitus
. Sinun on lisättävä tietoja tästäalkaa
käsikirjoittaapackage.json
. Erityisesti sinun on lisättävä yksi rivi -kohdan allekäsikirjoituksia
ohje koskien sinuaalkaa
komento.
Avaa tiedosto haluamassasi tekstieditorissa:
- nanopackage.json
Etsikäsikirjoitukset:
-osio ja lisää seuraavat kokoonpanot. Muista laittaa pilkku merkin loppuuntestata
komentosarja, tai tiedostosi ei jäsenny oikein.
Lähtö
{ . . . "scripts": { "test": "echo \"Virhe: testiä ei määritetty\" && poistu 1","start": "node index.js"}, . . . "riippuvuudet": { "nukkenäyttelijä": "^5.2.1" }}
Huomaat myös sennukkenäyttelijä
näkyy nyt allariippuvuuksia
lähellä tiedoston loppua. Sinunpackage.json
tiedosto ei vaadi enempää muutoksia. Tallenna muutokset ja sulje editori.
Olet nyt valmis aloittamaan kaavin koodauksen. Seuraavassa vaiheessa määrität selainesiintymän ja testaat kaavin perustoiminnallisuutta.
Vaihe 2 – Selainesiintymän määrittäminen
Kun avaat perinteisen selaimen, voit esimerkiksi napsauttaa painikkeita, navigoida hiirellä, kirjoittaa, avata kehitystyökaluja ja paljon muuta. Chromiumin kaltaisella päättömällä selaimella voit tehdä nämä samat asiat, mutta ohjelmallisesti ja ilman käyttöliittymää. Tässä vaiheessa määrität kaavin selainesiintymän. Kun käynnistät sovelluksesi, se avaa automaattisesti Chromiumin ja siirtyy kohteeseenbooks.toscrape.com. Nämä ensimmäiset toimet muodostavat ohjelmasi perustan.
Verkkokaavin tarvitsee neljä.js
tiedostot:browser.js
,indeksi, js
,pageController.js
, japageScraper.js
. Tässä vaiheessa luot kaikki neljä tiedostoa ja päivität niitä sitten jatkuvasti, kun ohjelmasi kehittyy. Aloitabrowser.js
; tämä tiedosto sisältää komentosarjan, joka käynnistää selaimesi.
Luo ja avaa projektisi juurihakemistostabrowser.js
tekstieditorissa:
- nanobrowser.js
Ensinnäkin teetvaatia
Nukketeatteri ja luo sittenasynk
kutsuttu toimintostartBrowser()
. Tämä toiminto käynnistää selaimen ja palauttaa sen esiintymän. Lisää seuraava koodi:
./book-scraper/browser.js
konstnukkenäyttelijä= vaatia("nukkenäyttelijä");asynk toiminto startBrowser(){antaaselain;yrittää {konsoli.Hirsi("Avaa selain......");selain= odottaanukkenäyttelijä.tuoda markkinoille({ päätön: väärä, args: ["--disable-setuid-sandbox"], 'ignoreHTTPSErrors': totta });} ottaa kiinni (err) {konsoli.Hirsi("Selaininstanssia ei voitu luoda => :",err);}palataselain;}moduuli.vientiä= {startBrowser};
Nukketeatterilla on a.tuoda markkinoille()
menetelmäjoka käynnistää selaimen esiintymän. Tämä menetelmä palauttaa aLupaus, joten sinun täytyyvarmista, että lupaus ratkeaa käyttämällä a.sitten
taiodottaa
lohko.
Käytätodottaa
varmistaaksesi, että lupaus ratkeaa, käärimällä tämän tapauksen ympärilleayritä saada kiinni
koodilohkoja palauttaa sitten selaimen esiintymän.
Huomaa, että.tuoda markkinoille()
menetelmä ottaa JSON-parametrin, jolla on useita arvoja:
- päätön-
väärä
tarkoittaa, että selain toimii käyttöliittymän kanssa, jotta voit katsella skriptin suorittamista samallatotta
tarkoittaa, että selain toimii päättömässä tilassa. Huomaa kuitenkin, että jos haluat ottaa kaavin käyttöön pilvessä, määritäpäätön
takaisintotta
. Useimmat virtuaalikoneet ovat päättömiä eivätkä sisällä käyttöliittymää, joten ne voivat käyttää selainta vain päättömässä tilassa. Nukketeatteri sisältää myös apäättäväinen
-tilassa, mutta sitä tulisi käyttää vain testaustarkoituksiin. - ohita HTTPSEvirheet-
totta
Voit vierailla verkkosivustoilla, joita ei isännöidä suojatun HTTPS-protokollan kautta, ja jättää huomioimatta kaikki HTTPS-virheet.
Tallenna ja sulje tiedosto.
Luo nyt toinen.js
tiedosto,index.js
:
- nanoindex.js
Tässä tuletvaatia
browser.js
japageController.js
. Soitat sittenstartBrowser()
toiminto ja välitä luotu selainesiintymä sivun ohjaimelle, joka ohjaa sen toimia. Lisää seuraava koodi:
./book-scraper/index.js
konstselainobjekti= vaatia('./selain');konstscraperController= vaatia('./pageController');//Käynnistä selain ja luo selainesiintymäantaaselainInstance=selainobjekti.startBrowser();// Välitä selaimen ilmentymä kaavinohjaimellescraperController(selainInstance)
Tallenna ja sulje tiedosto.
Luo kolmas.js
tiedosto,pageController.js
:
- nanopageController.js
pageController.js
hallitsee kaavintaprosessiasi. Se käyttää selaimen ilmentymää hallitsemaanpageScraper.js
tiedosto, jossa kaikki kaavintavat komentosarjat suoritetaan. Lopulta käytät sitä määrittämään, minkä kirjaluokan haluat kaapia. Toistaiseksi haluat kuitenkin vain varmistaa, että voit avata Chromiumin ja navigoida verkkosivulle:
./book-scraper/pageController.js
konstsivukaavin= vaatia('./pageScraper');asynk toiminto scrapeAll(selainInstance){antaaselain;yrittää{selain= odottaaselainInstance;odottaasivukaavin.kaavin(selain);}ottaa kiinni(err){konsoli.Hirsi("Selaininstanssia ei voitu ratkaista =>",err);}}moduuli.vientiä = (selainInstance) => scrapeAll(selainInstance)
Tämä koodi vie funktion, joka ottaa selaimen ilmentymän ja välittää sen funktiolle, jota kutsutaanscrapeAll()
. Tämä toiminto puolestaan välittää tämän ilmentymänpageScraper.scraper()
argumenttina, joka käyttää sitä sivujen kaappaamiseen.
Tallenna ja sulje tiedosto.
Lopuksi luo viimeinen.js
tiedosto,pageScraper.js
:
- nanopageScraper.js
Täällä luot objektin kirjaimella aurl
omaisuus ja akaavin()
menetelmä. Theurl
on sen verkkosivun URL-osoite, jonka haluat kaapata, kun taaskaavin()
menetelmä sisältää koodin, joka suorittaa varsinaisen kaavin, vaikka tässä vaiheessa se vain navigoi URL-osoitteeseen. Lisää seuraava koodi:
./book-scraper/pageScraper.js
konstscraperObject= {url: "http://books.toscrape.com",asynk kaavin(selain){antaasivu= odottaaselain.uusi sivu();konsoli.Hirsi(`Navigoidaan kohteeseen${Tämä.url}...`);odottaasivu.mene(Tämä.url);}}moduuli.vientiä=scraperObject;
Nukketeatterilla on auusi sivu()
menetelmäjoka luo uuden sivun ilmentymän selaimeen, ja nämä sivuesiintymät voivat tehdä melko monia asioita. Meidänkaavin()
-menetelmällä, loit sivuesiintymän ja käytit sittenpage.goto()
menetelmänavigoidaksesi kohteeseenbooks.toscrape.com-kotisivulla.
Tallenna ja sulje tiedosto.
Ohjelmasi tiedostorakenne on nyt valmis. Projektisi hakemistopuun ensimmäinen taso näyttää tältä:
Lähtö
.├── browser.js├── index.js├── node_modules├── package-lock.json├── package.json├── pageController.js└── pageScraper.
Suorita nyt komentonpm ajon aloitus
ja katso kaavinsovelluksesi suorittavan:
- npmjuoksun aloitus
Se avaa automaattisesti Chromium-selainesiintymän, avaa uuden sivun selaimessa ja siirtyy kohtaanbooks.toscrape.com.
Tässä vaiheessa loit Puppeteer-sovelluksen, joka avasi Chromiumin ja latasi näennäisen verkkokirjakaupan -books.toscrape.com -kotisivun. Seuraavassa vaiheessa raaputat jokaisen etusivun kirjan tiedot.
Vaihe 3 – Tietojen kaapiminen yhdeltä sivulta
Ennen kuin lisäät toimintoja kaavinsovellukseesi, avaa haluamasi verkkoselain ja siirry manuaalisesti kohtaankirjoja kotisivuille. Selaa sivustoa ja saat käsityksen tietojen rakenteesta.
Vasemmalla on kategoriaosio ja oikealla kirjat. Kun napsautat kirjaa, selain siirtyy uuteen URL-osoitteeseen, joka näyttää oleelliset tiedot kyseisestä kirjasta.
Tässä vaiheessa kopioit tämän toiminnan, mutta koodilla; automatisoit verkkosivustolla liikkumisen ja sen tietojen kulutuksen.
Ensinnäkin, jos tarkastat kotisivun lähdekoodin selaimen Dev Tools -työkalujen avulla, huomaat, että sivulla luetellaan jokaisen kirjan tiedotosio
tag. Sisälläosio
tunniste jokainen kirja on alla alista
(li
) -tunnisteen, ja täältä löydät linkin kirjan omalle sivulle, hinnan ja saatavuuden varastossa.
Kaaviat näiden kirjojen URL-osoitteet, suodatat varastossa olevat kirjat, siirryt kullekin yksittäiselle kirjan sivulle ja keräät kirjan tiedot.
Avaa uudelleenpageScraper.js
tiedosto:
- nanopageScraper.js
Lisää seuraava korostettu sisältö. Pesät toisenodottaa
lohko sisälläodota page.goto(this.url);
:
./book-scraper/pageScraper.js
konstscraperObject= { url: "http://books.toscrape.com", asynk kaavin(selain){ antaasivu= odottaaselain.uusi sivu();konsoli.Hirsi(`Navigoidaan kohteeseen${Tämä.url}...`);// Navigoi valitulle sivulleodottaasivu.mene(Tämä.url);// Odota, että vaadittu DOM renderöidäänodottaasivu.odotaValitsijaa('.page_inner');// Hanki linkki kaikkiin tarvittaviin kirjoihinantaaURL-osoitteet= odottaasivu.$$eval('section ol > li', linkkejä => {// Varmista, että kaavittava kirja on varastossalinkkejä=linkkejä.suodattaa(linkki =>linkki.querySelector('.instock.availability > i').tekstisisältö!== "Varastossa")// Pura linkit tiedoistalinkkejä=linkkejä.kartta(hän =>hän.querySelector('h3 > a').href)palatalinkkejä;});konsoli.Hirsi(URL-osoitteet); }}moduuli.vientiä=scraperObject;
Tässä koodilohkossa soititthepage.waitForSelector()
menetelmä. Tämä odotti, että div, joka sisältää kaikki kirjaan liittyvät tiedot, renderöitiin DOM:ssa, ja sitten soititthesivu.$$eval()
menetelmä. Tämä menetelmä saa URL-elementin valitsimella§ ol li
(varmista, että palautat aina vain merkkijonon tai numeronsivu.$eval()
jasivu.$$eval()
menetelmät).
Jokaisella kirjalla on kaksi tilaa; kirja on jokoVarastossa
taiLoppu varastosta
. Haluat vain raapia kirjoja, jotka ovatVarastossa
. Koskasivu.$$eval()
palauttaa joukon kaikkia vastaavia elementtejä, olet suodattanut tämän taulukon varmistaaksesi, että työskentelet vain varastossa olevien kirjojen kanssa. Teit tämän etsimällä ja arvioimalla luokkaa.varastossa.saatavuus
. Sitten kartoitithref
kirjalinkkien omaisuutta ja palautti sen menetelmästä.
Tallenna ja sulje tiedosto.
Suorita sovelluksesi uudelleen:
- npmjuoksun aloitus
Selain avautuu, siirtyy verkkosivulle ja sulkeutuu, kun tehtävä on valmis. Tarkista nyt konsoli; se sisältää kaikki kopioidut URL-osoitteet:
Lähtö
> book-scraper@1.0.0 start/Users/sammy/book-scraper> node index.jsAvaa selain......Siirry osoitteeseen http://books.toscrape.com...[ 'http://books.toscrape.com/catalogue/a-light-in-the-attic_1000 /index.html", "http://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html", "http://books.toscrape.com/catalogue/soumission_998/index.html", 'http://books.toscrape.com/catalogue/sharp-objects_997/index.html', 'http://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html ', 'http://books.toscrape.com/catalogue/the-requiem-red_995/index.html', 'http://books.toscrape.com/catalogue/the-dirty-little-secrets-of-getting -your-dream-job_994/index.html", "http://books.toscrape.com/catalogue/the-coming-woman-a-novel-based-on-the-life-of-the-infamous-feminist -victoria-woodhull_993/index.html", "http://books.toscrape.com/catalogue/the-boys-in-the-boat-nine-americans-and-their-epic-quest-for-gold-at" -the-1936-berlin-olympics_992/index.html", "http://books.toscrape.com/catalogue/the-black-maria_991/index.html", "http://books.toscrape.com/catalogue" /starving-hearts-triangular-trade-trilogy-1_990/index.html", "http://books.toscrape.com/catalogue/shakespeares-sonnets_989/index.html", "http://books.toscrape.com" /catalogue/set-me-free_988/index.html", "http://books.toscrape.com/catalogue/scott-pilgrims-precious-little-life-scott-pilgrim-1_987/index.html", "http:// ://books.toscrape.com/catalogue/rip-it-up-and-start-again_986/index.html", "http://books.toscrape.com/catalogue/our-band-could-be-your -life-scenes-from-the-american-indie-underground-1981-1991_985/index.html", "http://books.toscrape.com/catalogue/olio_984/index.html", "http://books" .toscrape.com/catalogue/mesaerion-the-best-science-fiction-stories-1800-1849_983/index.html", "http://books.toscrape.com/catalogue/libertarianism-for-beginners_982/index.html" ', 'http://books.toscrape.com/catalogue/its-only-the-himalayas_981/index.html']
Tämä on loistava alku, mutta haluat kaapata kaikki tietyn kirjan olennaiset tiedot, ei vain sen URL-osoitetta. Käytät nyt näitä URL-osoitteita jokaisen sivun avaamiseen ja kirjan nimen, tekijän, hinnan, saatavuuden, UPC:n, kuvauksen ja kuvan URL-osoitteen keräämiseen.
Avaa uudelleenpageScraper.js
:
- nanopageScraper.js
Lisää seuraava koodi, joka käy läpi jokaisen kaavitun linkin, avaa uuden sivun esiintymän ja noutaa sitten tarvittavat tiedot:
./book-scraper/pageScraper.js
konstscraperObject= { url: "http://books.toscrape.com", asynk kaavin(selain){ antaasivu= odottaaselain.uusi sivu();konsoli.Hirsi(`Navigoidaan kohteeseen${Tämä.url}...`);// Navigoi valitulle sivulleodottaasivu.mene(Tämä.url);// Odota, että vaadittu DOM renderöidäänodottaasivu.odotaValitsijaa('.page_inner');// Hanki linkki kaikkiin tarvittaviin kirjoihinantaaURL-osoitteet= odottaasivu.$$eval('section ol > li', linkkejä => {// Varmista, että kaavittava kirja on varastossalinkkejä=linkkejä.suodattaa(linkki =>linkki.querySelector('.instock.availability > i').tekstisisältö!== "Varastossa")// Pura linkit tiedoistalinkkejä=linkkejä.kartta(hän =>hän.querySelector('h3 > a').href)palatalinkkejä;}); // Selaa jokaisen linkin läpi, avaa uusi sivuinstanssi ja hanki niistä tarvittavat tiedotantaa sivu Lupaus = (linkki) => Uusi Lupaus(asynk(ratkaista,hylätä) => {antaadataObj= {};antaauusi sivu= odottaaselain.uusi sivu();odottaauusi sivu.mene(linkki);dataObj['kirjan nimi'] = odottaauusi sivu.$eval(".product_main > h1", teksti =>teksti.tekstisisältö);dataObj['bookPrice'] = odottaauusi sivu.$eval(".price_color", teksti =>teksti.tekstisisältö);dataObj['ei saatavilla'] = odottaauusi sivu.$eval('.varasto.saatavuus', teksti => {// Poista uudet rivi- ja sarkainvälitteksti=teksti.tekstisisältö.korvata(/(\r\n\t|\n|\r|\t)/gm, "");// Hanki käytettävissä olevien varastojen määräantaaregexp= /^.*\((.*)\).*$/i;antaavarastossa saatavilla=regexp.exec(teksti)[1].jakaa('')[0];palatavarastossa saatavilla;});dataObj['imageUrl'] = odottaauusi sivu.$eval("#product_gallery img", img =>img.src);dataObj['bookDescription'] = odottaauusi sivu.$eval('#Tuotteen Kuvaus', div =>div.seuraava sisarus.seuraava sisarus.tekstisisältö);dataObj['upc'] = odottaauusi sivu.$eval('.table.table-striped > tbody > tr > td', pöytä =>pöytä.tekstisisältö);ratkaista(dataObj);odottaauusi sivu.kiinni();});varten(linkkisisäänURL-osoitteet){antaaCurrentPageData= odottaa sivu Lupaus(URL-osoitteet[linkki]);// scrapedData.push(currentPageData);konsoli.Hirsi(CurrentPageData);} }}moduuli.vientiä=scraperObject;
Sinulla on joukko kaikkia URL-osoitteita. Haluat käydä läpi tämän taulukon, avata URL-osoitteen uudella sivulla, kaapata tietoja kyseiseltä sivulta, sulkea sivu ja avata uuden sivun taulukon seuraavaa URL-osoitetta varten. Huomaa, että käärit tämän koodin lupaukseen. Tämä johtuu siitä, että haluat odottaa jokaisen silmukan toiminnon valmistumista. Siksi jokainen lupaus avaa uuden URL-osoitteen, eikä se ratkea ennen kuin ohjelma on raapunut kaikki URL-osoitteen tiedot ja sitten sivun esiintymä on suljettu.
Varoitus:Huomaa hyvin, että odotit lupausta käyttämällä asisään
silmukka. Mikä tahansa muu silmukka riittää, mutta vältä iteroimista URL-taulukoiden yli käyttämällä taulukkoiterointimenetelmää, kutenjokaiselle
, tai mikä tahansa muu menetelmä, joka käyttää takaisinsoittotoimintoa. Tämä johtuu siitä, että takaisinsoittotoiminnon on käytävä ensin takaisinsoittojonon ja tapahtumasilmukan läpi, joten useat sivun esiintymät avautuvat kerralla. Tämä rasittaa paljon enemmän muistiasi.
Katso tarkemmin omaasisivu Lupaus
toiminto. Kaavin loi ensin uuden sivun jokaiselle URL-osoitteelle ja käytit sittensivu.$eval()
-toiminto kohdistaa valitsijoihin asiaankuuluviin yksityiskohtiin, jotka halusit kaapata uudelle sivulle. Jotkut tekstit sisältävät välilyöntejä, sarkaimia, rivinvaihtoja ja muita ei-aakkosnumeerisia merkkejä, jotka olet poistanut säännöllisellä lausekkeella. Lisäsit sitten jokaisen tällä sivulla kaavitun datan arvon objektiin ja ratkaisit kyseisen objektin.
Tallenna ja sulje tiedosto.
Suorita skripti uudelleen:
- npmjuoksun aloitus
Selain avaa kotisivun ja avaa sitten jokaisen kirjan sivun ja kirjaa kaavitut tiedot jokaiselta sivulta. Tämä tulos tulostuu konsoliisi:
Lähtö
Selaimen avaaminen......Siirrytään osoitteeseen http://books.toscrape.com...{ bookTitle: 'A Light in the Attic', bookHinta: '51,77 £, eiSaatavilla: '22', imageUrl: ' http://books.toscrape.com/media/cache/fe/72/fe72f0532301ec28892ae79a629a293c.jpg', bookDescription: "On vaikea kuvitella maailmaa ilman valoa ullakolla. [...]", upc: 'a897fe39b2153 '}{ bookTitle: 'Tipping the Velvet', bookHinta: '53,74 puntaa', eiSaatavilla: '20', imageUrl: 'http://books.toscrape.com/media/cache/08/e9/08e94f3731d7d6b760dfca'5. bookDescription: `"Eroottinen ja kottainen...Kirjoitettu kottaraisen voimalla."--"New York Timesin kirja-arvostelu" Nan King, osterityttö, kiehtoo musiikkihalli-ilmiötä Kitty Butler [...]`, upc : '90FA61229261140A'} {BookTitle: 'Soumission', BookPrice: '£ 50.10', Noavable: '20', ImageUrl: 'http://books.toscrape.com/media/cache/ee/cf/eecfe998905E455df12064dba399c075.jpg' , bookDescription: 'Dans une France assez proche de la nôtre, [...]', upc: '6957f44c3847a760'}...
Tässä vaiheessa keräsit tarvittavat tiedot jokaisesta kirjan etusivultabooks.toscrape.com, mutta voit lisätä paljon enemmän toimintoja. Esimerkiksi kirjojen jokainen sivu on sivuttu; miten saat kirjoja näiltä muilta sivuilta? Lisäksi sivuston vasemmasta reunasta löysit kirjaluokkia; entä jos et halua kaikkia kirjoja, mutta haluat vain kirjoja tietystä genrestä? Lisäät nyt nämä ominaisuudet.
Vaihe 4 – Tietojen kaapiminen useilta sivuilta
Sivut päälläbooks.toscrape.comsivutuissa on aSeuraava
-painiketta sisällön alla, kun taas sivut, joita ei ole sivutettu, eivät.
Tämän painikkeen avulla voit määrittää, onko sivu sivutettu vai ei. Koska jokaisen sivun tiedot ovat rakenteeltaan samanlaisia ja niissä on samat merkinnät, et kirjoita kaavinta jokaiselle mahdolliselle sivulle. Sen sijaan käytät käytäntöärekursio.
Ensin sinun on muutettava koodisi rakennetta hieman, jotta voit siirtyä rekursiivisesti useille sivuille.
Avaa uudelleenpagescraper.js
:
- nanopagescraper.js
Lisäät uuden toiminnon nimeltäscrapeCurrentPage()
sinunkaavin()
menetelmä. Tämä toiminto sisältää kaiken koodin, joka kerää tietoja tietystä sivusta ja napsauta sitten seuraavaa painiketta, jos se on olemassa. Lisää seuraava korostettu koodi:
./book-scraper/pageScraper.js scraper()
konstscraperObject= { url: "http://books.toscrape.com", asynk kaavin(selain){antaasivu= odottaaselain.uusi sivu();konsoli.Hirsi(`Navigoidaan kohteeseen${Tämä.url}...`);// Navigoi valitulle sivulleodottaasivu.mene(Tämä.url);antaascrapedData= [];// Odota, että vaadittu DOM renderöidäänasynk toiminto scrapeCurrentPage(){odottaasivu.odotaValitsijaa('.page_inner');// Hanki linkki kaikkiin tarvittaviin kirjoihinantaaURL-osoitteet= odottaasivu.$$eval('section ol > li', linkkejä => {// Varmista, että kaavittava kirja on varastossalinkkejä=linkkejä.suodattaa(linkki =>linkki.querySelector('.instock.availability > i').tekstisisältö!== "Varastossa")// Pura linkit tiedoistalinkkejä=linkkejä.kartta(hän =>hän.querySelector('h3 > a').href)palatalinkkejä;});// Selaa jokaisen linkin läpi, avaa uusi sivuinstanssi ja hanki niistä tarvittavat tiedotantaa sivu Lupaus = (linkki) => Uusi Lupaus(asynk(ratkaista,hylätä) => {antaadataObj= {};antaauusi sivu= odottaaselain.uusi sivu();odottaauusi sivu.mene(linkki);dataObj['kirjan nimi'] = odottaauusi sivu.$eval(".product_main > h1", teksti =>teksti.tekstisisältö);dataObj['bookPrice'] = odottaauusi sivu.$eval(".price_color", teksti =>teksti.tekstisisältö);dataObj['ei saatavilla'] = odottaauusi sivu.$eval('.varasto.saatavuus', teksti => {// Poista uudet rivi- ja sarkainvälitteksti=teksti.tekstisisältö.korvata(/(\r\n\t|\n|\r|\t)/gm, "");// Hanki käytettävissä olevien varastojen määräantaaregexp= /^.*\((.*)\).*$/i;antaavarastossa saatavilla=regexp.exec(teksti)[1].jakaa('')[0];palatavarastossa saatavilla;});dataObj['imageUrl'] = odottaauusi sivu.$eval("#product_gallery img", img =>img.src);dataObj['bookDescription'] = odottaauusi sivu.$eval('#Tuotteen Kuvaus', div =>div.seuraava sisarus.seuraava sisarus.tekstisisältö);dataObj['upc'] = odottaauusi sivu.$eval('.table.table-striped > tbody > tr > td', pöytä =>pöytä.tekstisisältö);ratkaista(dataObj);odottaauusi sivu.kiinni();});varten(linkkisisäänURL-osoitteet){antaaCurrentPageData= odottaa sivu Lupaus(URL-osoitteet[linkki]);scrapedData.työntää(CurrentPageData);// console.log(currentPageData);}// Kun kaikki tämän sivun tiedot on valmis, napsauta Seuraava-painiketta ja aloita seuraavan sivun kaapiminen// Tarkistat ensin, onko tämä painike olemassa, jotta tiedät onko seuraava sivu todella olemassa.antaanextButtonExist= väärä;yrittää{konstnextButton= odottaasivu.$eval('.seuraava > a', a =>a.tekstisisältö);nextButtonExist= totta;}ottaa kiinni(err){nextButtonExist= väärä;}jos(nextButtonExist){odottaasivu.klikkaus('.seuraava > a');palata scrapeCurrentPage(); // Kutsu tätä funktiota rekursiivisesti}odottaasivu.kiinni();palatascrapedData;}antaatiedot= odottaa scrapeCurrentPage();konsoli.Hirsi(tiedot);palatatiedot;}}moduuli.vientiä=scraperObject;
Sinä asetatnextButtonExist
muuttujan arvoksi false aluksi ja tarkista sitten, onko painike olemassa. JosSeuraava
painike on olemassa, asetat itsenextButtonOn olemassa
tototta
ja jatka napsauttamallaSeuraava
-painiketta ja kutsu sitten tätä funktiota rekursiivisesti.
JosnextButtonOn olemassa
on väärä, se palauttaascrapedData
joukko tavalliseen tapaan.
Tallenna ja sulje tiedosto.
Suorita skripti uudelleen:
- npmjuoksun aloitus
Tämä saattaa kestää jonkin aikaa. sovelluksesi loppujen lopuksi kaappaa nyt tietoja yli 800 kirjasta. Sulje selain vapaasti tai painaCTRL + C
peruuttaaksesi prosessin.
Olet nyt maksimoinut kaapimesi ominaisuudet, mutta olet luonut uuden ongelman prosessissa. Nyt ongelma ei ole liian vähän, vaan liian paljon. Seuraavassa vaiheessa hienosäädät sovellustasi suodattaaksesi kaavintuksesi kirjakategorioiden mukaan.
Vaihe 5 – Tietojen kaapiminen luokan mukaan
Jos haluat kaapata tietoja luokittain, sinun on muokattava molempiapageScraper.js
tiedosto ja sinunpageController.js
tiedosto.
AvatapageController.js
tekstieditorissa:
nano pageController.js
Soita kaavinta, jotta se raaputtaa vain matkakirjoja. Lisää seuraava koodi:
./book-scraper/pageController.js
konstsivukaavin= vaatia('./pageScraper');asynk toiminto scrapeAll(selainInstance){antaaselain;yrittää{selain= odottaaselainInstance;antaascrapedData= {};// Soita kaavin erilaisten kirjojen kaavittavaksiscrapedData['Matkustaa'] = odottaasivukaavin.kaavin(selain, 'Matkustaa');odottaaselain.kiinni();konsoli.Hirsi(scrapedData)}ottaa kiinni(err){konsoli.Hirsi("Selaininstanssia ei voitu ratkaista =>",err);}}moduuli.vientiä = (selainInstance) => scrapeAll(selainInstance)
Siirrät nyt kaksi parametria omaanpageScraper.scraper()
menetelmä, jossa toinen parametri on kaavittavien kirjojen luokka, mikä tässä esimerkissä onMatkustaa
. Mutta sinunpageScraper.js
tiedosto ei vielä tunnista tätä parametria. Sinun on myös säädettävä tätä tiedostoa.
Tallenna ja sulje tiedosto.
AvatapageScraper.js
:
- nanopageScraper.js
Lisää seuraava koodi, joka lisää luokkaparametrisi, siirry kyseiselle luokkasivulle ja aloita sitten sivuttujen tulosten kaapiminen:
./book-scraper/pageScraper.js
konstscraperObject= { url: "http://books.toscrape.com", asynk kaavin(selain,kategoria){ antaasivu= odottaaselain.uusi sivu();konsoli.Hirsi(`Navigoidaan kohteeseen${Tämä.url}...`); // Navigoi valitulle sivulle odottaasivu.mene(Tämä.url); // Valitse näytettävän kirjan luokkaantaavalittu luokka= odottaasivu.$$eval('.side_categories > ul > li > ul > li > a', (linkkejä,_kategoria) => {// Etsi elementtiä, jolla on vastaava tekstilinkkejä=linkkejä.kartta(a =>a.tekstisisältö.korvata(/(\r\n\t|\n|\r|\t|^\s|\s$|\B\s|\s\B)/gm, "") ===_kategoria?a: tyhjä);antaalinkki=linkkejä.suodattaa(tx =>tx!== tyhjä)[0];palatalinkki.href;},kategoria);// Navigoi valittuun luokkaanodottaasivu.mene(valittu luokka); antaascrapedData= []; // Odota, että vaadittu DOM renderöidään asynk toiminto scrapeCurrentPage(){ odottaasivu.odotaValitsijaa('.page_inner'); // Hanki linkki kaikkiin tarvittaviin kirjoihin antaaURL-osoitteet= odottaasivu.$$eval('section ol > li', linkkejä => { // Varmista, että kaavittava kirja on varastossalinkkejä=linkkejä.suodattaa(linkki =>linkki.querySelector('.instock.availability > i').tekstisisältö!== "Varastossa") // Pura linkit tiedoistalinkkejä=linkkejä.kartta(hän =>hän.querySelector('h3 > a').href) palatalinkkejä; }); // Selaa jokaisen linkin läpi, avaa uusi sivuinstanssi ja hanki niistä tarvittavat tiedot antaa sivu Lupaus = (linkki) => Uusi Lupaus(asynk(ratkaista,hylätä) => { antaadataObj= {}; antaauusi sivu= odottaaselain.uusi sivu(); odottaauusi sivu.mene(linkki);dataObj['kirjan nimi'] = odottaauusi sivu.$eval(".product_main > h1", teksti =>teksti.tekstisisältö);dataObj['bookPrice'] = odottaauusi sivu.$eval(".price_color", teksti =>teksti.tekstisisältö);dataObj['ei saatavilla'] = odottaauusi sivu.$eval('.varasto.saatavuus', teksti => { // Poista uudet rivi- ja sarkainvälitteksti=teksti.tekstisisältö.korvata(/(\r\n\t|\n|\r|\t)/gm, ""); // Hanki käytettävissä olevien varastojen määrä antaaregexp= /^.*\((.*)\).*$/i; antaavarastossa saatavilla=regexp.exec(teksti)[1].jakaa('')[0]; palatavarastossa saatavilla; });dataObj['imageUrl'] = odottaauusi sivu.$eval("#product_gallery img", img =>img.src);dataObj['bookDescription'] = odottaauusi sivu.$eval('#Tuotteen Kuvaus', div =>div.seuraava sisarus.seuraava sisarus.tekstisisältö);dataObj['upc'] = odottaauusi sivu.$eval('.table.table-striped > tbody > tr > td', pöytä =>pöytä.tekstisisältö); ratkaista(dataObj); odottaauusi sivu.kiinni(); }); varten(linkkisisäänURL-osoitteet){ antaaCurrentPageData= odottaa sivu Lupaus(URL-osoitteet[linkki]);scrapedData.työntää(CurrentPageData); // console.log(currentPageData); } // Kun kaikki tämän sivun tiedot on valmis, napsauta Seuraava-painiketta ja aloita seuraavan sivun kaapiminen // Tarkistat ensin, onko tämä painike olemassa, jotta tiedät onko seuraava sivu todella olemassa. antaanextButtonExist= väärä; yrittää{ konstnextButton= odottaasivu.$eval('.seuraava > a', a =>a.tekstisisältö);nextButtonExist= totta; } ottaa kiinni(err){nextButtonExist= väärä; } jos(nextButtonExist){ odottaasivu.klikkaus('.seuraava > a'); palata scrapeCurrentPage(); // Kutsu tätä funktiota rekursiivisesti } odottaasivu.kiinni(); palatascrapedData; } antaatiedot= odottaa scrapeCurrentPage();konsoli.Hirsi(tiedot); palatatiedot; }}moduuli.vientiä=scraperObject;
Tämä koodilohko käyttää antamaasi luokkaa saadakseen URL-osoitteen, jossa kyseisen luokan kirjat sijaitsevat.
Thesivu.$$eval()
voi ottaa argumentteja välittämällä argumentin kolmantena parametrina parametrille$$eval()
menetelmää ja määrittämällä sen kolmanneksi parametriksi takaisinkutsussa:
esimerkkisivu.$$eval()-funktio
sivu.$$eval('valitsin', toiminto(elem,args){//.......},args)
Tämä oli mitä teit koodissasi; olet läpäissyt kirjojen luokan, jonka halusit kaapata, kartoittanut kaikki luokat tarkistaaksesi, mikä niistä vastaa, ja palautti sitten tämän luokan URL-osoitteen.
Tätä URL-osoitetta käytetään sitten siirtymiseen sivulle, joka näyttää kirjakategorian, jonka haluat kaapata käyttämälläpage.goto(selectedCategory)
menetelmä.
Tallenna ja sulje tiedosto.
Suorita sovelluksesi uudelleen. Huomaat, että se siirtyy kohtaanMatkustaa
luokka, avaa rekursiivisesti kyseisen luokan kirjoja sivu sivulta ja kirjaa tulokset lokiin:
- npmjuoksun aloitus
Tässä vaiheessa kaavisit tietoja useilta sivuilta ja sitten kaavisit tietoja useilta sivuilta yhdestä tietystä luokasta. Viimeisessä vaiheessa muokkaat skriptiäsi keräämään tietoja useista luokista ja tallennat sitten kopioidut tiedot ketjutettuun JSON-tiedostoon.
Vaihe 6 – Tietojen kerääminen useista luokista ja tietojen tallentaminen JSON-muodossa
Tässä viimeisessä vaiheessa annat skriptin raaputtaa tiedot pois niin monesta luokasta kuin haluat ja muutat sitten tulostustapaa. Tuloksia kirjaamisen sijaan tallennat ne jäsenneltyyn tiedostoon nimeltädata.json
.
Voit lisätä nopeasti lisää luokkia kaavittavaksi; tämä vaatii vain yhden lisärivin genreä kohden.
AvatapageController.js
:
- nanopageController.js
Muokkaa koodia lisäämään luokkia. Alla oleva esimerkki lisääHistoriallinen fiktio
jaMysteeri
olemassa olevaanMatkustaa
kategoria:
./book-scraper/pageController.js
konstsivukaavin= vaatia('./pageScraper');asynk toiminto scrapeAll(selainInstance){ antaaselain; yrittää{selain= odottaaselainInstance;antaascrapedData= {};// Soita kaavin erilaisten kirjojen kaavittavaksiscrapedData['Matkustaa'] = odottaasivukaavin.kaavin(selain, 'Matkustaa');scrapedData['Historiallinen fiktio'] = odottaasivukaavin.kaavin(selain, 'Historiallinen fiktio');scrapedData['Mysteeri'] = odottaasivukaavin.kaavin(selain, 'Mysteeri');odottaaselain.kiinni();konsoli.Hirsi(scrapedData)}ottaa kiinni(err){konsoli.Hirsi("Selaininstanssia ei voitu ratkaista =>",err);}}moduuli.vientiä = (selainInstance) => scrapeAll(selainInstance)
Tallenna ja sulje tiedosto.
Suorita skripti uudelleen ja katso, kuinka se kerää tietoja kaikista kolmesta kategoriasta:
- npmjuoksun aloitus
Kun kaavin on täysin toimiva, viimeinen vaihe on tietojen tallentaminen hyödyllisempään muotoon. Tallennat sen nyt JSON-tiedostoon käyttämälläthefs
moduuli Node.js:ssä.
Avaa ensin uudelleenpageController.js
:
- nanopageController.js
Lisää seuraava korostettu koodi:
./book-scraper/pageController.js
konstsivukaavin= vaatia('./pageScraper');konstfs= vaatia('fs');asynk toiminto scrapeAll(selainInstance){antaaselain;yrittää{selain= odottaaselainInstance;antaascrapedData= {};// Soita kaavin erilaisten kirjojen kaavittavaksiscrapedData['Matkustaa'] = odottaasivukaavin.kaavin(selain, 'Matkustaa');scrapedData['Historiallinen fiktio'] = odottaasivukaavin.kaavin(selain, 'Historiallinen fiktio');scrapedData['Mysteeri'] = odottaasivukaavin.kaavin(selain, 'Mysteeri');odottaaselain.kiinni();fs.kirjoitustiedosto("data.json", JSON.kiristää(scrapedData), "utf8", toiminto(err) { jos(err) { palatakonsoli.Hirsi(err); } konsoli.Hirsi("Tiedot on kaavittu ja tallennettu onnistuneesti! Katso ne osoitteessa './data.json'");});}ottaa kiinni(err){konsoli.Hirsi("Selaininstanssia ei voitu ratkaista =>",err);}}moduuli.vientiä = (selainInstance) => scrapeAll(selainInstance)
Ensinnäkin tarvitset Node,js:nfs
moduuli sisäänpageController.js
. Tämä varmistaa, että voit tallentaa tietosi JSON-tiedostona. Sitten lisäät koodia, jotta kun kaapiminen on valmis ja selain sulkeutuu, ohjelma luo uuden tiedoston nimeltädata.json
. Huomaa, että sisältödata.json
ovatjäykistetty JSON. Siksi, kun luet sisältöädata.json
, ainajäsentää se JSON-muodossaennen tietojen uudelleenkäyttöä.
Tallenna ja sulje tiedosto.
Olet nyt rakentanut verkkokaappaussovelluksen, joka kaapii kirjoja useista luokista ja tallentaa sitten kopioidut tiedot JSON-tiedostoon. Sovelluksesi monimutkaisuuden kasvaessa saatat haluta tallentaa nämä kerätyt tiedot tietokantaan tai palvella niitä API:n kautta. Se, miten tätä dataa käytetään, on todella sinun päätettävissäsi.
Johtopäätös
Tässä opetusohjelmassa rakensit indeksointirobotin, joka kaavi dataa useilta sivuilta rekursiivisesti ja tallensi sen sitten JSON-tiedostoon. Lyhyesti sanottuna opit uuden tavan automatisoida tietojen kerääminen verkkosivustoilta.
Puppeteerilla on melko paljon ominaisuuksia, jotka eivät kuuluneet tämän opetusohjelman piiriin. Katso lisätietojaPuppeteerin käyttö päättömän Chromen helppoon hallintaan. Voit myös käydäNukketeatterin virallinen dokumentaatio.