Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
10
respostas

Programa para pegar em uma página web eventos (python e Beautifulsoup)

Objetivo: pegar os eventos em http://www.bhaktiyogapura.com/2018/03/calendario-vaisnava-marco-2018/

A cada mês, a URL muda apenas o fina, por exemplo, em abril será:

http://www.bhaktiyogapura.com/2018/03/calendario-vaisnava-abril-2018/

import requests
from bs4 import BeautifulSoup
import re

url = 'http://www.bhaktiyogapura.com/2018/03/calendario-vaisnava-marco-2018/'
response = requests.get(url, verify=False)
data = response.text
#soup = BeautifulSoup(data, "html5lib")
soup = BeautifulSoup(data, "lxml")
# aqui você seleciona o que você quer recuperar
r = soup.find("div",{'class':'the_content_wrapper'})
p = r.find_all("p")
# Aqui você itera em todos os páragrafos da agenda.
for linha in p:
    print(linha.text)

O código funciona mas imprime tudo. Gostaria de imprimir assim:

28 de Março 2018 – Quarta
Dvādaśī, G, 05:60, Maghā
-Quebra do jejum para Rio de Janeiro 05:60 às 09:58am
-Quebra do jejum para São Paulo: 06:13 às 10:12am
-Quebra do jejum para Brasília:  06:17 às 10:17am
-Quebra do jejum para Belo Horizonte:  06:02 às 10:01am
-Quebra do jejum para Vitória:  05:47 às 09:47am

Apenas as linhas que tem "-" no formato acima e não tudo! Alguma sugestão?

10 respostas

Edson, não entendi muito bem como você gostaria de imprimir. Esse formato quer você mostrou é o formato que o seu código retorna. Ou você não quer a data?

Eu gostaria de imprimir assim:

28 de Março 2018 – Quarta
Dvādaśī, G, 05:60, Maghā
-Quebra do jejum para Rio de Janeiro 05:60 às 09:58am
-Quebra do jejum para São Paulo: 06:13 às 10:12am
-Quebra do jejum para Brasília:  06:17 às 10:17am
-Quebra do jejum para Belo Horizonte:  06:02 às 10:01am
-Quebra do jejum para Vitória:  05:47 às 09:47am

Ou seja, pegando apenas o que começa com "-"

O meu programa está imprimindo TUDO!

Mas do jeito que você está fazendo imprime assim, Edson.

20 de Março 2018 – Terça
Tritīyā, G, 05:57, Aśvinī

21 de Março 2018 – Quarta
Caturthī, G, 05:57, Bhāranī

23 de Março 2018 – Sexta
Saptamī, G, 05:58, Rohiṇī

24 de Março 2018 – Sábado
Astamī, G, 05:58, Mṛgaśīrśa

Mas as saídas acima nao servem pois não têm o evento começando com "-"

Gostaria de imprimir apenas as linhas que tenham algo começando com "-" e suas respectivas datas!

solução!

Ahhh, agora entendi o que quis dizer! Um gerador pode resolver elegantemente seu problema:

def gera_blocos():
    linhas = []
    for linha in p:
        texto_linha = linha.text
        if texto_linha == '\xa0':
            if len(linhas) > 2:
                yield '\n'.join(linhas)
        elif texto_linha[0].isdigit():
            linhas.clear()
        linhas.append(texto_linha)

blocos = gera_blocos()
for bloco in blocos:
    print(bloco)
    print()

Não sei se você conhece a funcionalidade dos geradores no Python, então vou tentar explicar direitinho :). Uma função geradora, que é essa que eu criei nesse código, é uma função que retorna um objeto gerador iterador quando chamada. Em vez de usar a palavra chave return ela usa yield, que permite múltiplos retornos. Quando iteramos por um objeto gerador iterador, como fizemos com o laço for, aí sim obtemos o retorno que especificamos no yield.

Criamos uma lista vazia de linhas no começo. Para cada linha da nossa lista de tags p, pegamos o texto dentro da tag. Se esse texto for igual a '\xa0', que (por algum motivo) é o caractere que esse site usa em tags p de quebra de linha, aí checamos o tamanho da lista de linhas. Sabemos que no site, todo bloco tem pelo menos duas linhas, no estilo:

01 de Março 2018 – Quinta
Pūrṇimā, G, 05:49, Maghā

então a quantidade de linhas tem que ser maior que 2, já que só queremos os blocos que tenham itens (-). Se a quantidade for maior que 2, então retornamos todas as linhas separadas por uma quebra de linha.

Caso a linha não seja esse caractere ('\xa0'), então checamos se o primeiro caractere dela é um número. Se for, sabemos que é a primeira linha de um bloco, porque é uma linha com a data. Assim, podemos limpar nossa lista de linhas, porque sabemos que um novo bloco está começando.

Então, adicionamos a linha em nossa lista de linhas do bloco.

Eu imagino que isso esteja bem confuso, mas tenta ver com calma o código e a explicação e depois pode perguntar tudo que ficou difícil de entender!

Muito obrigado! Vou estudar a explicação com calma e depois retorno aqui!

Não hesita em perguntar aqui (ou em outro tópico do fórum) qualquer confusão, eu sei que não ficou muito claro :/! Abrações pra você, Edson!

Em breve vai sair um post no blog da Alura a respeito de geradores no Python, aí você vai poder entender um pouco mais!

Se eu trocar a url para:

url = "http://www.bhaktiyogapura.com/2018/02/calendario-vaisnava-fevereiro-2018/"

Ele ainda imprimi alguns valores indesejados:

28 Fevereiro 2018 – Quarta
Caturdaśī, G, 05:48, Āśleṣā


28 Fevereiro 2018 – Quarta
Caturdaśī, G, 05:48, Āśleṣā

Opa, Edson, é só adicionar um continue caso a linha seja aquele '\xa0' para isso não entrar na lista, dessa forma:

def gera_blocos():
    linhas = []
    for linha in p:
        texto_linha = linha.text
        if texto_linha == '\xa0':
            if len(linhas) > 2:
                yield '\n'.join(linhas)
            else:
                continue
        elif texto_linha[0].isdigit():
            linhas.clear()
        linhas.append(texto_linha)

blocos = gera_blocos()
for bloco in blocos:
    print(bloco)
    print()

Muito obrigado de novo! Vou aguardar o artigo sobre geradores! Uma ótima Páscoa!