Data scraping – przydatne narzędzia skryptowe

Kiedy automatyzacja odpytań serwerów webowych i pozyskiwanie stamtąd treści statycznych i dynamicznych stanie się potrzebą chwili, wówczas oczywiście możemy skorzystać z wielu komercyjnie dostępnych narzędzi, albo błyskawicznie stworzyć narzędzia własne, w oparciu o któryś z preferowanych języków skryptowych. Własnego pomysłu narzędzia mają jednak tę przewagę nad komercyjnymred-pen_data_with_graph_1i „gotowcami”, że można je wzbogacać o dodatkowe, pożyteczne funkcjonalności, wedle uznania i potrzeby. W elastyczności tkwi właśnie ich prawdziwa siła, bo dzięki prostym modyfikacjom mogą być używane do oprogramowania nieraz bardzo kreatywnych pomysłów.

Do czego możemy chcieć wykorzystać narzędzia służące do data scrapingu? Odpowiedź jest oczywista – do automatyzacji pozyskiwania każdego rodzaju danych dostępnych na stronach webowych. Jakiego rodzaju informacje w szczególności wchodzą w rachubę? Może to być na przykład określony rodzaj treści: pliki grafik, dokumenty PDF, teksty, multimedia, kursy walut, notowania giełdowe etc. Może nas też interesować na przykład wyłowienie z treści stron wyłącznie hiperlinków do dalszego ich przetwarzania. Chodzi na przykład o podążanie za linkami i dalszy scraping albo „fotografowanie” i przekształcanie ich treści do postaci dokumentów PDF.

Jako przykład pożytecznego wykorzystania data scraperów niech posłuży choćby automatyzacja pozyskiwania kursów walut albo notowań akcji przedsiębiorstw na giełdach papierów wartościowych. Skrypt, który opracowałem na potrzeby artykułu czyta przkładowo kursy walut ze strony WWW polskiego banku centralnego, po czym wywołuje Excel-a, tworzy w nim arkusz kalkulacyjny i automatycznie wstawia do tego arkusza przeczytane dane. Dodatkowo wyprowadza wspomniane dane na konsolę, po czym proponuje wykonanie „zdjęcia” strony webowej z tabelą kursów i zapisanie jej do pliku PDF.

Może nie jest to jakaś imponująca funkcjonalność, ale na podstawie tego prototypowego rozwiązania można tworzyć w pełni użyteczne narzędzia do znacznie bardziej poważnych zastosowań. Opracowanym i zacytowanym w treści artykułu skryptem chciałem przede wszystkim zwrócić Waszą uwagę na klika ciekawych „klocków”, z których można budować świetne rozwiązania, dające developerowi – trzeba to przyznać bezdyskusyjnie – ogromny power. Jednym z takich klocków jest świetna biblioteka Nokogiri, która oferuje funkcje analizy składniowej stron i dokumentów webowych, szybkie wyszukiwanie w nich informacji, posługując się w tym celu składnią CSS, XPath czy XML. Prawdą jest, że przy jej pomocy, w połączeniu z arsenałem natywnych narzędzi języka skryptowego, służących do przetwarzania wyrażeń regularnych, pozyskiwanie danych ze stron webowych staje się czystą przyjemnością.

Kolejnym „klockiem” godnym uwagi jest biblioteka Win32OLE, pozwalająca na wykorzystywanie funkcji API systemu Windows z poziomu kodu skryptów. W naszym skrypcie biblioteka ta została wykorzystana do wywołania programu Excel, utworzenia w nim arkusza kalkulacyjnego i automatycznego zasilenia go danymi pozyskanymi ze strony webowej.

Wreszcie trzecią godną uwagi biblioteką jest PDFkit. Biblioteka oferuje całe mnóstwo funkcji do tworzenia i przetwarzania dokumentów PDF. W prototypowym skrypcie wykorzystałem ją do utworzenia dokumentu PDF, do którego w następnej kolejności zostało zapisane „zdjęcie” strony webowej (tu: strona z tabelą kursów walut).

Dla porządku przypominam, że przed uruchomieniem skryptu należy zadbać o zainstalowanie wymaganych bibliotek:

gem install nokogiri
gem install win32ole-pp
gem install pdfkit

