Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Marcel dos Santos

November 17, 2018
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

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

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

    que dificilmente será repetida
  3. os dados são organizados e armazenados em um banco de

    dados ou em arquivos CSV, XML ou JSON
  4. a extração de dados é feita por robôs que podem

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

    evitar qualquer comportamento indesejado no serviço terceiro
  6. é uma maneira de rodar o Chrome em um ambiente

    headless, ou seja, sem a interface de usuário
  7. é possível realizar o debug remoto de uma instância headless

    utilizando o DevTools Protocol a partir de outro navegador
  8. o uso via linha de comando é bastante flexível mas,

    para casos mais elaborados, recomenda-se um biblioteca de alto nível
  9. é uma biblioteca para Node que fornece uma API de

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

    ser configurado para ser executado de forma non-headless
  11. ao instalar o Puppeteer é feito o download da versão

    mais recente do Chromium para garantir o funcionamento com a API
  12. o puppeteer-core é uma versão leve para executar um browser

    já instalado ou para se conectar em um browser remoto
  13. 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
  14. 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(); })();
  15. 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(); })();
  16. 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(); })();
  17. uma biblioteca construída para o estilo de programação funcional que

    facilita a utilização de pipelines e dados imutáveis
  18. !// 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
  19. !// 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
  20. !// 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
  21. const puppeteer = require('puppeteer'); (async () !=> { !// 1.

    open a headless chrome instance const browser = await puppeteer.launch({ headless: false, devtools: true }); !// !!... })();
  22. 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); !// !!... })();
  23. !// 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; });
  24. (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(); })();