Hogyan lehet kaparni a Ruby-val és a Nokogirivel, és feltérképezni az adatokat

Néha meg akarja ragadni az adatokat egy webhelyről a saját projektjéhez. Szóval mit használsz? Ruby, Nokogiri és JSON a megmentéshez!

A közelmúltban a hidakra vonatkozó adatok feltérképezésén dolgoztam. A Nokogiri segítségével egy város híd adatait sikerült megfognom egy táblából. Ezután ugyanabban a táblázatban lévő hivatkozásokat használtam a kapcsolódó oldalak kaparására. Végül a lekapart adatokat konvertáltam JSON-ra, és egy Google Map feltöltésére használtam.

Ez a cikk bemutatja az általam használt eszközöket és a kód működését!

Lásd a teljes kódot a GitHub repóban.

Élő térképes bemutató itt.

A projekt

Célom az volt, hogy vegyek egy táblázatot egy hídadat-webhelyről, és azt Google-térképpé alakítsam, amely földrajzi elhelyezkedésű csapokat tartalmaz, amelyek minden hídhoz információs előugró ablakokat készítenek.

Ennek megvalósításához a következőket kell tennem:

  1. Adatok kaparása az eredeti webhelyről.
  2. Konvertálja ezeket az adatokat JSON objektummá.
  3. Alkalmazza ezeket az adatokat egy új, interaktív térkép elkészítéséhez.

A projektje bizonyosan változni fog - hányan próbálják feltérképezni az antik hidakat? - de remélem, hogy ez a folyamat hasznosnak bizonyul a környezetében.

Nokogiri

Rubynak van egy csodálatos web-kaparó gyöngyszeme, Nokogiri néven. Egyéb funkciók mellett lehetővé teszi HTML dokumentumok keresését CSS választók által. Ez azt jelenti, hogy ha ismerjük az azonosítókat, osztályokat vagy akár elemtípusokat, ahol az adatokat a DOM tárolja, akkor képesek leszünk kitépni őket.

A kaparó

Ha a GibHub repóval együtt jár, akkor a kaparóm a bridges_scraper.rb oldalon található.

require 'open-uri'require 'nokogiri'require 'json'

Az Open-uri lehetővé teszi, hogy fájlként nyissuk meg a HTML-t, és továbbítsuk a Nokogirihez a nehéz emeléshez.

Az alábbi kódban a DOM információkat átadom az URL-ről a hídadatokkal a Nokogirinek. Ezután megtalálom az adatokat tartó táblaelemet, megkeresem a sorait, és iterálok rajtuk keresztül.

url = '//bridgereports.com/city/wichita-kansas/'html = open(url)
doc = Nokogiri::HTML(html)bridges = []table = doc.at('table')
table.search('tr').each do |tr| bridges.push( carries: cells[1].text, crosses: cells[2].text, location: cells[3].text, design: cells[4].text, status: cells[5].text, year_build: cells[6].text.to_i, year_recon: cells[7].text, span_length: cells[8].text.to_f, total_length: cells[9].text.to_f, condition: cells[10].text, suff_rating: cells[11].text.to_f, id: cells[12].text.to_i )end
json = JSON.pretty_generate(bridges)File.open("data.json", 'w')  file.write(json) 

A Nokogirinek rengeteg módszere van (itt van egy csalólap és egy kezdő útmutató!). Csak néhányat használunk.

A tábla az .at ('table') fájlnál található , amely egy táblaelem első előfordulását adja vissza a DOM-ban. Ez nagyon jól működik ennek a viszonylag egyszerű oldalnak.

Ha a táblázat a kezünkben van, a .search ('tr') egy sor tömböt ad a sorelemekből , amelyeket az .each- kel iterálunk . Minden sorban megtisztítják az adatokat, és a hidak tömb egyetlen bejegyzésébe tolják.

Miután az összes sort összegyűjtötte, az adatokat JSON-vá konvertálja, és egy új, „data.json” nevű fájlba menti.

Több oldal adatainak egyesítése

Ebben az esetben más kapcsolódó oldalakra volt szükségem információra. Pontosabban szükségem volt minden híd szélességére és hosszúságára, amely nem szerepelt az asztalon. Ugyanakkor azt találtuk, hogy a kapcsolatot az első cella minden sorban vezetett egy oldalt, amely nem biztosítja ezeket a részleteket.

Olyan kódot kellett írnom, amely néhány dolgot végrehajtott:

  • Linkeket gyűjtött a táblázat első cellájából.
  • Létrehozott egy új Nokogiri objektumot az adott oldal HTML-jéből.
  • Szedje ki a szélességi és hosszúsági fokokat.
  • Alvja le a programot, amíg a folyamat befejeződik.
cells = tr.search('th, td') links = {} cells[0].css('a').each do |a| links[a.text] = a['href'] end got_coords = false if links['NBI report'] nbi = links['NBI report'] report = "//bridgereports.com" + nbi report_html = open(report) sleep 1 until report_html r = Nokogiri::HTML(report_html) lat = r.css('span.latitude').text.strip.to_f long = r.css('span.longitude').text.strip.to_f
 got_coords = true else got_coords = true end sleep 1 until got_coords == true
 bridges.push( links: links, latitude: lat, longitude: long, carries: cells[1].text, ..., # all other previous key/value pairs )end

Néhány további dologra érdemes itt felhívni a figyelmet:

  • A „got_coords” -ot egyszerű binárisként használom. Ez alapértelmezés szerint hamis értékre van állítva, és akkor változik, amikor az adatokat rögzítik, VAGY egyszerűen nem állnak rendelkezésre.
  • A szélességi és hosszúsági körök a megfelelő osztályokkal rendelkeznek. Ez egyszerűvé teszi az adatok biztonságát: .css ('span.latitude') Ezt követi .text, .strip és .to_f, amelyek 1) megkapják a szöveget a spanról , 2) csíkolják a felesleges szóközöket és 3) konvertálják a string egy úszó számra.

JSON → Google Map

Az újonnan létrehozott JSON objektumot érintéssel kell módosítani, hogy illeszkedjen a Google Maps API-hoz. Ezt JavaScript-el tettem a map.js-en belül

A JSON-adatok a map.js fájlon belül érhetők el, mert áthelyezték őket a JS mappába, hozzárendelték a „bridge_data” nevű változóhoz, és az index.html címkéjében szerepeltek.

Rendben! Most átalakítjuk a JSON fájlt (a bridge_data változóhoz rendelt) egy új tömbgé, amelyet a Google Maps használhat.

const locations = bridge_data.map(function(b) { var mapEntry = []; var info = "Built In: " + b.year_build + "

" + "Span Length: " + b.span_length + " ft

" + "Total Length: " + b.total_length + " ft

" + "Condition: " + b.condition + "

" + "Design: " + b.design + "

"; mapEntry.push( info, b.latitude, b.longitude, b.id ) return mapEntry;});

A .map segítségével új dimenziós tömböt hozok létre, a „helyek” nevet. Minden bejegyzés tartalmaz információt, amely megjelenik a Google Maps felugró ablakunkban, ha a felhasználó rákattint az adott csapra a térképen. Hozzáadjuk a szélességi, hosszúsági és egyedi hídazonosítót is.

Az eredmény egy olyan Google Map, amely minden hídhoz információs gazdag előugró ablakokkal ábrázolja a helyek tömbjét!

Segített neked? Adj neki néhány tapsot, és kövesd!