Kolejny skrypt został opracowany, by pomóc pozyskiwać dane ze stron wymagających interakcyjności. W takich sytuacjach doskonale sprawdza się biblioteka Watir. Pozwala ona na kompletne oprogramowanie interakcji z dowolnymi formularzami na aktywnych stronach webowych. Przydaje się przy testach funkcjonalnych albo testach regresyjnych aplikacji webowych, a także przy testowaniu procedur walidacji danych w formularzach. Może być wykorzystana z powodzeniem również do przeprowadzania testów podatności aplikacji webowych.

Prototypowy skrypt ilustrujący artykuł pokazuje, jak przy pomocy funkcji biblioteki Watir można odpytać wyszukiwarkę Google o określone hasło. Skrypt w pierwszej kolejności wywołuje przeglądarkę Internet Explorer, a następnie wyświetla w jej oknie wyniki swojego działania. Gdybyśmy skorzystać z innej przeglądarki, wówczas należałoby użyć innej, alternatywnej dla Watir-a biblioteki – Watir-webdriver, którą wcześniej rzecz jasna należy zainstalować w systemie.

Zainstalujcie proszę następujące gem-y:

gem install watir
gem install watir-classic
gem install watir-webdriver

Z wyników przeprowadzonego wyszukiwania można w dalszej kolejności „wyłuskać” hiperlinki i podążyć ich śladem, ale oprogramowanie tej funkcjonalności pozostawiam czytelnikom artykułu. Przykłady rozwiązań, znajdujące się w obu skryptach, dostarczają właściwie pełnej bazy wiedzy niezbędnej do łatwego wykonania tego rodzaju modyfikacji.

Zachęcam – jak zwykle – do eksperymentowania i dalszego rozwijania prototypowych skryptów oraz tworzenia na ich podstawie w pełni użytecznych narzędzi. Oto garść pomysłów:

  • Skaner podatności aplikacji webowych;
  • Nakładka na serwisy wyszukiwawcze oferująca filtrowanie informacji pod kątem spełnienia wyrażeń regularnych;
  • Narzędzia – dashboardy do wizualizacji danych pobieranych z Internetu.

Oto kod pierwszego skryptu do pozyskiwania danych z nieinterakcyjnych stron webowych:

require 'nokogiri'
require 'open-uri'
require 'net/https'
require 'win32ole'
require 'rubygems'
require 'pdfkit'

# ----- Function to make a snapshot of web page saved as PDF file
def web2file(url)
   site_image = PDFKit.new(url)
   site_image.to_file("currency.pdf")
end

# ---------------- Collect data from web page -----------------
page = Nokogiri::HTML(open('http://www.nbp.pl/kursy/kursya.html'))
# ---- Perform parsing of collected data using CSS approach ---
content = page.css('table.pad5').css('td')

licznik = 0
row = 2
no_excel = 0

begin
   # ---------- Call Excel and create a new workbook and worksheet
   excel = WIN32OLE.new('Excel.Application')
   excel.visible = true
   workbook = excel.Workbooks.Add();
   worksheet = workbook.Worksheets(1);
   # ---------- Set headers of columns -----------------------------
   worksheet.Range("A1:C1").value = ["Waluta","Przelicznik","Kurs"];
rescue => error
   STDERR.puts "Problem with opening Excel: error"
   no_excel = 1
end
	
# ---------- Fill the worksheet and display scraped data on STDOUT
content.each { |elem| 
   puts elem.to_s.gsub(/<.*?>/, '').force_encoding("utf-8").upcase.rjust(40) 
   case licznik % 3
      when 0
         row +=1 
         worksheet.Range("A#{row}").value = elem.to_s.gsub(/<.*?>/, '').force_encoding("utf-8") if no_excel == 0
      when 1
         worksheet.Range("B#{row}").value = elem.to_s.gsub(/<.*?>/, '').force_encoding("utf-8") if no_excel == 0
      when 2
         worksheet.Range("C#{row}").value = elem.to_s.gsub(/<.*?>/, '').force_encoding("utf-8") if no_excel == 0
         puts '-' * 40
   end
   licznik += 1 
}

if no_excel == 0
   workbook.saved = true;
   # excel.ActiveWorkbook.Close(0);
   # excel.Quit();
end

print "Do you want to make a PDF snapshot of the web page with currency exchange rates? (Y or N) "
answer = STDIN.gets.chomp

