Автор оригинала: FreeCodeCamp Community Member.
Andrew Tales
Иногда вы хотите получить данные с сайта для вашего собственного проекта. Так что вы используете? Ruby, Nokogiri и Json к спасению!
Недавно я работал над проектом на карту Данные о мостах Отказ Используя Nokogiri, я смог захватить данные моста города из таблицы. Затем я использовал ссылки в той же таблице, чтобы скрепить связанные страницы. Наконец, я преобразовал SCRAPED DATA в JSON и использовал его для заполнения карты Google.
Эта статья проходит вас через инструменты, которые я использовал и как работает код!
Смотрите полный код на моем Github репо.
Живая карта Demo здесь Отказ
Проект
Моя цель состояла в том, чтобы взять стол из данных моста Сайт И включите его на карту Google с геологическими контактами, которые создали бы информационные всплывающие окна для каждого моста.
Чтобы это случилось, мне нужно:
- Scrape Data с оригинального сайта.
- Преобразуйте эти данные в JSON Object Отказ
- Примените эти данные, чтобы сделать новую интерактивную карту.
Ваш проект будет варьироваться, наверняка – сколько людей пытаются набрать антикварные мосты? – Но я надеюсь, что этот процесс окажется полезным для вашего контекста.
Nokogiri
Ruby имеет удивительный веб-канализационный драгоценный камень Nokogiri Отказ Среди других функций он позволяет искать HTML-документы CSS селекторами. Это означает, что если мы знаем IDS, классы или даже типы элементов, где данные хранятся в DOM, мы можем вырвать это.
Скребок
Если вы следуете наряду с Gibhub Repo , вы можете найти мой скребок в bridges_scraper.rb
require 'open-uri'require 'nokogiri'require 'json'
Open-Uri позволяет нам открывать HTML как файл и передавать его на нокогири для тяжелой подъема.
В приведенном ниже коде я передаю информацию DOM с URL-адреса с мостом данных на Nokogiri. Затем я нахожу элемент таблицы, удерживающую данные, ищите его строки и итерацию через них.
url = 'https://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| file.write(json) }
Nokogiri имеет много методов (вот есть Cheat Sheet и стартер Руководство !). Мы используем всего несколько.
Таблица найдена с .at («Таблица») , который возвращает первый вхождение элемента таблицы в доме. Это работает просто для этой относительно простой страницы.
Со столом в руке, .Search («TR») Предоставляет массив элементов строки, которые мы повторяемся с .each Отказ В каждом ряду данные очищаются и выдвинуты в одну запись для массива мостов.
После того, как все строки собраны, данные преобразуются в JSON и сохраняются в новом файле под названием «Data.json».
Сочетание данных с нескольких страниц
В этом случае мне нужна информация с других связанных страниц. В частности, мне нужна широта и долгота каждого моста, который не был показан на столе. Однако я обнаружил, что ссылка в первой ячейке каждой строки привела к странице, которую сделал предоставить эти детали.
Мне нужно было написать код, который сделал несколько вещей:
- Собранные ссылки от первой ячейки в таблице.
- Создан новый объект Nokogiri из HTML на этой странице.
- Вытащить широту и долготу.
- Спи программу, пока этот процесс не завершится.
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 = "https://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
Несколько дополнительных вещей стоит указывать здесь:
- Я использую «got_coords» как простым двоичным. Это установлено на ложь По умолчанию и переключается, когда данные захвачены или просто недоступны.
- Широта и долгота расположены в промежутках с соответствующими классами. Это делает защищать данные простым: .css (‘Spanip.latitude’) Следуют .Text, .Strip и .to_f Какой 1) получает текст с пролета, 2) полос любых избыточных пробелов, а 3) преобразует строку в номер поплавка.
JSON → Google Map
Недавно сформированный объект JSON должен быть изменен прикосновение, чтобы соответствовать API Google Maps. Я сделал это с JavaScript внутри map.js.
Данные JSON доступны внутри map.js Поскольку он был перемещен в папку JS, назначенную переменной под названием «Brance_data» и включен в тег