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

Extraindo dados da internet usando Scrapy

Extraindo dados da internet usando Scrapy

Apresentando as principais características do Scrapy, um framework open-source 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.

Palestra apresentada no Caipyra 2018 (http://caipyra.python.org.br/).

Avatar for Renne Rocha

Renne Rocha

June 10, 2018
Tweet

More Decks by Renne Rocha

Other Decks in Programming

Transcript

  1. Ge ng informa on off the Internet is like taking

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

    estruturadas (tipicamente páginas web)
  3. 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
  4. https://scrapy.org/ An open source and collaborative framework for extracting the

    data you need from websites. In a fast, simple, yet extensible way.
  5. import requests from bs4 import BeautifulSoup response = requests.get('http://caipyra.python.org.br/') soup

    = BeautifulSoup(response.text, 'html.parser') palestras = soup.find('section', id='palestras') titulos = [ palestra.get_text() for palestra in palestras.find_all('h4') ]
  6. 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?
  7. # 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
  8. # 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
  9. $ scrapy runspider sp_jundiai.py ... 2018-06-05 22:58:28 [scrapy.utils.log] INFO: Scrapy

    1.5.0 started 2018-06-05 22:58:28 [scrapy.core.engine] INFO: Spider opened 2018-06-05 22:58:30 [scrapy.core.engine] DEBUG: Crawled (200) <GE 2018-06-05 22:58:30 [sp_jundiai] INFO: Received content from http 2018-06-05 22:58:30 [scrapy.core.engine] INFO: Closing spider (fi 2018-06-05 22:58:30 [scrapy.statscollectors] INFO: Dumping Scrapy 2018-06-05 22:58:30 [scrapy.core.engine] INFO: Spider closed (fin ...
  10. $ 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">'>, ...]
  11. $ 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.extract() 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>'
  12. # 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
  13. # 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)').extract_first() diario_data = diario.xpath( './/span[2]/text()').extract_first() https://github.com/okfn-brasil/diario-o cial
  14. # 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)').extract_first() diario_data = diario.xpath( './/span[2]/text()').extract_first() yield { 'url': diario_url, 'data': diario_data } https://github.com/okfn-brasil/diario-o cial
  15. # 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)').extract_first() yield Request( url=url, callback=self.parse ) https://github.com/okfn-brasil/diario-o cial
  16. Item Exporters Uma vez que você obteve seus items, você

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

    vai querer persisti-los ou exportá-los para utilizar esses dados em outra aplicação. O Scrapy fornece um conjunto de Item Exportesr para diferentes formatos como CSV, JSON ou JL. $ 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
  18. Páginas com JavaScript Conteúdo dinâmico Single Page Applications casos simples:

    emular requests AJAX casos complexos: Splash (https://github.com/scrapinghub/splash)
  19. import json import scrapy from w3lib.url import add_or_replace_parameter 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') }
  20. 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)
  21. Medidas an -bots Bloqueio de IP Número de requests por

    segundo User-Agent Cookies de sessão Localização