programming ruby google drive nokogiri html oauth2

Leggere i documenti in Google Drive con Ruby

La settimana scorsa avevo spiegato come leggere le email con ruby. Più o meno per lo stesso motivo, ho provato a leggere i documenti da Google Drive. La cosa è stata abbastanza semplice, perché ho trovato già pronte delle gems, cioè google_drive (che permette anche di utilizzare l'autenticazione oauth2 e nokogiri che mi fa estrarre solo l'html che mi serve dal documento.

Prerequisiti

Installare le gems

gem install google_drive
gem install nokogiri

Autenticazione semplice

require "google_drive"

# Accede a Google Drive    
session = GoogleDrive.login("username@gmail.com", "mypassword")
# Mostra tutti i documenti
session.files.each do |file|
  p file.title
end

Ma io ho bisogno di ottenere l'html! Con il seguente script si scaricano tutti i documenti nella cartella doc.

require "google_drive"

DST_DIR = "doc"
FileUtils.mkdir_p(DST_DIR) unless File.exists?(DST_DIR)
# Accede a Google Drive    
session = GoogleDrive.login("username@gmail.com", "mypassword")
# Per ogni documento
session.files.each do |file|
  # scarica il file
  file.download_to_file("#{DST_DIR}/#{file.title}.html", :content_type => "text/html")
end

Per includerlo tranquillamente in una pagina html esistente, devo prima estrarre il contenuto di body. Per questo ho usato nokogiri, un parser HTML (e non solo).

Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among Nokogiri’s many features is the ability to search documents via XPath or CSS3 selectors.

require "google_drive"
require "nokogiri"

DST_DIR = "doc"
FileUtils.mkdir_p(DST_DIR) unless File.exists?(DST_DIR)
# Accede a Google Drive    
session = GoogleDrive.login("username@gmail.com", "mypassword")
# Per ogni documento
session.files.each do |file|
  filename = "#{DST_DIR}/#{file.title}.html"
  # scarica il file
  file.download_to_file(filename, :content_type => "text/html")
  # Parse HTML
  page = Nokogiri::HTML(open(filename))
  # Estrai html di body
  content = page.css("body")[0].inner_html
  style = page.css("style")[0].inner_html
end

La variabile content è un oggetto String con il contenuto html del corpo del documento. La variabile style contiene lo stylesheet del documento. Ora possiamo usarle come meglio crediamo!

Rendere pubblici i documenti

Purtroppo, se nel documento ci sono delle immagini, queste sono collegate a Google Drive. Nel mio caso non ho necessità di tenere il documento in modalità "Privata" in lettura. Così posso utilizzare Google Drive come CDN per le immagini. Ma prima devo mettere i documenti in modalità condivisa:

  • click destro sul documento
  • condividi
  • Condividi...
  • Chi ha accesso - Cambia
  • Opzioni di visibilità: pubblica sul web
  • Controllare che sia così: Accesso:Chiunque (non richiede l'accesso) Può visualizzare
  • Salva

Integrazione con Jekyll

Perché no? In fondo... Google Drive ha un'ottima interfaccia WYSIWYG, quindi si può usare per creare velocemente documenti ricchi, con immagine, formattazione e oltre. Non è nel mio stile, ma va benissimo per il mio amico che non conosce un minimo di html.

Di cosa abbiamo bisogno? Vogliamo che tutti i documenti salvati nella cartella posts diventino i post di Jekyll. Dobbiamo quindi estrarre alcune informazioni, come la data di pubblicazione e il titolo del documento. Vogliamo anche che tutti i documenti nella cartella pages siano trattati come normali pagine.

Aggiungiamo questo al Rakefile:

require "stringex"
require "google_drive"
require "nokogiri"

desc "Download posts from Google Drive"
task :pull_google_drive do
  # Accede a Google Drive
  session = GoogleDrive.login("username@gmail.com", "mypassword")
  # Per ogni documento nella cartella posts
  session.collection_by_title("posts").files.each do |file|
    published = Time.parse(file.document_feed_entry.css('published')[0].content)
    title = file.title
    filename = "#{source_dir}/#{posts_dir}/#{published.strftime('%Y-%m-%d')}-#{title.to_url}.html"
    tmp_filename = "#{filename}.tmp.html";
    # scarica il file
    file.download_to_file(tmp_filename, :content_type => "text/html")
    # Parse HTML
    page = Nokogiri::HTML(open(tmp_filename))
    # Estrai html di body
    content = page.css("body")[0].inner_html
    style = page.css("style")[0]
    open(filename, 'w') do |post|
      post.puts "---"
      post.puts "layout: post"
      post.puts "title: \"#{title.gsub(/&/,'&')}\""
      post.puts "date: #{published.strftime('%Y-%m-%d %H:%M')}"
      post.puts "---"
      post.puts style
      post.puts content
    end
  end
  # Per ogni documento nella cartella pages
  session.collection_by_title("pages").files.each do |file|
    title = file.title
    filename = "#{source_dir}/#{title.to_url}.html"
    tmp_filename = "#{filename}.tmp.html";
    # scarica il file
    file.download_to_file(tmp_filename, :content_type => "text/html")
    # Parse HTML
    page = Nokogiri::HTML(open(tmp_filename))
    # Estrai html di body
    content = page.css("body")[0].inner_html
    style = page.css("style")[0]
    open(filename, 'w') do |post|
      post.puts "---"
      post.puts "layout: default"
      post.puts "title: \"#{title.gsub(/&/,'&')}\""
      post.puts "---"
      post.puts style
      post.puts content
    end
  end
end

Ora basta chiamare rake pull_google_drive per sincronizzare Jekyll con Google Drive. Attenzione: bisogna creare le cartelle posts e pages nel Google Drive e inserire almeno un documento all'interno di esse, altrimenti questo script lancia un errore.

Dopo la sincronizzazione, basta chiamare al solito jekyll --server (oppure jekyll serve nel caso sia la versione 1.0) per vedere il risultato.

Ti è piaciuto l'articolo? Condividilo! Commentalo!

comments powered by Disqus