Retour d'expérience - aggrégation de données en Ruby (Learnivore.com)

Thibaut Barrère
Aggrégation de données
      avec Ruby
   Retour d’expérience Learnivore.com
             thibaut.barrere@gmail.com




                                         1
A quoi ressemble Learnivore ?




                                2
Briques techniques
•   ThinkingSphinx + Sphinx

•   TinyTL
•   Hpricot
•   TagCleaner
•   Ramaze
•   UrlRewriter
•   ActiveRecord
•   ActsAsTaggableOnSteroids

•   Craken
•   WillPaginate
•   Thin




                                      3
Le modèle
class Item < ActiveRecord::Base
  acts_as_taggable

  validates_presence_of :title, :url, :source, :summary, :thumbnail_img_tag, :pricing
  validates_uniqueness_of :url # our key

  define_index do
    indexes title
    indexes summary
    indexes source, :facet => true
    indexes tags.name, :as => :tag, :facet => true
    indexes pricing, :facet => true
    indexes language, :facet => true
    has update_date
    where "update_date <= curdate()"

    set_property :delta => true
  end
end



                                                                                        4
Processus d’import
• DSL (TinyTL)
• Tourne chaque heure
• Pour chaque source, récupère un feed ou une page html
• Normalise et conforme chaque item
• Ajoute et conforme les tags
• Upsert (update or insert) - clé = url cible


                                                          5
Déclaration d’une source

source(:peepcode) {
  fresh_get(PEEPCODE_HOST + '/products').
    at('ul.products').search('li a').
    map { |e| PEEPCODE_HOST + e['href'] }
}




                                            6
Traitement spécifique (1/2)
each_row(:bddcasts) { |row|
  # resource from rss
  row[:title] = grab(row[:content],'title')
  row[:update_date] = Date.parse(grab(row[:content],'published'))
  row[:url] = grab(row[:content], 'feedburner:origlink')
  row[:summary] = SimpleSanitizer.sanitize( CGI.unescapeHTML(grab(row[:content], 'content')))

    # resource from page
    page = get(row[:url])
    img_src = "http://bddcasts.com" + page.at("div.episode div.image img").attributes['src']
    tags = grab_all(page, "div.episode div.details p.tags a", ', ')
    episode_css_classes = page.at("div.episode").attributes['class']
    pricing = case episode_css_classes
      when /orange/; 'paid'
      when /green/; 'free'
      else raise "Bddcasts pricing guess failed: episode css class : '#{episode_css_classes}"
    end

    row[:thumbnail_img_tag] = "<img src='#{img_src}' height='90' style='border: 1px solid #aaa'/>"
    row[:pricing] = pricing
    row[:tag_list] = tags
}




                                                                                                     7
Traitement spécifique (2/2)
each_row(:thinkcode_tv) { |row|
  row[:title] = grab(row[:content],'title')
  row[:url] = grab(row[:content],'guid').gsub('//catalogo','/catalogo')
  row[:update_date] = Date.parse(grab(row[:content],'pubdate'))
  row[:summary] = SimpleSanitizer.sanitize(CGI.unescapeHTML(grab(row[:content],'description')))

    img_src = Hpricot(CGI.unescapeHTML(grab(row[:content],'description'))).
      at('img').attributes['src']
    row[:thumbnail_img_tag] = "<img height='90' src='#{THINKCODE_HOST}#{img_src}'/>"
    row[:pricing] = 'paid'

    row[:language] = 'italian'
}




                                                                                                  8
Import / nettoyage des tags

•   tags du partenaires
    +
    tags delicious

•   conformation / nettoyage




                               9
Screens (= tests data)
   assert_include %w(free paid), row[:pricing]

   assert_match(/https{0,1}:///, row[:url], :url)

   assert_not_nil row[:update_date]

   assert row[:update_date].is_a?(Date)

   ...




                                                      10
Consommation

• via le web => facettes + full-text
• RSS => sort by fraîcheur desc (feedburner MyBrand)
• Twitter => semi-automatique via bit.ly


                                                       11
Conclusions

• Contacter les partenaires = bien
• ThinkingSphinx = bien
• Code = une petite portion du travail
• Toute data doit généralement être nettoyée avant
  consommation



                                                     12
1 of 12

Recommended

ATA 2010 Conference Proceedings by
ATA 2010 Conference ProceedingsATA 2010 Conference Proceedings
ATA 2010 Conference ProceedingsAgnes Meilhac
329 views12 slides
ChatGPT and the Future of Work - Clark Boyd by
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
28K views69 slides
Getting into the tech field. what next by
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
6.6K views22 slides
Google's Just Not That Into You: Understanding Core Updates & Search Intent by
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
6.9K views99 slides
How to have difficult conversations by
How to have difficult conversations How to have difficult conversations
How to have difficult conversations Rajiv Jayarajah, MAppComm, ACC
5.6K views19 slides
Introduction to Data Science by
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data ScienceChristy Abraham Joy
82.6K views51 slides

More Related Content

Recently uploaded

TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... by
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc
170 views29 slides
The Role of Patterns in the Era of Large Language Models by
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language ModelsYunyao Li
85 views65 slides
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T by
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TCloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TShapeBlue
152 views34 slides
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti... by
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...ShapeBlue
139 views29 slides
State of the Union - Rohit Yadav - Apache CloudStack by
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStackShapeBlue
297 views53 slides
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O... by
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...ShapeBlue
132 views13 slides

Recently uploaded(20)

TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... by TrustArc
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc170 views
The Role of Patterns in the Era of Large Language Models by Yunyao Li
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language Models
Yunyao Li85 views
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T by ShapeBlue
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TCloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
ShapeBlue152 views
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti... by ShapeBlue
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
ShapeBlue139 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue297 views
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O... by ShapeBlue
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...
Declarative Kubernetes Cluster Deployment with Cloudstack and Cluster API - O...
ShapeBlue132 views
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays56 views
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue by ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
ShapeBlue147 views
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue by ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueMigrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
ShapeBlue218 views
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by ShapeBlue
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
ShapeBlue186 views
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R... by ShapeBlue
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
ShapeBlue173 views
Extending KVM Host HA for Non-NFS Storage - Alex Ivanov - StorPool by ShapeBlue
Extending KVM Host HA for Non-NFS Storage -  Alex Ivanov - StorPoolExtending KVM Host HA for Non-NFS Storage -  Alex Ivanov - StorPool
Extending KVM Host HA for Non-NFS Storage - Alex Ivanov - StorPool
ShapeBlue123 views
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
ShapeBlue263 views
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And... by ShapeBlue
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...
Enabling DPU Hardware Accelerators in XCP-ng Cloud Platform Environment - And...
ShapeBlue106 views
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue161 views
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by ShapeBlue
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
ShapeBlue184 views
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by The Digital Insurer
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...
Digital Personal Data Protection (DPDP) Practical Approach For CISOs by Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash158 views

Featured

Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright... by
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
12.7K views21 slides
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present... by
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Applitools
55.5K views138 slides
12 Ways to Increase Your Influence at Work by
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at WorkGetSmarter
401.7K views64 slides
ChatGPT webinar slides by
ChatGPT webinar slidesChatGPT webinar slides
ChatGPT webinar slidesAlireza Esmikhani
30.5K views36 slides
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G... by
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...DevGAMM Conference
3.6K views12 slides

Featured(20)

Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright... by RachelPearson36
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
RachelPearson3612.7K views
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present... by Applitools
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Applitools55.5K views
12 Ways to Increase Your Influence at Work by GetSmarter
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
GetSmarter401.7K views
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G... by DevGAMM Conference
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
DevGAMM Conference3.6K views
Barbie - Brand Strategy Presentation by Erica Santiago
Barbie - Brand Strategy PresentationBarbie - Brand Strategy Presentation
Barbie - Brand Strategy Presentation
Erica Santiago25.1K views
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well by Saba Software
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them wellGood Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Saba Software25.3K views
Introduction to C Programming Language by Simplilearn
Introduction to C Programming LanguageIntroduction to C Programming Language
Introduction to C Programming Language
Simplilearn8.5K views
The Pixar Way: 37 Quotes on Developing and Maintaining a Creative Company (fr... by Palo Alto Software
The Pixar Way: 37 Quotes on Developing and Maintaining a Creative Company (fr...The Pixar Way: 37 Quotes on Developing and Maintaining a Creative Company (fr...
The Pixar Way: 37 Quotes on Developing and Maintaining a Creative Company (fr...
Palo Alto Software88.4K views
9 Tips for a Work-free Vacation by Weekdone.com
9 Tips for a Work-free Vacation9 Tips for a Work-free Vacation
9 Tips for a Work-free Vacation
Weekdone.com7.2K views
How to Map Your Future by SlideShop.com
How to Map Your FutureHow to Map Your Future
How to Map Your Future
SlideShop.com275.1K views
Beyond Pride: Making Digital Marketing & SEO Authentically LGBTQ+ Inclusive -... by AccuraCast
Beyond Pride: Making Digital Marketing & SEO Authentically LGBTQ+ Inclusive -...Beyond Pride: Making Digital Marketing & SEO Authentically LGBTQ+ Inclusive -...
Beyond Pride: Making Digital Marketing & SEO Authentically LGBTQ+ Inclusive -...
AccuraCast3.4K views
Exploring ChatGPT for Effective Teaching and Learning.pptx by Stan Skrabut, Ed.D.
Exploring ChatGPT for Effective Teaching and Learning.pptxExploring ChatGPT for Effective Teaching and Learning.pptx
Exploring ChatGPT for Effective Teaching and Learning.pptx
Stan Skrabut, Ed.D.57.7K views
How to train your robot (with Deep Reinforcement Learning) by Lucas García, PhD
How to train your robot (with Deep Reinforcement Learning)How to train your robot (with Deep Reinforcement Learning)
How to train your robot (with Deep Reinforcement Learning)
Lucas García, PhD42.5K views
4 Strategies to Renew Your Career Passion by Daniel Goleman
4 Strategies to Renew Your Career Passion4 Strategies to Renew Your Career Passion
4 Strategies to Renew Your Career Passion
Daniel Goleman122K views
The Student's Guide to LinkedIn by LinkedIn
The Student's Guide to LinkedInThe Student's Guide to LinkedIn
The Student's Guide to LinkedIn
LinkedIn88.1K views
Different Roles in Machine Learning Career by Intellipaat
Different Roles in Machine Learning CareerDifferent Roles in Machine Learning Career
Different Roles in Machine Learning Career
Intellipaat12.4K views

Retour d'expérience - aggrégation de données en Ruby (Learnivore.com)

  • 1. Aggrégation de données avec Ruby Retour d’expérience Learnivore.com thibaut.barrere@gmail.com 1
  • 2. A quoi ressemble Learnivore ? 2
  • 3. Briques techniques • ThinkingSphinx + Sphinx • TinyTL • Hpricot • TagCleaner • Ramaze • UrlRewriter • ActiveRecord • ActsAsTaggableOnSteroids • Craken • WillPaginate • Thin 3
  • 4. Le modèle class Item < ActiveRecord::Base acts_as_taggable validates_presence_of :title, :url, :source, :summary, :thumbnail_img_tag, :pricing validates_uniqueness_of :url # our key define_index do indexes title indexes summary indexes source, :facet => true indexes tags.name, :as => :tag, :facet => true indexes pricing, :facet => true indexes language, :facet => true has update_date where "update_date <= curdate()" set_property :delta => true end end 4
  • 5. Processus d’import • DSL (TinyTL) • Tourne chaque heure • Pour chaque source, récupère un feed ou une page html • Normalise et conforme chaque item • Ajoute et conforme les tags • Upsert (update or insert) - clé = url cible 5
  • 6. Déclaration d’une source source(:peepcode) { fresh_get(PEEPCODE_HOST + '/products'). at('ul.products').search('li a'). map { |e| PEEPCODE_HOST + e['href'] } } 6
  • 7. Traitement spécifique (1/2) each_row(:bddcasts) { |row| # resource from rss row[:title] = grab(row[:content],'title') row[:update_date] = Date.parse(grab(row[:content],'published')) row[:url] = grab(row[:content], 'feedburner:origlink') row[:summary] = SimpleSanitizer.sanitize( CGI.unescapeHTML(grab(row[:content], 'content'))) # resource from page page = get(row[:url]) img_src = "http://bddcasts.com" + page.at("div.episode div.image img").attributes['src'] tags = grab_all(page, "div.episode div.details p.tags a", ', ') episode_css_classes = page.at("div.episode").attributes['class'] pricing = case episode_css_classes when /orange/; 'paid' when /green/; 'free' else raise "Bddcasts pricing guess failed: episode css class : '#{episode_css_classes}" end row[:thumbnail_img_tag] = "<img src='#{img_src}' height='90' style='border: 1px solid #aaa'/>" row[:pricing] = pricing row[:tag_list] = tags } 7
  • 8. Traitement spécifique (2/2) each_row(:thinkcode_tv) { |row| row[:title] = grab(row[:content],'title') row[:url] = grab(row[:content],'guid').gsub('//catalogo','/catalogo') row[:update_date] = Date.parse(grab(row[:content],'pubdate')) row[:summary] = SimpleSanitizer.sanitize(CGI.unescapeHTML(grab(row[:content],'description'))) img_src = Hpricot(CGI.unescapeHTML(grab(row[:content],'description'))). at('img').attributes['src'] row[:thumbnail_img_tag] = "<img height='90' src='#{THINKCODE_HOST}#{img_src}'/>" row[:pricing] = 'paid' row[:language] = 'italian' } 8
  • 9. Import / nettoyage des tags • tags du partenaires + tags delicious • conformation / nettoyage 9
  • 10. Screens (= tests data) assert_include %w(free paid), row[:pricing] assert_match(/https{0,1}:///, row[:url], :url) assert_not_nil row[:update_date] assert row[:update_date].is_a?(Date) ... 10
  • 11. Consommation • via le web => facettes + full-text • RSS => sort by fraîcheur desc (feedburner MyBrand) • Twitter => semi-automatique via bit.ly 11
  • 12. Conclusions • Contacter les partenaires = bien • ThinkingSphinx = bien • Code = une petite portion du travail • Toute data doit généralement être nettoyée avant consommation 12