One place for hosting & domains

      September 2018

      Como Fazer Scraping em Páginas Web com Beautiful Soup and Python 3


      Introdução

      Muitos projetos de análise de dados, big data, e aprendizado de máquina exigem o scraping de websites para coletar os dados com os quais você irá trabalhar. A linguagem de programação Python é largamente utilizada na comunidade de data science, e, portanto, tem um ecossistema de módulos e ferramentas que você pode usar em seus próprios projetos. Neste tutorial estaremos nos concentrando no módulo Beautiful Soup.

      Beautiful Soup, uma alusão à música Mock Turtle’s encontrada no Capítulo 10 de Alice no País das Maravilhas, de Lewis Carroll, é uma biblioteca do Python que permite um retorno rápido em projetos de web scraping. Atualmente disponível como Beautiful Soup 4 e compatível tanto com Python 2.7 quanto com Python 3, o Beautiful Soup cria uma árvore de análise a partir de documentos HTML e XML analisados (incluindo documentos com tags não fechadas ou tag soup e outras marcações malformadas).

      Neste tutorial, iremos coletar e analisar uma página web de forma a pegar dados textuais e gravar as informações que tivermos recolhido em um arquivo CSV.

      Pré-requisitos

      Antes de trabalhar com este tutorial, você deve ter um ambiente de programação Python local ou baseado em servidor configurado em sua máquina.

      Você deve ter os módulos Requests e Beautiful Soup instalados, o que pode ser conseguido seguindo o nosso tutorial “How To Work with Web Data Using Requests and Beautiful Soup with Python 3.” Também seria útil ter familiaridade no trabalho com esses módulos.

      Adicionalmente, uma vez que vamos trabalhar com dados extraídos da web, você deve estar confortável com a estrutura e a marcação de tags HTML.

      Entendendo os Dados

      Neste tutorial, iremos trabalhar com dados do site oficial do National Gallery of Art nos Estados Unidos. O National Gallery é um museu de arte localizado no National Mall em Washington, D.C. Ele possui mais de 120.000 peças datadas desde o Renascimento aos dias atuais feitas por mais de 13.000 artistas.

      Gostaríamos de pesquisar o Índice de Artistas, que, no momento da atualização deste tutorial, estava disponível via Internet Archive’s Wayback Machine na seguinte URL:

      https://web.archive.org/web/20170131230332/https://www.nga.gov/collection/an.shtm

      Nota: A longa URL acima é devido a este site ter sido arquivado pelo Internet Archive.

      O Internet Archive é uma biblioteca digital sem fins lucrativos que fornece acesso livre a sites da internet e outras mídias digitais. A organização tira instantâneos de websites para preservar a história dos sites, e atualmente, podemos acessar uma versão mais antiga do site da National Gallery que estava disponível quando este tutorial foi escrito pela primeira vez. O Internet Archive é uma boa ferramenta para se ter em mente sempre que estiver fazendo qualquer tipo de scraping de dados históricos, incluindo a comparação entre iterações do mesmo site e dados disponíveis.

      Logo abaixo do cabeçalho do Internet Archive, você verá uma página como esta:

      Como estamos fazendo esse projeto para aprender sobre o web scraping com o Beautiful Soup, não precisamos extrair muitos dados do site, por isso, vamos limitar o escopo dos dados do artista que estamos tentando capturar. Vamos, portanto, escolher uma letra — em nosso exemplo escolheremos a letra Z — e veremos uma página como esta:

      Na página acima, vemos que o primeiro artista listado no momento da escrita é Zabaglia, Niccola, o que é uma boa coisa a se notar quando começamos a extrair dados. Começaremos trabalhando com essa primeira página, com a seguinte URL para a letra Z:

      https://web.archive.org/web/20121007172955/http://www.nga.gov/collection/anZ1.htm

      É importante observar, para análise posterior, quantas páginas existem para a letra que você está escolhendo listar, o que você pode descobrir clicando na última página de artistas. Nesse caso, existe um total de 4 páginas, e o último artista listado no momento da escrita é Zykmund, Václav. A última página de artistas com Z tem a seguinte URL:

      https://web.archive.org/web/20121010201041/http://www.nga.gov/collection/anZ4.htm

      Contudo, você também pode acessar a página acima usando a mesma string numérica do Internet Archive da primeira página:

      https://web.archive.org/web/20121007172955/http://www.nga.gov/collection/anZ4.htm

      É importante observar isso, pois mais adiante neste tutorial faremos a iteração dessas páginas.

      Para começar a se familiarizar com a forma que essa página web é configurada, você pode dar uma olhada em seu DOM, que o ajudará a entender como o HTML é estruturado. Para inspecionar o DOM, você pode abrir Ferramentas do Desenvolvedor do seu navegador.

      Importando as Bibliotecas

      Para iniciar nosso projeto de codificação, vamos ativar nosso ambiente de programação. Certifique-se de que você está no diretório onde o seu ambiente de desenvolvimento está localizado, e execute o seguinte comando.

      Com o nosso ambiente de programação ativado, vamos criar um novo arquivo, com o nano por exemplo. Você pode nomear seu arquivo como quiser, vamos chamá-lo de nga_z_artists.py nesse tutorial.

      Nesse arquivo, podemos começar a importar as bibliotecas que iremos utilizar — Requests e Beautiful Soup.

      A biblioteca Requests lhe permite fazer uso do HTTP dentro dos seus programas Python em um formato legível, e o módulo Beautiful Soup é projetado para fazer web scraping rapidamente.

      Vamos importar tanto o Requests quanto o Beautiful Soup com a declaração import. Para o Beautiful Soup iremos importá-lo do bs4, o pacote no qual o Beautiful Soup 4 é encontrado.

      nga_z_artists.py

      
      # Importar bibliotecas
      import requests
      from bs4 import BeautifulSoup
      

      Com os módulos Requests e Beautiful Soup importados, podemos passar a trabalhar para coletar primeiro uma página e analisá-la.

      Coletando e Analisando uma Página Web

      O próximo passo que precisaremos fazer é coletar a URL da primeira página web com o Requests. Iremos atribuir a URL da primeira página à variável page usando o método requests.get().

      nga_z_artists.py

      
      import requests
      from bs4 import BeautifulSoup
      
      
      # Coletar a primeira página da lista de artistas
      page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')
      
      

      Nota: Como a URL é longa, o código acima, bem como todo este tutorial não passarão no PEP 8 E501, que sinaliza linhas com mais de 79 caracteres. Você pode querer atribuir a URL a uma variável para tornar o código mais legível nas versões finais. O código neste tutorial é para fins de demonstração e permitirá que você troque URLs mais curtas como parte de seus próprios projetos.

      Agora iremos criar o objeto BeautifulSoup, ou uma árvore de análise. Esse objeto utiliza como argumento o documento page.text do Requests (o conteúdo da resposta do servidor) e então o analisa através do html.parser interno do Python.

      nga_z_artists.py

      
      import requests
      from bs4 import BeautifulSoup
      
      
      page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')
      
      # Criar o objeto BeautifulSoup
      soup = BeautifulSoup(page.text, 'html.parser')
      
      

      Com a nossa página coletada, analisada e configurada como um objeto BeautifulSoup, podemos passar para a coleta dos dados que gostaríamos.

      Pegando Texto de uma Página Web

      Para este projeto, iremos coletar nomes de artistas e os links relevantes disponíveis no website. Você pode querer coletar dados diferentes, tais como a nacionalidade dos artistas e datas. Para quaisquer dados que você queira coletar, você precisa descobrir como ele é descrito pelo DOM da página web.

      Para fazer isso, no seu navegador web, clique com o botão direito — ou CTRL + clique no macOS — no nome do primeiro artista, Zabaglia, Niccola. Dentro do menu de contexto que aparece, você deve ver um item de menu semelhante ao Inspecionar Elemento (Firefox) ou Inspecionar (Chrome).

      Após clicar no item de menu relevante Inspecionar, as ferramentas para desenvolvedores web devem aparecer no seu navegador. Queremos procurar pela classe e as tags associadas aos nomes dos artistas nessa lista.

      Veremos primeiro que a tabela de nomes está dentro de tags <div> onde class="BodyText". É importante observar isso, para que só procuremos texto nessa seção da página web. Também notamos que o nome Zabaglia, Niccola está em uma tag de link, já que o nome faz referência a uma página web que descreve o artista. Então, vamos querer referenciar a tag <a> para links. O nome de cada artista é uma referência a um link.

      Para fazer isso, iremos utilizar os métodos find() e find_all() do Beautiful Soup a fim de extrair o texto dos nomes dos artistas do BodyText <div>.

      nga_z_artists.py

      
      import requests
      from bs4 import BeautifulSoup
      
      
      # Coletar e analisar a primeira página
      page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')
      soup = BeautifulSoup(page.text, 'html.parser')
      
      # Pegar todo o texto da div BodyText
      artist_name_list = soup.find(class_='BodyText')
      
      # Pegar o texto de todas as instâncias da tag <a> dentro da div BodyText
      artist_name_list_items = artist_name_list.find_all('a')
      
      

      A seguir, na parte inferior do nosso arquivo de programa, criaremos um loop for para iterar todos os nomes de artistas que acabamos de colocar na variável artist_name_list_items.

      Vamos imprimir esses nomes com o método prettify() para transformar a árvore de análise do Beautiful Soup em uma string Unicode bem formatada.

      nga_z_artists.py

      
      ...
      artist_name_list = soup.find(class_='BodyText')
      artist_name_list_items = artist_name_list.find_all('a')
      
      # Criar loop para imprimir todos os nomes de artistas
      for artist_name in artist_name_list_items:
          print(artist_name.prettify())
      
      

      Vamos executar o programa como ele está até agora:

      Assim que fizermos isso, receberemos a seguinte saída:

      Output

      <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11630"> Zabaglia, Niccola </a> ... <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=3427"> Zao Wou-Ki </a> <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/collection/anZ2.htm"> Zas-Zie </a> <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/collection/anZ3.htm"> Zie-Zor </a> <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/collection/anZ4.htm"> <strong> next <br/> page </strong> </a>

      O que vemos na saída nesse ponto é o texto completo e as tags relativas a todos os nomes de artistas dentro de tags <a> encontradas na tag <div class="BodyText"> na primeira página, bem como algum texto de link adicional na parte inferior. Como não queremos essa informação extra, vamos trabalhar para remover isso na próxima seção.

      Removendo Dados Supérfluos

      Até agora, conseguimos coletar todos os dados de texto do link dentro de uma seção <div> da nossa página web. No entanto, não queremos ter os links inferiores que não fazem referência aos nomes dos artistas. Por isso, vamos trabalhar para remover essa parte.

      Para remover os links inferiores da página, vamos clicar novamente com o botão direito e Inspecionar o DOM. Veremos que os links na parte inferior da seção <div class="BodyText"> estão contidos em uma tabela HTML: <table class="AlphaNav">:

      Podemos, portanto, usar o Beautiful Soup para encontrar a classe AlphaNav e usar o método decompose() para remover uma tag da árvore de análise e depois destruí-la juntamente com seu conteúdo.

      Usaremos a variável last_links para fazer referência a esses links inferiores e adicioná-los ao arquivo do programa:

      nga_z_artists.py

      
      import requests
      from bs4 import BeautifulSoup
      
      
      page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')
      
      soup = BeautifulSoup(page.text, 'html.parser')
      
      # Remover links inferiores
      last_links = soup.find(class_='AlphaNav')
      last_links.decompose()
      
      artist_name_list = soup.find(class_='BodyText')
      artist_name_list_items = artist_name_list.find_all('a')
      
      for artist_name in artist_name_list_items:
          print(artist_name.prettify())
      
      

      Agora, quando executarmos o programa com o comando python nga_z_artist.py, receberemos a seguinte saída:

      Output

      <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11630"> Zabaglia, Niccola </a> <a href="http://www.digitalocean.com/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=34202"> Zaccone, Fabian </a> ... <a href="http://www.digitalocean.com/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=11631"> Zanotti, Giampietro </a> <a href="http://www.digitalocean.com/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=3427"> Zao Wou-Ki </a>

      Nesse ponto, vemos que a saída não inclui mais os links na parte inferior da página web e agora exibe apenas os links associados aos nomes dos artistas.

      Até agora, focamos especificamente os links com os nomes dos artistas, mas temos os dados de tags extras que realmente não queremos. Vamos remover isso na próxima seção.

      Pegando o Conteúdo de uma Tag

      Para acessar apenas os nomes reais dos artistas, queremos focar no conteúdo das tags <a> em vez de imprimir toda a tag de link.

      Podemos fazer isso com o .contents do Beautiful Soup, que irá retornar a tag filha com um tipo de dados lista do Python.

      Vamos revisar o loop for para que, em vez de imprimir o link inteiro e sua tag, façamos a impressão da lista das filhas (ou seja, os nomes completos dos artistas).

      nga_z_artists.py

      
      import requests
      from bs4 import BeautifulSoup
      
      
      page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')
      
      soup = BeautifulSoup(page.text, 'html.parser')
      
      last_links = soup.find(class_='AlphaNav')
      last_links.decompose()
      
      artist_name_list = soup.find(class_='BodyText')
      artist_name_list_items = artist_name_list.find_all('a')
      
      # Usar .contents para pegar as tags <a> filhas
      for artist_name in artist_name_list_items:
          names = artist_name.contents[0]
          print(names)
      
      

      Note que estamos iterando na lista acima chamando o número do índice de cada item.

      Podemos executar o programa com o comando python para ver a seguinte saída:

      Output

      Zabaglia, Niccola Zaccone, Fabian Zadkine, Ossip ... Zanini-Viola, Giuseppe Zanotti, Giampietro Zao Wou-Ki

      Recebemos de volta uma lista de todos os nomes dos artistas disponíveis na primeira página da letra Z.

      Mas, e se quisermos também capturar as URLs associadas a esses artistas? Podemos extrair URLs encontradas dentro de tags <a> utilizando o método get('href') do Beautiful Soup.

      A partir da saída dos links acima, sabemos que a URL inteira não está sendo capturada, então vamos concatenar a string do link com o início da string da URL (nesse caso https://web.archive.org/).

      Estas linhas também serão adicionadas ao loop for:

      nga_z_artists.py

      
      ...
      for artist_name in artist_name_list_items:
          names = artist_name.contents[0]
          links = 'https://web.archive.org' + artist_name.get('href')
          print(names)
          print(links)
      
      

      Quando executamos o programa acima, receberemos tanto os nomes dos artistas quanto as URLs para os links que nos dizem mais sobre eles:

      Output

      Zabaglia, Niccola https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11630 Zaccone, Fabian https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=34202 ... Zanotti, Giampietro https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11631 Zao Wou-Ki https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=3427

      Embora estejamos agora recebendo informações do site, ele está apenas imprimindo em nossa janela de terminal. Em vez disso, vamos capturar esses dados para podermos usá-los em outro lugar, gravando-os em um arquivo.

      Gravando os Dados em um Arquivo CSV

      Coletar dados que só residem em uma janela de terminal não é muito útil. Arquivos de valores separados por vírgulas (CSV) nos permitem armazenar dados tabulares em texto plano, e é um formato comum para planilhas e bancos de dados. Antes de iniciar esta seção, você deve familiarizar-se com como manipular arquivos de texto sem formatação em Python.

      Primeiro, precisamos importar o módulo interno csv do Python junto com os outros módulos no topo do arquivo de código:

      import csv
      

      Em seguida, vamos criar e abrir um arquivo chamado z-artist-names.csv para que possamos gravar nele (iremos utilizar aqui a variável f para o arquivo), utilizando o modo 'w'. Também vamos escrever os cabeçalhos da primeira linha: Name and Link que iremos passar para o método writerow() como uma lista.

      f = csv.writer(open('z-artist-names.csv', 'w'))
      f.writerow(['Name', 'Link'])
      

      Finalmente, dentro do nosso loop for, vamos escrever cada linha com os names ou nomes dos artistas e seus links associados:

      f.writerow([names, links])
      

      Você pode ver as linhas para cada uma dessas tarefas no arquivo abaixo:

      nga_z_artists.py

      
      import requests
      import csv
      from bs4 import BeautifulSoup
      
      
      page = requests.get('https://web.archive.org/web/20121007172955/http://www.nga.gov/collection/anZ1.htm')
      
      soup = BeautifulSoup(page.text, 'html.parser')
      
      last_links = soup.find(class_='AlphaNav')
      last_links.decompose()
      
      # Criar um arquivo para gravar, adicionar linha de cabeçalhos
      f = csv.writer(open('z-artist-names.csv', 'w'))
      f.writerow(['Name', 'Link'])
      
      artist_name_list = soup.find(class_='BodyText')
      artist_name_list_items = artist_name_list.find_all('a')
      
      for artist_name in artist_name_list_items:
          names = artist_name.contents[0]
          links = 'https://web.archive.org' + artist_name.get('href')
      
      
          # Adicionar em uma linha o nome de cada artista e o link associado
          f.writerow([names, links])
      
      

      Quando você executar o programa agora com o comando python, nenhuma saída será retornada para sua janela de terminal. Em vez disso, um arquivo será criado no diretório em que você está trabalhando, chamado z-artist-names.csv.

      Dependendo do que você usa para abrí-lo, ele deve ser algo assim:

      z-artist-names.csv

      
      Name,Link
      "Zabaglia, Niccola",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=11630
      "Zaccone, Fabian",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=34202
      "Zadkine, Ossip",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=3475w
      ...
      
      

      Ou, ele pode se parecer mais com uma planilha:

      Em ambos os casos, agora você pode usar esse arquivo para trabalhar com os dados de maneiras mais significativas, já que as informações coletadas agora estão armazenadas no disco do seu computador.

      Recuperando Páginas Relacionadas

      Criamos um programa que extrairá dados da primeira página da lista de artistas cujos sobrenomes começam com a letra Z. Porém, existem 4 páginas desses artistas no total, disponíveis no website.

      Para coletar todas essas páginas, podemos executar mais iterações com loops for. Isso revisará a maior parte do código que escrevemos até agora, mas empregará conceitos semelhantes.

      Para começar, vamos inicializar uma lista para manter as páginas:

      pages = []
      

      Vamos preencher essa lista inicializada com o seguinte loop for:

      for i in range(1, 5):
          url = 'https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ' + str(i) + '.htm'
          pages.append(url)
      
      

      Anteriormente neste tutorial, observamos que devemos prestar atenção ao número total de páginas que contêm nomes de artistas começando com a letra Z (ou qualquer letra que estivermos utilizando). Uma vez que existem 4 páginas para a letra Z, construímos o loop foracima com um intervalo de 1 a 5 de modo que ele vai iterar através de cada uma das 4 páginas.

      Para este website específico, as URLs começam com a string https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZe são seguidas com um número de página (que será o inteiro i do loop for que convertemos para uma string) e terminam com .htm. Iremos concatenar estas strings e depois acrescentar o resultado à lista pages.

      Além desse loop, teremos um segundo loop que passará por cada uma das páginas acima. O código nesse loop for será parecido com o código que criamos até agora, já que ele está executando a tarefa que completamos para a primeira página dos artistas com a letra Z para cada um das 4 páginas do total. Observe que, como colocamos o programa original no segundo loop for, agora temos o loop original como um loop for aninhado contido nele.

      Os dois loops for ficarão assim:

      pages = []
      
      for i in range(1, 5):
          url = 'https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ' + str(i) + '.htm'
          pages.append(url)
      
      for item in pages:
          page = requests.get(item)
          soup = BeautifulSoup(page.text, 'html.parser')
      
          last_links = soup.find(class_='AlphaNav')
          last_links.decompose()
      
          artist_name_list = soup.find(class_='BodyText')
          artist_name_list_items = artist_name_list.find_all('a')
      
          for artist_name in artist_name_list_items:
              names = artist_name.contents[0]
              links = 'https://web.archive.org' + artist_name.get('href')
      
              f.writerow([names, links])
      
      

      No código acima, você deve ver que o primeiro loop for está iterando nas páginas e o segundo loop for está extraindo dados de cada uma dessas páginas e, em seguida, adicionando os nomes e links dos artistas, linha por linha, em cada linha de cada página.

      Estes dois loops for estão abaixo das declaraçõs import, da criação e escrita do arquivo CSV (com a linha para a escrita dos cabeçalhos do arquivo), e a inicialização da variável pages (atribuída a uma lista).

      Dentro de um contexto macro do arquivo de programação, o código completo se parece com isto:

      nga_z_artists.py

      
      import requests
      import csv
      from bs4 import BeautifulSoup
      
      
      f = csv.writer(open('z-artist-names.csv', 'w'))
      f.writerow(['Name', 'Link'])
      
      pages = []
      
      for i in range(1, 5):
          url = 'https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ' + str(i) + '.htm'
          pages.append(url)
      
      
      for item in pages:
          page = requests.get(item)
          soup = BeautifulSoup(page.text, 'html.parser')
      
          last_links = soup.find(class_='AlphaNav')
          last_links.decompose()
      
          artist_name_list = soup.find(class_='BodyText')
          artist_name_list_items = artist_name_list.find_all('a')
      
          for artist_name in artist_name_list_items:
              names = artist_name.contents[0]
              links = 'https://web.archive.org' + artist_name.get('href')
      
              f.writerow([names, links])
      
      
      

      Como esse programa está fazendo um trabalho, levará algum tempo para criar o arquivo CSV. Depois de concluído, a saída estará comleta, mostrando os nomes dos artistas e seus links associados de Zabaglia, Niccola até Zykmund, Václav.

      Sendo Cuidadoso

      Ao fazer scraping em páginas web, é importante manter-se cuidadoso com os servidores dos quais você está pegando informações.

      Verifique se o site tem termos de serviço ou termos de uso relacionados ao web scraping. Além disso, verifique se o site tem uma API que permite coletar dados antes de você mesmo fazer scraping.

      Certifique-se de não acessar continuamente os servidores para coletar dados. Depois de coletar o que você precisa de um site, execute scripts que vasculhem pelos dados localmente, em vez de sobrecarregar os servidores de outra pessoa.

      Adicionalmente, é uma boa ideia fazer web scraping com um cabeçalho que tenha o seu nome e e-mail para que o website possa identificá-lo e fazer o acompanhamento caso tenha alguma dúvida. Um exemplo de cabeçalho que você pode usar com a biblioteca Requests do Python é o seguinte:

      import requests
      
      headers = {
          'User-Agent': 'Seu nome, example.com',
          'From': 'email@example.com'
      }
      
      url = 'https://example.com'
      
      page = requests.get(url, headers = headers)
      
      

      A utilização de cabeçalhos com informações identificáveis ​​garante que as pessoas que acessam os logs de um servidor possam entrar em contato com você.

      Conclusão

      Este tutorial usou o Python e o Beautiful Soup para coletar dados de um website. Armazenamos o texto que reunimos em um arquivo CSV.

      Você pode continuar trabalhando neste projeto coletando mais dados e tornando seu arquivo CSV mais robusto. Por exemplo, você pode querer incluir as nacionalidades e os anos de cada artista. Você também pode usar o que aprendeu para coletar dados de outros sites.

      Para continuar aprendendo sobre como extrair informações da web, leia nosso tutorial “How To Crawl A Web Page with Scrapy and Python 3.”



      Source link

      Using a CDN to Speed Up Static Content Delivery


      Introduction

      Modern websites and applications must often deliver a significant amount of static content to end users. This content includes images, stylesheets, JavaScript, and video. As these static assets grow in number and size, bandwidth usage swells and page load times increase, deteriorating the browsing experience for your users and reducing your servers’ available capacity.

      To dramatically reduce page load times, improve performance, and reduce your bandwidth and infrastructure costs, you can implement a CDN, or content delivery network, to cache these assets across a set of geographically distributed servers.

      In this tutorial, we’ll provide a high-level overview of CDNs and how they work, as well as the benefits they can provide for your web applications.

      What is a CDN?

      A content delivery network is a geographically distributed group of servers optimized to deliver static content to end users. This static content can be almost any sort of data, but CDNs are most commonly used to deliver web pages and their related files, streaming video and audio, and large software packages.

      Diagram of content delivery without a CDN

      A CDN consists of multiple points of presence (PoPs) in various locations, each consisting of several edge servers that cache assets from your origin, or host server. When a user visits your website and requests static assets like images or JavaScript files, their requests are routed by the CDN to the nearest edge server, from which the content is served. If the edge server does not have the assets cached or the cached assets have expired, the CDN will fetch and cache the latest version from either another nearby CDN edge server or your origin servers. If the CDN edge does have a cache entry for your assets (which occurs the majority of the time if your website receives a moderate amount of traffic), it will return the cached copy to the end user.

      Content Delivery Network (CDN) diagram

      This allows geographically dispersed users to minimize the number of hops needed to receive static content, fetching the content directly from a nearby edge’s cache. The result is significantly decreased latencies and packet loss, faster page load times, and drastically reduced load on your origin infrastructure.

      CDN providers often offer additional features such as DDoS mitigation and rate-limiting, user analytics, and optimizations for streaming or mobile use cases at additional cost.

      How Does a CDN Work?

      When a user visits your website, they first receive a response from a DNS server containing the IP address of your host web server. Their browser then requests the web page content, which often consists of a variety of static files, such as HTML pages, CSS stylesheets, JavaScript code, and images.

      Once you roll out a CDN and offload these static assets onto CDN servers, either by “pushing” them out manually or having the CDN “pull” the assets automatically (both mechanisms are covered in the next section), you then instruct your web server to rewrite links to static content such that these links now point to files hosted by the CDN. If you’re using a CMS such as WordPress, this link rewriting can be implemented using a third-party plugin like CDN Enabler.

      Many CDNs provide support for custom domains, allowing you to create a CNAME record under your domain pointing to a CDN endpoint. Once the CDN receives a user request at this endpoint (located at the edge, much closer to the user than your backend servers), it then routes the request to the Point of Presence (PoP) located closest to the user. This PoP often consists of one or more CDN edge servers collocated at an Internet Exchange Point (IxP), essentially a data center that Internet Service Providers (ISPs) use to interconnect their networks. The CDN’s internal load balancer then routes the request to an edge server located at this PoP, which then serves the content to the user.

      Caching mechanisms vary across CDN providers, but generally they work as follows:

      1. When the CDN receives a first request for a static asset, such as a PNG image, it does not have the asset cached and must fetch a copy of the asset from either a nearby CDN edge server, or the origin server itself. This is known as a cache “miss,” and can usually be detected by inspecting the HTTP response header, containing X-Cache: MISS. This initial request will be slower than future requests because after completing this request the asset will have been cached at the edge.
      2. Future requests for this asset (cache “hits”), routed to this edge location, will now be served from cache, until expiry (usually set through HTTP headers). These responses will be significantly faster than the initial request, dramatically reducing latencies for users and offloading web traffic onto the CDN network. You can verify that the response was served from a CDN cache by inspecting the HTTP response header, which should now contain X-Cache: HIT.

      To learn more about how a specific CDN works and has been implemented, consult your CDN provider’s documentation.

      In the next section, we’ll introduce the two popular types of CDNs: push and pull CDNs.

      Push vs. Pull Zones

      Most CDN providers offer two ways of caching your data: pull zones and push zones.

      Pull Zones involve entering your origin server’s address, and letting the CDN automatically fetch and cache all the static resources available on your site. Pull zones are commonly used to deliver frequently updated, small to medium sized web assets like HTML, CSS, and JavaScript files. After providing the CDN with your origin server’s address, the next step is usually rewriting links to static assets such that they now point to the URL provided by the CDN. From that point onwards, the CDN will handle your users’ incoming asset requests and serve content from its geographically distributed caches and your origin as appropriate.

      To use a Push Zone, you upload your data to a designated bucket or storage location, which the CDN then pushes out to caches on its distributed fleet of edge servers. Push zones are typically used for larger, infrequently changing files, like archives, software packages, PDFs, video, and audio files.

      Benefits of Using a CDN

      Almost any site can reap the benefits provided by rolling out a CDN, but generally the core reasons for implementing one are to offload bandwidth from your origin servers onto the CDN servers, and to reduce latency for geographically distributed users.

      We’ll go through these and several of the other major advantages afforded by using a CDN below.

      Origin Offload

      If you’re nearing bandwidth capacity on your servers, offloading static assets like images, videos, CSS and JavaScript files will drastically reduce your servers’ bandwidth usage. Content delivery networks are designed and optimized for serving static content, and client requests for this content will be routed to and served by edge CDN servers. This has the added benefit of reducing load on your origin servers, as they then serve this data at a much lower frequency.

      Lower Latency for Improved User Experience

      If your user base is geographically dispersed, and a non-trivial portion of your traffic comes from a distant geographical area, a CDN can decrease latency by caching static assets on edge servers closer to your users. By reducing the distance between your users and static content, you can more quickly deliver content to your users and improve their experience by boosting page load speeds.

      These benefits are compounded for websites serving primarily bandwidth-intensive video content, where high latencies and slow loading times more directly impact user experience and content engagement.

      Manage Traffic Spikes and Avoid Downtime

      CDNs allow you to handle large traffic spikes and bursts by load balancing requests across a large, distributed network of edge servers. By offloading and caching static content on a delivery network, you can accommodate a larger number of simultaneous users with your existing infrastructure.

      For websites using a single origin server, these large traffic spikes can often overwhelm the system, causing unplanned outages and downtime. Shifting traffic onto highly available and redundant CDN infrastructure, designed to handle variable levels of web traffic, can increase the availability of your assets and content.

      Reduce Costs

      As serving static content usually makes up the majority of your bandwidth usage, offloading these assets onto a content delivery network can drastically reduce your monthly infrastructure spend. In addition to reducing bandwidth costs, a CDN can decrease server costs by reducing load on the origin servers, enabling your existing infrastructure to scale. Finally, some CDN providers offer fixed-price monthly billing, allowing you to transform your variable monthly bandwidth usage into a stable, predictable recurring spend.

      Increase Security

      Another common use case for CDNs is DDoS attack mitigation. Many CDN providers include features to monitor and filter requests to edge servers. These services analyze web traffic for suspicious patterns, blocking malicious attack traffic while continuing to allow reputable user traffic through. CDN providers usually offer a variety of DDoS mitigation services, from common attack protection at the infrastructure level (OSI layers 3 and 4), to more advanced mitigation services and rate limiting.

      In addition, most CDNs let you configure full SSL, so that you can encrypt traffic between the CDN and the end user, as well as traffic between the CDN and your origin servers, using either CDN-provided or custom SSL certificates.

      Choosing the Best Solution

      If your bottleneck is CPU load on the origin server, and not bandwidth, a CDN may not be the most appropriate solution. In this case, local caching using popular caches such as NGINX or Varnish may significantly reduce load by serving assets from system memory.

      Before rolling out a CDN, additional optimization steps — like minifying and compressing JavaScript and CSS files, and enabling web server HTTP request compression — can also have a significant impact on page load times and bandwidth usage.

      A helpful tool to measure your page load speed and improve it is Google’s PageSpeed Insights. Another helpful tool that provides a waterfall breakdown of request and response times as well as suggested optimizations is Pingdom.

      Conclusion

      A content delivery network can be a quick and effective solution for improving the scalability and availability of your web sites. By caching static assets on a geographically distributed network of optimized servers, you can greatly reduce page load times and latencies for end users. In addition, CDNs allow you to significantly reduce your bandwidth usage by absorbing user requests and responding from cache at the edge, thus lowering your bandwidth and infrastructure costs.

      With plugins and third-party support for major frameworks like WordPress, Drupal, Django, and Ruby on Rails, as well as additional features like DDoS mitigation, full SSL, user monitoring, and asset compression, CDNs can be an impactful tool for securing and optimizing high-traffic web sites.



      Source link

      How To Move a PostgreSQL Data Directory to a New Location on Ubuntu 18.04


      Introduction

      Databases grow over time, sometimes outgrowing the space on their original file system. When they’re located on the same partition as the rest of the operating system, this can also potentially lead to I/O contention.

      RAID, network block storage, and other devices can offer redundancy and improve scalability, along with other desirable features. Whether you’re adding more space, evaluating ways to optimize performance, or looking to take advantage of other storage features, this tutorial will guide you through relocating PostgreSQL’s data directory.

      Prerequisites

      To complete this guide, you will need:

      In this example, we’re moving the data to a block storage device mounted at /mnt/volume_nyc1_01. If you are using Block Storage on DigitalOcean, this guide can help you mount your volume before continuing with this tutorial.

      Regardless of what underlying storage you use, though, the following steps can help you move the data directory to a new location.

      Step 1 — Moving the PostgreSQL Data Directory

      Before we get started with moving PostgreSQL’s data directory, let’s verify the current location by starting an interactive PostgreSQL session. In the following command, psql is the command to enter the interactive monitor and -u postgres tells sudo to execute psql as the system’s postgres user:

      Once you have the PostgreSQL prompt opened up, use the following command to show the current data directory:

      Output

      data_directory ------------------------------ /var/lib/postgresql/10/main (1 row)

      This output confirms that PostgreSQL is configured to use the default data directory, /var/lib/postgresql/10/main, so that’s the directory we need to move. Once you've confirmed the directory on your system, type q and press ENTER to close the PostgreSQL prompt.

      To ensure the integrity of the data, stop PostgreSQL before you actually make changes to the data directory:

      • sudo systemctl stop postgresql

      systemctl doesn't display the outcome of all service management commands. To verify that you’ve successfully stopped the service, use the following command:

      • sudo systemctl status postgresql

      The final line of the output should tell you that PostgreSQL has been stopped:

      Output

      . . . Jul 12 15:22:44 ubuntu-512mb-nyc1-01 systemd[1]: Stopped PostgreSQL RDBMS.

      Now that the PostgreSQL server is shut down, we’ll copy the existing database directory to the new location with rsync. Using the -a flag preserves the permissions and other directory properties, while -v provides verbose output so you can follow the progress. We’re going to start the rsync from the postgresql directory in order to mimic the original directory structure in the new location. By creating that postgresql directory within the mount-point directory and retaining ownership by the PostgreSQL user, we can avoid permissions problems for future upgrades.

      Note: Be sure there is no trailing slash on the directory, which may be added if you use tab completion. If you do include a trailing slash, rsync will dump the contents of the directory into the mount point instead of copying over the directory itself.

      The version directory, 10, isn’t strictly necessary since we’ve defined the location explicitly in the postgresql.conf file, but following the project convention certainly won’t hurt, especially if there’s a need in the future to run multiple versions of PostgreSQL:

      • sudo rsync -av /var/lib/postgresql /mnt/volume_nyc1_01

      Once the copy is complete, we'll rename the current folder with a .bak extension and keep it until we’ve confirmed that the move was successful. This will help to avoid confusion that could arise from having similarly-named directories in both the new and the old location:

      • sudo mv /var/lib/postgresql/10/main /var/lib/postgresql/10/main.bak

      Now we’re ready to configure PostgreSQL to access the data directory in its new location.

      Step 2 — Pointing to the New Data Location

      By default, the data_directory is set to /var/lib/postgresql/10/main in the /etc/postgresql/10/main/postgresql.conf file. Edit this file to reflect the new data directory:

      • sudo nano /etc/postgresql/10/main/postgresql.conf

      Find the line that begins with data_directory and change the path which follows to reflect the new location. In the context of this tutorial, the updated directive will look like this:

      /etc/postgresql/10/main/postgresql.conf

      . . .
      data_directory = '/mnt/volume_nyc1_01/postgresql/10/main'
      . . .
      

      Save and close the file by pressing CTRL + X, Y, then ENTER. This is all you need to do to configure PostgreSQL to use the new data directory location. All that’s left at this point is to start the PostgreSQL service again and check that it is indeed pointing to the correct data directory.

      Step 3 — Restarting PostgreSQL

      After changing the data-directory directive in the postgresql.conf file, go ahead and start the PostgreSQL server using systemctl:

      • sudo systemctl start postgresql

      To confirm that the PostgreSQL server started successfully, check its status by again using systemctl:

      • sudo systemctl status postgresql

      If the service started correctly, you will see the following line at the end of this command’s output:

      Output

      . . . Jul 12 15:45:01 ubuntu-512mb-nyc1-01[1]: Started PostgreSQL RDBMS. . . .

      Lastly, to make sure that the new data directory is indeed in use, open the PostgreSQL command prompt.

      Check the value for the data directory again:

      Output

      data_directory ----------------------------------------- /mnt/volume_nyc1_01/postgresql/10/main (1 row)

      This confirms that PostgreSQL is using the new data directory location. Following this, take a moment to ensure that you’re able to access your database as well as interact with the data within. Once you’ve verified the integrity of any existing data, you can remove the backup data directory:

      • sudo rm -Rf /var/lib/postgresql/10/main.bak

      With that, you have successfully moved your PostgreSQL data directory to a new location.

      Conclusion:

      If you’ve followed along, your database should be running with its data directory in the new location and you’ve completed an important step toward being able to scale your storage. You might also want to take a look at 5 Common Server Setups For Your Web Application for ideas on how to create a server infrastructure to help you scale and optimize web applications.



      Source link