case answer
   when /[Yy]/
      begin
         web2file('http://www.nbp.pl/kursy/kursya.html')
      rescue => e
         STDERR.puts "Problem with making PDF snapshot of the web page: #{e)"
      end
      puts "Snapshot complete. Please find it in currency.pdf file"
   when /[Nn]/
      puts "Good bye"
   else
      puts "Unknown option. Must be Y or N"
end

Poniżej znajduje się kod skryptu do pozyskiwania danych ze stron interakcyjnych:

require 'rubygems'
require 'watir'

def ask_google(subject)
   begin
      b = Watir::Browser.new
      b.goto 'www.google.com'
      b.text_field(:name => 'q').set subject
      b.button(:name => 'btnG').click
      b.div(:id => 'resultStats').wait_until_present
      puts b.div(:id => 'rcnt').text.scan(/http.*/)
      puts "\nDisplaying page: '#{b.title}' with results: '#{b.div(:id => "resultStats").text}'"
      print "Do you want to close the browser? (Y/N) "
      answer = STDIN.gets.chomp
      case answer
         when /[Yy]/
            b.close
            puts "Bye, bye..."
         else
            puts "Browser is still open"
      end
   rescue => error
      puts "Problem: #{error}"
      return
   end
end

ask_google("Watir")

Kolejny skrypt pokazuje jak prosta jest ekstrakcja hiperlinków z treści stron webowych.

Jego wywołanie z opcją -h lub –help wyprowadza na konsolę podpowiedź prawidłowej składni:

$ ruby ask_bing.rb -h
Usage: ask_bing.rb [options]
Extract hiperlinks from Bing query about given topic: ask_bing.rb -q topic

Oto kod skryptu:

# encoding: UTF-8 
require 'nokogiri'
require 'open-uri'
require 'optparse'

def syntax
   puts "Extract hiperlinks from Bing query about given topic: #{File.basename($0)} -q topic"
end

def ask_bing(subject)
   subject = subject.gsub(/\s/, '%20')
   doc = Nokogiri::HTML(open("http://www.bing.com/search?q=#{subject}"))
   hiperlinks = doc.css('h2 a[href]').map { |link| link['href'] }
   return hiperlinks	
end	

options = {:topic => nil}

parser = OptionParser.new do |opts|
   opts.banner = "Usage: #{File.basename($0)} [options]"

   opts.on('-q', '--topic topic', 'Topic') do |topic|
      options[:topic] = topic;
   end

   opts.on('-h', '--help', 'Displays Help') do
      puts opts.banner
      syntax
      exit
   end
end

parser.parse!

if options[:topic] == nil
   print 'Enter the topic to search for: '
   options[:topic] = gets.chomp
end

topic = options[:topic]

puts ask_bing(topic)

Przykładowo, efektem zapytań o Nikona D4S będzie:

$ ruby ask_bing.rb -q "Nikon D4S"
http://imaging.nikon.com/lineup/dslr/d4s/
http://www.optyczne.pl/6738-news-Nikon_D4s.html
http://www.nikon.pl/pl_PL/product/digital-cameras/slr/professional/d4s
http://www.kenrockwell.com/nikon/d4s.htm
http://www.nikon.com/news/2014/0225_dslr_01.htm
http://www.fotomaniak.pl/83852/nikon-d4s/
http://www.ceneo.pl/15976986
http://imaging.nikon.com/lineup/dslr/d4s/spec.htm
http://www.skapiec.pl/site/cat/2/comp/9571491
http://www.nikonusa.com/en/Nikon-Products/Product/dslr-cameras/1541/D4S.html

Informacje Janusz Nawrat
Just ordinary man who likes thinking...

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

TOMASZ WEŁNA

artysta grafik | wykładowca

PRACOWNIA OKO

Szkoła Rysunku Malarstwa i Grafiki DR TOMASZA WEŁNY | KRAKÓW | Plac Matejki 10 | tel 691 81 75 74

Piękno neurobiologii

Blog Jerzego Vetulaniego

Teoria muzyki, zasady muzyki, podstawy muzyki

Teoria muzyki, zasady muzyki, podstawy muzyki - czyli to co każdy amator muzyki wiedzieć powinien :)

Personal Development & Inspirations

Przemyślenia i refleksje, którymi warto się podzielić (blog by Janusz Nawrat)

Business IT Cooperation Platform

Biznes i IT - dwa światy, które muszą współdziałać

%d bloggers like this: