Web Scraping com Chrome Headless, Puppeteer e Ramda

Web Scraping com Chrome Headless, Puppeteer e Ramda

Web scraping é uma técnica de extração de dados de sites da web. Ela é bastante útil pois permite a obtenção de dados de forma automatizada de sites que não fornecem uma API oficial. Nesta palestra veremos como podemos utilizar o Chrome Headless (uma forma de executar o Chrome de maneira automatizada e sem interface gráfica), o Puppeter (uma biblioteca de automatização do Chrome) e a Ramda.js (uma biblioteca de JavaScript com foco em programação funcional) para realizar a tarefa de extração de dados de sites de forma automatizada.

52711e2157a6fed933b0361cc06a6953?s=128

Marcel dos Santos

November 17, 2018
Tweet

Transcript

  1. Marcel Gonçalves dos Santos @marcelgsantos web scraping e Ramda chrome

    headless com Puppeteer ,
  2. pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

  3. None
  4. @femugsp sp.femug.com #dfmcz18 #gdgmaceio #puppeteer

  5. @phpsp phpsp.org.br

  6. Quem nunca precisou obter informações de sites na web?

  7. None
  8. None
  9. None
  10. None
  11. E como resolver este problema?

  12. None
  13. Hmmm… O que acharam dessa solução?

  14. copiar e colar informações de um site manualmente em um

    documento de texto ou planilha não parece ser a melhor solução!
  15. a não ser que a tarefa seja realmente simples e

    que dificilmente será repetida
  16. essa abordagem pode gerar um trabalho excessivo e erros no

    processo de coleta de dados
  17. E como resolver este problema de uma forma melhor?

  18. fazer a automação da coleta de dados

  19. None
  20. Web scraping

  21. técnica que permite extrair dados de um site ou aplicação

    web de forma automatizada
  22. os dados são organizados e armazenados em um banco de

    dados ou em arquivos CSV, XML ou JSON
  23. o conceito também é conhecido como raspagem de dados

  24. é utilizado em aplicações legadas ou que não possuem uma

    API
  25. a extração de dados é feita por robôs que podem

    ser implementados em qualquer tecnologia
  26. a técnica deve ser utilizada com cautela de modo a

    evitar qualquer comportamento indesejado no serviço terceiro
  27. o conceito difere do termo web crawling

  28. Chrome Headless

  29. None
  30. é uma maneira de rodar o Chrome em um ambiente

    headless, ou seja, sem a interface de usuário
  31. permite a utilização de funcionalidades modernas da plataforma web na

    linha de comando
  32. recomendado para automação de testes e automações em geral

  33. pode ser executado através de comandos simples

  34. chrome !--headless https:!//!!www.google.com.br

  35. chrome !--headless https:!//!!www.google.com.br

  36. não funcionou?!

  37. o comando deve ser apontado para a instalação do Chrome

    no computador
  38. alias chrome="/Applications/Google\ Chrome.app/ Contents/MacOS/Google\ Chrome"

  39. chrome !--headless https:!//!!www.google.com.br

  40. não viu nada?!

  41. é porque é headless…

  42. None
  43. ahhh… deve-se utilizar a flag no Windows devido um bug

    !--disable-gpu
  44. o Chrome Headless pode ser utilizado para diversas tarefas

  45. chrome !--headless !--dump-dom https:!//!!www.google.com.br Imprimir o DOM

  46. chrome !--headless !--print-to-pdf https:!//!!www.google.com.br Gerar PDF

  47. chrome !--headless !--screenshot https:!//!!www.google.com.br Tirar screenshot

  48. chrome \
 !--headless \ 
 !--screenshot \
 !--window-size=1280,1696 \
 https:!//!!www.google.com.br

    Tirar screenshot (2)
  49. chrome \
 !--headless \ 
 !--screenshot \
 !--window-size=412,732 \
 https:!//!!www.google.com.br

    Tirar screenshot (3)
  50. é possível realizar o debug remoto de uma instância headless

    utilizando o DevTools Protocol a partir de outro navegador
  51. chrome \
 !--headless \
 !--remote-debugging-port=9222 \
 http:!//!!www.google.com.br Debug remoto

  52. None
  53. é possível também utilizar o Selenium junto com o Chrome

    Headless
  54. o uso via linha de comando é bastante flexível mas,

    para casos mais elaborados, recomenda-se um biblioteca de alto nível
  55. Puppeteer

  56. é uma biblioteca para Node que fornece uma API de

    alto nível para controlar o Chrome ou Chromium através do DevTools Protocol
  57. o Puppeteer roda de forma headless por padrão, mas pode

    ser configurado para ser executado de forma non-headless
  58. a instalação pode ser feita de forma bem simples

  59. npm install puppeteer

  60. ao instalar o Puppeteer é feito o download da versão

    mais recente do Chromium para garantir o funcionamento com a API
  61. npm install puppeteer-core

  62. o puppeteer-core é uma versão do Puppeteer que não faz

    o download do Chromium por padrão
  63. o puppeteer-core é uma versão leve para executar um browser

    já instalado ou para se conectar em um browser remoto
  64. o Puppeteer requer o Node versão 6.4.0 ou superior e,

    para utilizar async/await, a versão 7.6.0 ou superior
  65. o Puppeteer é apoiado sobre o Chrome Headless e o

    Chrome DevTools Protocol
  66. Pirâmide do Puppeteer Chrome Headless Chrome DevTools Protocol Puppeteer seu

    script
  67. ele permite realizar inúmeros tipos de tarefas

  68. const puppeteer = require('puppeteer'); !// 01 - launch headless chrome

    instance !// and get browser's version (async () !=> { const browser = await puppeteer.launch(); console.log(await browser.version()); await browser.close(); })();
  69. const puppeteer = require('puppeteer'); !// 02 - launch headless chrome

    instance, create new page, !// navigate to google.com.br and get pages' title (async () !=> { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https:!//google.com.br/'); console.log(await page.title()); await browser.close(); })();
  70. const puppeteer = require('puppeteer'); !// 03 - navigate to google.com.br,

    type a search term, !// wait for the result and take a screenshot (async () !=> { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https:!//!!www.google.com.br/'); await page.focus('[name="q"]'); await page.keyboard.type('devfest maceió'); await page.waitFor(2000); await page.screenshot({ path: 'devfest-maceio-search.png' }); await browser.close(); })();
  71. Biblioteca Ramda

  72. uma biblioteca construída para o estilo de programação funcional que

    facilita a utilização de pipelines e dados imutáveis
  73. possui foco no estilo puramente funcional

  74. todas as funções do Ramda são auto-curried

  75. os argumentos das funções do Ramda são organizados de forma

    a facilitar a utilização de currying
  76. Caso de Uso Rápido somar os preços dos produtos de

    um carrinho de compras
  77. !// shopping cart const cart = [ {id: 1, product:

    'iPhone', price: 499}, {id: 2, product: 'Kindle', price: 179}, {id: 3, product: 'Macbook Pro', price: 1199}, ]; !// get prices from shopping cart and sum them
 !// using intermediate values const cartPrices = R.map(item !=> item.price, cart); const cartSum = R.sum(cartPrices); console.log(cartSum); !// 1877 realiza o mapeamento da lista de produtos (objetos) para uma lista de preços (números) faz a somatória da lista de números e retorna o total Passo 1
  78. !// shopping cart const cart = [ {id: 1, product:

    'iPhone', price: 499}, {id: 2, product: 'Kindle', price: 179}, {id: 3, product: 'Macbook Pro', price: 1199}, ]; !// get prices from shopping cart and sum them
 !// using function composition const totalCart = R.compose( R.sum, R.map(item !=> item.price), ); console.log(totalCart(cart)); !// 1877 cria uma nova função a partir da composição de funções e elimina valores intermediários Passo 2 aplicação parcial da função map a composição é feita da direita para a esquerda
  79. !// shopping cart const cart = [ {id: 1, product:

    'iPhone', price: 499}, {id: 2, product: 'Kindle', price: 179}, {id: 3, product: 'Macbook Pro', price: 1199}, ]; !// get prices from shopping cart and sum them !// using function composition with pipe const totalCart = R.pipe( R.map(item !=> item.price), R.sum, ); console.log(totalCart(cart)); !// 1877 Passo 3 o pipe de funções é feito da esquerda para a direita e facilita a leitura do código
  80. Caso de uso Scraper das palestras do DevFest Maceió 2018

  81. é uma single page application feita em Angular com a

    lista de palestras do evento
  82. None
  83. const puppeteer = require('puppeteer'); (async () !=> { !// 1.

    open a headless chrome instance const browser = await puppeteer.launch({ headless: false, devtools: true }); !// !!... })();
  84. const puppeteer = require('puppeteer'); (async () !=> { !// 1.

    open a headless chrome instance !// !!... !// 2. create a new page and navigate to devfest schedule const page = await browser.newPage(); await page.goto('https:!//devfest.gdgmaceio.org/programacao'); await page.waitFor(5000); !// !!... })();
  85. !// 3. get the number of stores from the report

    const list = await page.evaluate(() !=> { !// 3.1. list of time slots let listOfSlots = document.querySelectorAll('.turn-list > .item’); let talks = []; !// 3.2. iterate over each time slot listOfSlots.forEach(slot !=> { let time = slot.querySelector('.hour').innerText; !// 3.3. list of talks let listOfTalks = slot.querySelectorAll('.events-list > .item'); !// 3.4. iterate over each talk listOfTalks.forEach(talk !=> { let location = talk.querySelector('.location').innerText; let title = talk.querySelector('.title').innerText; let speaker = talk.querySelector('.speaker .name').innerText; let position = talk.querySelector('.speaker .description').innerText; let category = talk.querySelector('.category').innerText; talks.push({location, time, title, speaker, position, category}); }); }); return talks; });
  86. (async () !=> { !// 1. open a headless chrome

    instance const browser = await puppeteer.launch({ headless: false, devtools: true }); !// 2. create a new page and navigate to devfest schedule const page = await browser.newPage(); await page.goto('https:!//devfest.gdgmaceio.org/programacao'); await page.waitFor(5000); !// !!... !// 4. show scraped data console.log(list); !// 5. close browser instance await browser.close(); })();
  87. None
  88. Conclusão

  89. automatize o máximo de tarefas que puder!

  90. Referências

  91. bit.ly/palestra-puppeteer-referencias

  92. Avalie!

  93. bit.ly/palestra-puppeteer-avalie

  94. @marcelgsantos speakerdeck.com/marcelgsantos Obrigado. Perguntas?