One place for hosting & domains

      Como Fazer o Deploy de uma Aplicação Go Resiliente no Kubernetes da DigitalOcean


      O autor escolheu o Girls Who Code para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Docker é uma ferramenta de containerização utilizada para fornecer às aplicações um sistema de arquivos que armazena tudo o que eles precisam para executar, garantindo que o software tenha um ambiente de runtime consistente e se comporte da mesma maneira, independentemente de onde esteja implantado ou deployado. O Kubernetes é uma plataforma em nuvem para automatizar o deployment, a escalabilidade e o gerenciamento de aplicações containerizadas.

      Ao aproveitar o Docker, você pode fazer o deploy de uma aplicação em qualquer sistema que ofereça suporte ao Docker com a confiança de que ele sempre funcionará conforme o esperado. O Kubernetes, por sua vez, permite que você faça o deploy de sua aplicação em vários nodes em um cluster. Além disso, ele lida com as principais tarefas, como lançar novos containers em caso de queda de qualquer um dos seus containers. Juntas, essas ferramentas simplificam o processo de deployment de uma aplicação, permitindo que você se concentre no desenvolvimento.

      Neste tutorial, você vai criar uma aplicação de exemplo escrita em Go e a colocará em funcionamento localmente em sua máquina de desenvolvimento. Em seguida, você irá containerizar a aplicação com o Docker, fazer o deploy em um cluster Kubernetes e vai criar um balanceador de carga que servirá como ponto de entrada voltado ao público para a sua aplicação.

      Pré-requisitos

      Antes de começar este tutorial, você precisará do seguinte:

      • Um servidor de desenvolvimento ou máquina local a partir da qual você fará o deploy da aplicação. Embora as instruções deste guia funcionem em grande parte para a maioria dos sistemas operacionais, este tutorial pressupõe que você tenha acesso a um sistema Ubuntu 18.04 configurado com um usuário não-root com privilégios sudo, conforme descrito em nosso tutorial Configuração Inicial de servidor com Ubuntu 18.04.
      • A ferramenta de linha de comando docker instalada em sua máquina de desenvolvimento. Para instalar isto, siga os Passos 1 e 2 do nosso tutorial sobre Como Instalar e Usar o Docker no Ubuntu 18.04.
      • A ferramenta de linha de comando kubectl instalada em sua máquina de desenvolvimento. Para instalá-la, siga este guia da documentação oficial do Kubernetes.
      • Uma conta gratuita no Docker Hub para a qual você enviará sua imagem do Docker. Para configurar isso, visite o website do Docker Hub, clique no botão Get Started no canto superior direito da página e siga as instruções de registro.
      • Um cluster Kubernetes. Você pode provisionar um cluster Kubernetes na DigitalOcean seguindo nosso Guia de início rápido do Kubernetes. Você ainda pode concluir este tutorial se provisionar seu cluster em outro provedor de nuvem. Sempre que você adquirir seu cluster, certifique-se de definir um arquivo de configuração e garantir que você possa se conectar ao cluster a partir do seu servidor de desenvolvimento.

      Passo 1 — Criando uma Aplicação Web de Exemplo em Go

      Nesta etapa, você criará uma aplicação de exemplo escrita em Go. Após containerizar este app com o Docker, ele servirá My Awesome Go App em resposta a solicitações para o endereço IP do seu servidor na porta 3000.

      Comece atualizando as listas de pacotes do seu servidor, se você não tiver feito isso recentemente:

      Em seguida, instale o Go executando:

      Depois, verifique se você está em seu diretório home e crie um novo diretório que vai conter todos os seus arquivos do projeto:

      Em seguida, navegue até este novo diretório:

      Use o nano ou seu editor de texto preferido para criar um arquivo chamado main.go, que conterá o código da sua aplicação Go:

      A primeira linha em qualquer arquivo-fonte do Go é sempre uma instrução package que define a qual pacote de código o arquivo pertence. Para arquivos executáveis como este, a declaração package deve apontar para o pacote main:

      go-app/main.go

      package main
      

      Depois disso, adicione uma instrução import onde você pode listar todas as bibliotecas que a aplicação precisará. Aqui, inclua fmt, que lida com entrada e saída de texto formatada, e net/http, que fornece implementações de cliente e servidor HTTP:

      go-app/main.go

      package main
      
      import (
        "fmt"
        "net/http"
      )
      

      Em seguida, defina uma função homePage que terá dois argumentos: http.ResponseWriter e um ponteiro para http.Request. Em Go, uma interface ResponseWriter é usada para construir uma resposta HTTP, enquanto http.Request é um objeto que representa uma solicitação de entrada. Assim, este bloco lê solicitações HTTP de entrada e, em seguida, constrói uma resposta:

      go-app/main.go

      . . .
      
      import (
        "fmt"
        "net/http"
      )
      
      func homePage(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "My Awesome Go App")
      }
      

      Depois disso, adicione uma função setupRoutes que mapeará as solicitações de entrada para as funções planejadas do handler HTTP. No corpo desta função setupRoutes, adicione um mapeamento da rota / para sua função homePage recém-definida. Isso diz à aplicação para imprimir a mensagem My Awesome Go App mesmo para solicitações feitas a endpoints desconhecidos:

      go-app/main.go

      . . .
      
      func homePage(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "My Awesome Go App")
      }
      
      func setupRoutes() {
        http.HandleFunc("/", homePage)
      }
      

      E finalmente, adicione a seguinte função main. Isso imprimirá uma string indicando que sua aplicação foi iniciada. Ela então chamará a função setupRoutes antes de começar a ouvir e servir sua aplicação Go na porta 3000.

      go-app/main.go

      . . .
      
      func setupRoutes() {
        http.HandleFunc("/", homePage)
      }
      
      func main() {
        fmt.Println("Go Web App Started on Port 3000")
        setupRoutes()
        http.ListenAndServe(":3000", nil)
      }
      

      Após adicionar essas linhas, é assim que o arquivo final ficará:

      go-app/main.go

      package main
      
      import (
        "fmt"
        "net/http"
      )
      
      func homePage(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "My Awesome Go App")
      }
      
      func setupRoutes() {
        http.HandleFunc("/", homePage)
      }
      
      func main() {
        fmt.Println("Go Web App Started on Port 3000")
        setupRoutes()
        http.ListenAndServe(":3000", nil)
      }
      

      Salve e feche este arquivo. Se você criou este arquivo usando nano, faça-o pressionando CTRL + X, Y, depois ENTER.

      Em seguida, execute a aplicação usando o seguinte comando go run. Isto irá compilar o código no seu arquivo main.go e irá executá-lo localmente em sua máquina de desenvolvimento:

      Output

      Go Web App Started on Port 3000

      Esta saída confirma que a aplicação está funcionando conforme o esperado. Ela será executada indefinidamente, entretanto, feche-a pressionando CTRL + C.

      Ao longo deste guia, você usará essa aplicação de exemplo para experimentar com o Docker e o Kubernetes. Para esse fim, continue lendo para saber como containerizar sua aplicação com o Docker.

      Passo 2 — Dockerizando sua Aplicação Go

      Em seu estado atual, a aplicação Go que você acabou de criar está sendo executada apenas em seu servidor de desenvolvimento. Nesta etapa, você tornará essa nova aplicação portátil ao containerizá-la com o Docker. Isso permitirá que ela seja executada em qualquer máquina que ofereça suporte a containers Docker. Você irá criar uma imagem do Docker e a enviará para um repositório público central no Docker Hub. Dessa forma, seu cluster Kubernetes pode baixar a imagem de volta e fazer o deployment dela como um container dentro do cluster.

      O primeiro passo para a containerização de sua aplicação é criar um script especial chamado de Dockerfile. Um Dockerfile geralmente contém uma lista de instruções e argumentos que são executados em ordem sequencial para executar automaticamente determinadas ações em uma imagem base ou criar uma nova.

      Nota: Nesta etapa, você vai configurar um container Docker simples que criará e executará sua aplicação Go em um único estágio. Se, no futuro, você quiser reduzir o tamanho do container onde suas aplicações Go serão executadas em produção, talvez seja interessante dar uma olhada no mutli-stage builds ou compilação em múltiplos estágios.

      Crie um novo arquivo chamado Dockerfile:

      Na parte superior do arquivo, especifique a imagem base necessária para a aplicação Go:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      

      Em seguida, crie um diretório app dentro do container que vai conter os arquivos-fonte da aplicação:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      RUN mkdir /app
      

      Abaixo disso, adicione a seguinte linha que copia tudo no diretório raiz dentro do diretório app:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      RUN mkdir /app
      ADD . /app
      

      Em seguida, adicione a seguinte linha que altera o diretório de trabalho para app, significando que todos os comandos a seguir neste Dockerfile serão executados a partir desse local:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      RUN mkdir /app
      ADD . /app
      WORKDIR /app
      

      Adicione uma linha instruindo o Docker a executar o comando go build -o main, que compila o executável binário da aplicação Go:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      RUN mkdir /app
      ADD . /app
      WORKDIR /app
      RUN go build -o main .
      

      Em seguida, adicione a linha final, que irá rodar o executável binário:

      go-app/Dockerfile

      FROM golang:1.12.0-alpine3.9
      RUN mkdir /app
      ADD . /app
      WORKDIR /app
      RUN go build -o main .
      CMD ["/app/main"]
      

      Salve e feche o arquivo depois de adicionar essas linhas.

      Agora que você tem esse Dockerfile na raiz do seu projeto, você pode criar uma imagem Docker baseada nele usando o seguinte comando docker build. Este comando inclui a flag -t que, quando passado o valor go-web-app, nomeará a imagem Docker como go-web-app e irá marcar ou colocar uma tag nela.

      Nota: No Docker, as tags permitem que você transmita informações específicas para uma determinada imagem, como o seu número de versão. O comando a seguir não fornece uma tag específica, portanto, o Docker marcará a imagem com sua tag padrão: latest. Se você quiser atribuir uma tag personalizada a uma imagem, você adicionaria o nome da imagem com dois pontos e a tag de sua escolha, assim:

      • docker build -t sammy/nome_da_imagem:nome_da_tag .

      Marcar ou "taggear" uma imagem como essa pode lhe dar maior controle sobre suas imagens. Por exemplo, você poderia fazer o deploy de uma imagem marcada como v1.1 em produção, mas fazer o deploy de outra marcada como v1.2 em seu ambiente de pré-produção ou teste.

      O argumento final que você vai passar é o caminho: .. Isso especifica que você deseja criar a imagem Docker a partir do conteúdo do diretório de trabalho atual. Além disso, certifique-se de atualizar sammy para o seu nome de usuário do Docker Hub:

      • docker build -t sammy/go-web-app .

      Este comando de compilação vai ler todas as linhas do seu Dockerfile, executá-las em ordem e armazenará em cache, permitindo que futuras compilações sejam executadas muito mais rapidamente:

      Output

      . . . Successfully built 521679ff78e5 Successfully tagged go-web-app:latest

      Quando este comando terminar a compilação, você poderá ver sua imagem quando executar o comando docker images da seguinte forma:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE sammy/go-web-app latest 4ee6cf7a8ab4 3 seconds ago 355MB

      Em seguida, use o seguinte comando para criar e iniciar um container com base na imagem que você acabou de criar. Este comando inclui a flag -it, que especifica que o container será executado no modo interativo. Ele também possui a flag -p que mapeia a porta na qual a aplicação Go está sendo executada em sua máquina de desenvolvimento — porta 3000 — para a porta 3000 em seu container Docker.

      • docker run -it -p 3000:3000 sammy/go-web-app

      Output

      Go Web App Started on Port 3000

      Se não houver mais nada em execução nessa porta, você poderá ver a aplicação em ação abrindo um navegador e navegando até a seguinte URL:

      http://ip_do_seu_servidor:3000
      

      Nota: Se você estiver seguindo este tutorial em sua máquina local em vez de um servidor, visite a aplicação acessando a seguinte URL:

      http://localhost:3000
      

      Your containerized Go App

      Depois de verificar se a aplicação funciona como esperado no seu navegador, finalize-a pressionando CTRL + C no seu terminal.

      Quando você faz o deploy de sua aplicação containerizada em seu cluster Kubernetes, você vai precisar conseguir extrair a imagem de um local centralizado. Para esse fim, você pode enviar sua imagem recém-criada para o repositório de imagens do Docker Hub.

      Execute o seguinte comando para efetuar login no Docker Hub a partir do seu terminal:

      Isso solicitará seu nome de usuário e sua senha do Docker Hub. Depois de inseri-los corretamente, você verá Login Succeeded na saída do comando.

      Após o login, envie sua nova imagem para o Docker Hub usando o comando docker push, assim:

      • docker push sammy/go-web-app

      Quando esse comando for concluído com êxito, você poderá abrir sua conta do Docker Hub e ver sua imagem do Docker lá.

      Agora que você enviou sua imagem para um local central, está pronto para fazer o seu deployment em seu cluster do Kubernetes. Primeiro, porém, vamos tratar de um breve processo que tornará muito menos tedioso executar comandos kubectl.

      Passo 3 — Melhorando a Usabilidade para o kubectl

      Nesse ponto, você criou uma aplicação Go funcional e fez a containerização dela com o Docker. No entanto, a aplicação ainda não está acessível publicamente. Para resolver isso, você fará o deploy de sua nova imagem Docker em seu cluster Kubernetes usando a ferramenta de linha de comando kubectl. Antes de fazer isso, vamos fazer uma pequena alteração no arquivo de configuração do Kubernetes que o ajudará a tornar a execução de comandos kubectl menos trabalhosa.

      Por padrão, quando você executa comandos com a ferramenta de linha de comando kubectl, você deve especificar o caminho do arquivo de configuração do cluster usando a flag --kubeconfig. No entanto, se o seu arquivo de configuração é chamado config e está armazenado em um diretório chamado ~/.kube, o kubectl saberá onde procurar pelo arquivo de configuração e poderá obtê-lo sem a flag --kubeconfig apontando para ele.

      Para esse fim, se você ainda não tiver feito isso, crie um novo diretório chamado ~/.kube:

      Em seguida, mova o arquivo de configuração do cluster para este diretório e renomeie-o como config no processo:

      • mv clusterconfig.yaml ~/.kube/config

      Seguindo em frente, você não precisará especificar a localização do arquivo de configuração do seu cluster quando executar o kubectl, pois o comando poderá encontrá-lo agora que está no local padrão. Teste esse comportamento executando o seguinte comando get nodes:

      Isso exibirá todos os nodes que residem em seu cluster Kubernetes. No contexto do Kubernetes, um node é um servidor ou uma máquina de trabalho na qual pode-se fazer o deployment de um ou mais pods:

      Output

      NAME STATUS ROLES AGE VERSION k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfd Ready <none> 1m v1.13.5 k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfi Ready <none> 1m v1.13.5 k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfv Ready <none> 1m v1.13.5

      Com isso, você está pronto para continuar e fazer o deploy da sua aplicação em seu cluster Kubernetes. Você fará isso criando dois objetos do Kubernetes: um que fará o deploy da aplicação em alguns pods no cluster e outro que criará um balanceador de carga, fornecendo um ponto de acesso à sua aplicação.

      Passo 4 — Criando um Deployment

      Recursos RESTful compõem todas as entidades persistentes dentro de um sistema Kubernetes, e neste contexto elas são comumente chamadas de Kubernetes objects. É útil pensar nos objetos do Kubernetes como as ordens de trabalho que você envia ao Kubernetes: você lista quais recursos você precisa e como eles devem funcionar, e então o Kubernetes trabalhará constantemente para garantir que eles existam em seu cluster.

      Um tipo de objeto do Kubernetes, conhecido como deployment, é um conjunto de pods idênticos e indistinguíveis. No Kubernetes, um pod é um agrupamento de um ou mais containers que podem se comunicar pela mesma rede compartilhada e interagir com o mesmo armazenamento compartilhado. Um deployment executa mais de uma réplica da aplicação pai de cada vez e substitui automaticamente todas as instâncias que falham, garantindo que a aplicação esteja sempre disponível para atender às solicitações do usuário.

      Nesta etapa, você criará um arquivo de descrição de objetos do Kubernetes, também conhecido como manifest, para um deployment. Esse manifest conterá todos os detalhes de configuração necessários para fazer o deploy da sua aplicação Go em seu cluster.

      Comece criando um manifest de deployment no diretório raiz do seu projeto: go-app/. Para projetos pequenos como este, mantê-los no diretório raiz minimiza a complexidade. Para projetos maiores, no entanto, pode ser benéfico armazenar seus manifests em um subdiretório separado para manter tudo organizado.

      Crie um novo arquivo chamado deployment.yml:

      Diferentes versões da API do Kubernetes contêm diferentes definições de objetos, portanto, no topo deste arquivo você deve definir a apiVersion que você está usando para criar este objeto. Para o propósito deste tutorial, você estará usando o agrupamento apps/v1, pois ele contém muitas das principais definições de objeto do Kubernetes que você precisará para criar um deployment. Adicione um campo abaixo de apiVersion, descrevendo o kind ou tipo de objeto do Kubernetes que você está criando. Neste caso, você está criando um Deployment:

      go-app/deployment.yml

      ---
      apiVersion: apps/v1
      kind: Deployment
      

      Em seguida, defina o metadata para o seu deployment. Um campo metadata é necessário para todos os objetos do Kubernetes, pois contém informações como o name ou nome exclusivo do objeto. Este name é útil, pois permite distinguir diferentes deployments e identificá-los usando nomes inteligíveis:

      go-app/deployment.yml

      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
          name: go-web-app
      

      Em seguida, você construirá o bloco spec do seu deployment.yml. Um campo spec é um requisito para todos os objetos do Kubernetes, mas seu formato exato é diferente para cada tipo de objeto. No caso de um deployment, ele pode conter informações como o número de réplicas que você deseja executar. No Kubernetes, uma réplica é o número de pods que você deseja executar em seu cluster. Aqui, defina o número de replicas para 5:

      go-app/deployment.yml

      . . .
      metadata:
          name: go-web-app
      spec:
        replicas: 5
      

      Depois, crie um bloco selector aninhado sob o bloco spec. Isso servirá como um seletor de label ou seletor de etiquetas para seus pods. O Kubernetes usa seletores de label para definir como o deployment encontra os pods que ele deve gerenciar.

      Dentro deste bloco selector, defina matchLabels e adicione a label name. Essencialmente, o campo matchLabels diz ao Kubernetes para quais pods o deployment se aplica. Neste exemplo, o deployment será aplicado a todos os pods com o nome go-web-app:

      go-app/deployment.yml

      . . .
      spec:
        replicas: 5
        selector:
          matchLabels:
            name: go-web-app
      

      Depois disso, adicione um bloco template. Cada deployment cria um conjunto de pods usando as labels especificadas em um bloco template. O primeiro subcampo deste bloco é o metadata, que contém as labels que serão aplicadas a todos os pods deste deployment. Essas labels são pares de chave/valor que são usados como atributos de identificação de objetos do Kubernetes. Quando você definir seu serviço mais tarde, você pode especificar que deseja que todos os pods com essa label name sejam agrupados sob esse serviço. Defina esta label name para go-web-app:

      go-app/deployment.yml

      . . .
      spec:
        replicas: 5
        selector:
          matchLabels:
            name: go-web-app
        template:
          metadata:
            labels:
              name: go-web-app
      

      A segunda parte deste bloco template é o bloco spec. Este é diferente do bloco spec que você adicionou anteriormente, já que este se aplica somente aos pods criados pelo bloco template, em vez de todo o deployment.

      Dentro deste bloco spec, adicione um campo containers e mais uma vez defina um atributo name. Este campo name define o nome de qualquer container criado por este deployment específico. Abaixo disso, defina a imagem ou image que você deseja baixar e fazer o deploy. Certifique-se de alterar sammy para seu próprio nome de usuário do Docker Hub:

      go-app/deployment.yml

      . . .
        template:
          metadata:
            labels:
              name: go-web-app
          spec:
            containers:
            - name: application
              image: sammy/go-web-app
      

      Depois disso, adicione um campo imagePullPolicy definido como IfNotPresent, que direcionará o deployment para baixar uma imagem apenas se ainda não tiver feito isso antes. Então, por último, adicione um bloco ports. Lá, defina o containerPort que deve corresponder ao número da porta que sua aplicação Go está escutando. Neste caso, o número da porta é 3000:

      go-app/deployment.yml

      . . .
          spec:
            containers:
            - name: application
              image: sammy/go-web-app
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 3000
      

      A versão completa do seu arquivo deployment.yml ficará assim:

      go-app/deployment.yml

      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: go-web-app
      spec:
        replicas: 5
        selector:
          matchLabels:
            name: go-web-app
        template:
          metadata:
            labels:
              name: go-web-app
          spec:
            containers:
            - name: application
              image: sammy/go-web-app
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 3000
      

      Salve e feche o arquivo.

      Em seguida, aplique seu novo deployment com o seguinte comando:

      • kubectl apply -f deployment.yml

      Nota: Para mais informações sobre todas as configurações disponíveis para seus deployments, confira a documentação oficial do Kubernetes aqui: Kubernetes Deployments

      Na próxima etapa, você criará outro tipo de objeto do Kubernetes que gerenciará como você vai acessar os pods existentes em seu novo deployment. Esse serviço criará um balanceador de carga que, então, vai expor um único endereço IP, e as solicitações para esse endereço IP serão distribuídas para as réplicas em seu deployment. Esse serviço também manipulará regras de encaminhamento de porta para que você possa acessar sua aplicação por HTTP.

      Passo 5 — Criando um Serviço

      Agora que você tem um deployment bem sucedido do Kubernetes, está pronto para expor sua aplicação ao mundo externo. Para fazer isso, você precisará definir outro tipo de objeto do Kubernetes: um service. Este serviço irá expor a mesma porta em todos os nodes do cluster. Então, seus nodes encaminharão qualquer tráfego de entrada nessa porta para os pods que estiverem executando sua aplicação.

      Nota: Para maior clareza, vamos definir esse objeto de serviço em um arquivo separado. No entanto, é possível agrupar vários manifests de recursos no mesmo arquivo YAML, contanto que estejam separados por ---. Veja esta página da documentação do Kubernetes para maiores detalhes.

      Crie um novo arquivo chamado service.yml:

      Inicie este arquivo novamente definindo os campos apiVersion e kind de maneira similar ao seu arquivo deployment.yml. Desta vez, aponte o campo apiVersion para v1, a API do Kubernetes comumente usada para serviços:

      go-app/service.yml

      ---
      apiVersion: v1
      kind: Service
      

      Em seguida, adicione o nome do seu serviço em um bloco metadata como você fez em deployment.yml. Pode ser qualquer coisa que você goste, mas para clareza, vamos chamar de go-web-service:

      go-app/service.yml

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: go-web-service
      

      Em seguida, crie um bloco spec. Este bloco spec será diferente daquele incluído em seu deployment, e ele conterá o tipo ou type deste serviço, assim como a configuração de encaminhamento de porta e o seletor.

      Adicione um campo definindo o type deste serviço e defina-o para LoadBalancer. Isso provisionará automaticamente um balanceador de carga que atuará como o principal ponto de entrada para sua aplicação.

      Atenção: O método para criar um balanceador de carga descrito nesta etapa só funcionará para clusters Kubernetes provisionados por provedores de nuvem que também suportam balanceadores de carga externos. Além disso, esteja ciente de que provisionar um balanceador de carga de um provedor de nuvem incorrerá em custos adicionais. Se isto é uma preocupação para você, você pode querer olhar a exposição de um endereço IP externo usando um Ingress.

      go-app/service.yml

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: go-web-service
      spec:
        type: LoadBalancer
      

      Em seguida, adicione um bloco ports onde você definirá como deseja que seus apps sejam acessados. Aninhado dentro deste bloco, adicione os seguintes campos:

      • name, apontando para http
      • port, apontando para a porta 80
      • targetPort, apontando para a porta 3000

      Isto irá pegar solicitações HTTP de entrada na porta 80 e encaminhá-las para o targetPort de 3000. Este targetPort é a mesma porta na qual sua aplicação Go está rodando:

      go-app/service.yml

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: go-web-service
      spec:
        type: LoadBalancer
        ports:
        - name: http
          port: 80
          targetPort: 3000
      

      Por último, adicione um bloco selector como você fez no arquivo deployments.yml. Este bloco selector é importante, pois mapeia quaisquer pods deployados chamados go-web-app para este serviço:

      go-app/service.yml

      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: go-web-service
      spec:
        type: LoadBalancer
        ports:
        - name: http
          port: 80
          targetPort: 3000
        selector:
          name: go-web-app
      

      Depois de adicionar essas linhas, salve e feche o arquivo. Depois disso, aplique este serviço ao seu cluster do Kubernetes novamente usando o comando kubectl apply assim:

      • kubectl apply -f service.yml

      Esse comando aplicará o novo serviço do Kubernetes, além de criar um balanceador de carga. Esse balanceador de carga servirá como o ponto de entrada voltado ao público para a sua aplicação em execução no cluster.

      Para visualizar a aplicação, você precisará do endereço IP do novo balanceador de carga. Encontre-o executando o seguinte comando:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE go-web-service LoadBalancer 10.245.107.189 203.0.113.20 80:30533/TCP 10m kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 3h4m

      Você pode ter mais de um serviço em execução, mas encontre o que está com a label go-web-service. Encontre a coluna EXTERNAL-IP e copie o endereço IP associado ao go-web-service. Neste exemplo de saída, este endereço IP é 203.0.113.20. Em seguida, cole o endereço IP na barra de URL do seu navegador para visualizar a aplicação em execução no seu cluster Kubernetes.

      Nota: Quando o Kubernetes cria um balanceador de carga dessa maneira, ele faz isso de forma assíncrona. Consequentemente, a saída do comando kubectl get services pode mostrar o endereço EXTERNAL-IP do LoadBalancer restante em um estado <pending> por algum tempo após a execução do comando kubectl apply. Se for esse o caso, aguarde alguns minutos e tente executar novamente o comando para garantir que o balanceador de carga foi criado e está funcionando conforme esperado.

      O balanceador de carga receberá a solicitação na porta 80 e a encaminhará para um dos pods em execução no seu cluster.

      Your working Go App!

      Com isso, você criou um serviço Kubernetes acoplado a um balanceador de carga, oferecendo um ponto de entrada único e estável para a aplicação.

      Conclusão

      Neste tutorial, você criou uma aplicação Go, containerizada com o Docker e, em seguida, fez o deploy dela em um cluster Kubernetes. Em seguida, você criou um balanceador de carga que fornece um ponto de entrada resiliente para essa aplicação, garantindo que ela permaneça altamente disponível, mesmo se um dos nodes do cluster falhar. Você pode usar este tutorial para fazer o deploy da sua própria aplicação Go em um cluster Kubernetes ou continuar aprendendo outros conceitos do Kubernetes e do Docker com a aplicação de exemplo que você criou no Passo 1.

      Seguindo em frente, você pode mapear o endereço IP do seu balanceador de carga para um nome de domínio que você controla para que você possa acessar a aplicação por meio de um endereço web legível em vez do IP do balanceador de carga. Além disso, os seguintes tutoriais de Kubernetes podem ser de seu interesse:

      Por fim, se você quiser saber mais sobre o Go, recomendamos que você confira nossa série sobre Como Programar em Go.



      Source link

      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