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

Obtendo dados estruturados da Internet usando Scrapy

Renne Rocha
September 22, 2018

Obtendo dados estruturados da Internet usando Scrapy

Palestra apresentada no ABC-Dev 2018:
http://2018.abcdevelopers.org/

Apresentando as principais características do Scrapy, framework open-source em Python que facilita o desenvolvimento de aplicações para navegação e extração de dados estruturados em páginas web, através de exemplos práticos de situações reais.

Renne Rocha

September 22, 2018
Tweet

More Decks by Renne Rocha

Other Decks in Programming

Transcript

  1. Renne Rocha Python Developer na Scrapinghub Laboratório Hacker de Campinas

    Grupy-Campinas @rennerocha (Twitter, Instagram, Github, Bitbucket) [email protected]
  2. Ge ng informa on off the Internet is like taking

    a drink from a fire hydrant. Mitchell Kapor
  3. Web Scraping Extrair dados estruturados de fontes de dados não

    estruturadas (tipicamente páginas web)
  4. Casos de Uso 1. Pesquisas com dados governamentais 2. Monitorar

    o que estão falando do meu produto 3. Monitorar os produtos dos concorrentes 4. Ofertas de emprego, imóveis, bens de consumo 5. Análise de redes sociais
  5. import requests from bs4 import BeautifulSoup response = requests.get('https://2018.abcdevelopers.org/') soup

    = BeautifulSoup(response.text, 'html.parser') speakers = soup.find_all('article', {'class': 'speaker'}) speaker_names = [ speaker.find('h4').get_text() for speaker in speakers ] print(speaker_names)
  6. (.venv) renne@capivara:code$ python3 abcdev.py ['Larissa Abreu', 'Renne Rocha', 'Pamela Iupi

    Peixinho', 'William Grasel', 'Marina Limeira', 'Caique Mitsuoka', 'Carol Soares', 'Ivan Amaro', 'Carolina Pascale', 'Bruno Rocha', 'Thabata Marchi', 'Flavio Milani', 'Daniela Rocha', 'James William Pontes Miranda', 'Andreza Rocha', 'Mateus Malaquias', 'Alda Rocha', 'Lucas J Silva', 'Livia Gabos', 'Matheus Hernandes', 'Regina Helena Macedo', 'Maicon Peixinho', 'Patricia Morimoto', 'Fábio Serrão', 'Carla Vieira', 'Ciro Valente Filho']
  7. E se es vessemos processando? Um e-commerce com milhares de

    produtos? Um site governamental com dados de diversos anos? Um site de notícias com dezenas de categorias? Precisássemos navegar por vários links para agrupar as informações desejadas?
  8. https://scrapy.org/ Um framework em Python de código aberto e colaborativo

    para extrair os dados que você precisa de páginas na internet, de um modo fácil, simples e extensível.
  9. Diário Oficial Serenata de Amor Extrair as informações dos diários

    o ciais dos 100 maiores municípios do país https://github.com/okfn-brasil/diario-o cial
  10. # sp_jundiai.py import scrapy class SpJundiaiDiarioOficialSpider(scrapy.Spider): name = 'sp_jundiai' def

    start_requests(self): url = 'https://imprensaoficial.jundiai.sp.gov.br/' yield scrapy.Request( url=url, callback=self.parse, ) https://github.com/okfn-brasil/diario-o cial
  11. # sp_jundiai.py import scrapy class SpJundiaiDiarioOficialSpider(scrapy.Spider): name = 'sp_jundiai' def

    start_requests(self): url = 'https://imprensaoficial.jundiai.sp.gov.br/' yield scrapy.Request( url=url, callback=self.parse, ) def parse(self, response): self.logger.info( 'Received content from {}'.format( response.url)) https://github.com/okfn-brasil/diario-o cial
  12. Executando meu spider $ scrapy runspider sp_jundiai.py ...[scrapy.utils.log] INFO: Scrapy

    1.5.0 started (bot: scrapybot) ...[scrapy.core.engine] INFO: Spider opened...[scrapy.core.engine ...[sp_jundiai] INFO: Received content from https://imprensaofici ...[scrapy.core.engine] INFO: Closing spider (finished) ...[scrapy.statscollectors] INFO: Dumping Scrapy stats: ...[scrapy.core.engine] INFO: Spider closed (finished)
  13. $ scrapy shell https://imprensaoficial.jundiai.sp.gov.br/ In [1]: response.css('#lista-edicoes li.edicao-atual') Out[1]: [<Selector

    data='<li class="edicao-atual" id="page-1">'>, <Selector data='<li class="edicao-atual" id="page-2">'>, <Selector data='<li class="edicao-atual" id="page-3">'>, ...]
  14. $ scrapy shell https://imprensaoficial.jundiai.sp.gov.br/ In [1]: response.css('#lista-edicoes li.edicao-atual') Out[1]: [<Selector

    data='<li class="edicao-atual" id="page-1">'>, <Selector data='<li class="edicao-atual" id="page-2">'>, <Selector data='<li class="edicao-atual" id="page-3">'>, ...] In [2]: diario = response.css( ...: '#lista-edicoes li.edicao-atual')[0] In [3]: diario.getall() Out[3]: '<li class="edicao-atual" id="page-7051"> \n\n\t\n\t<a href="https://imprensaoficial.j undiai.sp.gov.br/edicao-extra-4407/" (...) </li>'
  15. # sp_jundiai.py def parse(self, response): diarios = response.css('#lista-edicoes li.edicao-atual') for

    diario in diarios: pass https://github.com/okfn-brasil/diario-o cial
  16. # sp_jundiai.py def parse(self, response): diarios = response.css('#lista-edicoes li.edicao-atual') for

    diario in diarios: diario_url = diario.css('a::attr(href)').get() diario_data = diario.xpath('.//span[2]/text()').get() https://github.com/okfn-brasil/diario-o cial
  17. # sp_jundiai.py def parse(self, response): diarios = response.css('#lista-edicoes li.edicao-atual') for

    diario in diarios: diario_url = diario.css('a::attr(href)').get() diario_data = diario.xpath('.//span[2]/text()').get() yield { 'url': diario_url, 'data': diario_data } https://github.com/okfn-brasil/diario-o cial
  18. # sp_jundiai.py def parse(self, response): diarios = response.css('#lista-edicoes li.edicao-atual') for

    diario in diarios: (...) prox_paginas = response.css('div.paginacao a.inactive') for pagina in prox_paginas: url = pagina.css('*::attr(href)').get() yield Request( url=url, callback=self.parse ) https://github.com/okfn-brasil/diario-o cial
  19. Item Exporters Uma vez que você obteve seus items, você

    vai querer persistí-los ou exportá-los para utilizar esses dados em outra aplicação. O Scrapy fornece um conjunto de Item Exporters para diferentes formatos como CSV, JSON, JL ou XML.
  20. Item Exporters Uma vez que você obteve seus items, você

    vai querer persistí-los ou exportá-los para utilizar esses dados em outra aplicação. O Scrapy fornece um conjunto de Item Exporters para diferentes formatos como CSV, JSON, JL ou XML. $ scrapy runspider sp_jundiai.py -o sp_jundiai.csv $ scrapy runspider sp_jundiai.py -o sp_jundiai.json $ scrapy runspider sp_jundiai.py -o sp_jundiai.jl
  21. Item Exporters Uma vez que você obteve seus items, você

    vai querer persistí-los ou exportá-los para utilizar esses dados em outra aplicação. O Scrapy fornece um conjunto de Item Exporters para diferentes formatos como CSV, JSON, JL ou XML. Mas é muito simples desenvolver o seu próprio exportador para outros formatos.
  22. import scrapy class ABCDevSpider(scrapy.Spider): name = 'abcdev' def start_requests(self): urls

    = [ 'https://2018.abcdevelopers.org' ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): speaker_names = response.css( 'article h4::text').getall() yield { 'speakers': speaker_names }
  23. Páginas com JavaScript Conteúdo dinâmico Single Page Applications casos simples:

    emular requests AJAX casos complexos: Splash (https://github.com/scrapinghub/splash) Headless Browser
  24. import json import scrapy class ToScrapeScroll(scrapy.Spider): name = 'toscrape' start_urls

    = [ 'http://quotes.toscrape.com/api/quotes?page=1' ] def parse(self, response): data = json.loads(response.body) for quote in data.get('quotes'): yield { 'text': quote.get('text'), 'author': quote.get('name') }
  25. import json import scrapy from w3lib.url import add_or_replace_parameter class ToScrapeScroll(scrapy.Spider):

    # (...) def parse(self, response): data = json.loads(response.body) for quote in data.get('quotes'): (...) if data.get('has_next'): current_page = data.get('page') next_page_url = add_or_replace_parameter( response.url, 'page', current_page + 1) yield Request(next_page_url)