jsfoliveira / project-tech-news

Projeto desenvolvido e proposto no curso da Trybe.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

👩‍💻 Project Tech News

Esse projeto contém uma série de informações sobre o que eu aprendi aqui na Trybe ao longo do curso de desenvolvimento web da Trybe.
O objetivo principal desse projeto é fazer consultas em notícias sobre tecnologia.

As notíciasforam obtidas através da raspagem do blog da Trybe.

🚵 Habilidades que foram trabalhadas:

  • Utilizar o terminal interativo do Python
  • Escrever seus próprios módulos e importá-los em outros códigos
  • Aplicar técnicas de raspagem de dados
  • Extrair dados de conteúdo HTML
  • Armazenar os dados obtidos em um banco de dados

🚀Começando

Esse projeto foi proposto pelo curso de desenvolvimento web da Trybe.

Desenvolvimento

Esse projeto foi desenvolvido no bloco de ciências da computação. Pude desenvolver habilidades de arquitetura de redes e raspagens de dados.

Commits

Os commits foram feitos de acordo com os requisitos finalizados.

Branch

Todo o projeto foi feita na branch 'juliana-oliveira-tech-news'.

Instalação (sem Docker)

Antes de rodar o projeto, é necessário criar o ambiente virtual e instalar as dependências através dos comandos:

  • python3 -m venv .venv && source .venv/bin/activate
  • python3 -m pip install -r dev-requirements.txt

Estrutura do projeto

🧱 Estrutura do Projeto
Este repositório já contém um template com a estrutura de diretórios e arquivos, tanto de código quanto de teste criados. Veja abaixo:
Legenda:
🔸Arquivos que não podem ser alterados
🔹Arquivos a serem alterados para realizar os requisitos.
.
├── tech_news
│   ├── analyzer
│   │   ├── 🔹ratings.py
│   │   └── 🔹search_engine.py
│   ├── 🔸database.py
│   └── 🔹menu.py
│   └── 🔹scraper.py
├── tests
│   ├── 🔸assets/*
│   ├── 🔸__init__.py
│   ├── 🔸generate_fixture.py
│   ├── 🔸news.py
│   ├── 🔸test_menu.py
│   ├── 🔸test_ratings.py
│   ├── 🔸test_scraper.py
│   ├── 🔸test_search_engine.py
│   └── 🔸utils.py
├── 🔸dev-requirements.txt
├── 🔸docker-compose.yml
├── 🔸Dockerfile
├── 🔸pyproject.toml
├── 🔸README.md
├── 🔸requirements.txt
├── 🔸setup.cfg
├── 🔸setup.py
└── 🔸trybe.yml

Apesar do projeto já possuir uma estrutura base, você perceberá que possui arquivos vazios, ou seja, neles você quem deve implementar as classes. Novos arquivos e funções podem ser criados conforme a necessidade da sua implementação, porém não remova arquivos já existentes.

Raspagem de dados

🏃🏾 Executando o Projeto As notícias que foram raspadas estão disponíveis no _Blog da Trybe_: https://blog.betrybe.com.
Essas notícias foram salvas no banco de dados utilizando as funções python que já vêm prontas no módulo `database.py`

Mongo

MongoDB

Para a realização deste projeto, utilizaremos um banco de dados chamado tech_news. As notícias serão armazenadas em uma coleção chamada news. Já existem algumas funções prontas no arquivo tech_news/database.py que te auxiliarão no desenvolvimento. Não altere as funções deste arquivo; mudanças nele não serão executadas no avaliador automático.

Rodar MongoDB via Docker: docker-compose up -d mongodb no terminal. Para mais detalhes acerca do mongo com o docker, olhe o arquivo docker-compose.yml

Caso queira instalar e rodar o servidor MongoDB nativo na máquina, siga as instruções no tutorial oficial:

Ubuntu: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/ MacOS: https://docs.mongodb.com/guides/server/install/

Com o banco de dados rodando, o nosso módulo conseguirá acessá-lo sem problemas. Importe o módulo tech_news/database.py e chame as funções contidas nele. Lembre-se de que o mongoDB utilizará por padrão a porta 27017. Se já houver outro serviço utilizando esta porta, considere desativá-lo.

Autores

Esse foi um projeto individula.

Ferramentas usadas

Foi usado Visual Studio Code, além do Trello que auxiliou na organização das tarefas.

Framework usado

Boas-vindas ao repositório do Tech News

👣Requisitos

Metodologia usada

No trabalho do desenvolvimento de software a gente sempre tem prazos, muitas vezes os prazos são apertados.
Por outro lado, eu não quero criar algo que não entendo perfeitamente, como também fazer códigos rápidos pode levar a erros que podem demorar muito pra corrigir.
Por isso, usei e sempre uso o método Baby Steps, que é uma estratégia de abordar o desafio passo à passo, defensivamente.
Baby steps é um termo em inglês que quer dizer passos de bebê. Refere-se a fazer as coisas, quaisquer que sejam, devagar, com calma, passo a passo.

👣Requisito 1 - Crie a função fetch

local: tech_news/scraper.py

Antes de fazer scrape, precisamos de uma página! Esta função será responsável por fazer a requisição HTTP ao site e obter o conteúdo HTML. Alguns cuidados deverão ser tomados: como a nossa função poderá ser utilizada várias vezes em sucessão, na nossa implementação devemos nos assegurar que um Rate Limit será respeitado.

  • A função deve receber uma URL
  • A função deve fazer uma requisição HTTP get para esta URL utilizando a função requests.get
  • A função deve retornar o conteúdo HTML da resposta.
  • A função deve respeitar um Rate Limit de 1 requisição por segundo; Ou seja, caso chamada múltiplas vezes, ela deve aguardar 1 segundo entre cada requisição que fizer. Dica: Uma forma simples de garantir que cada requisição seja feita com um intervalo mínimo de um segundo é utilizar time.sleep(1) antes de cada requisição. (Existem outras formas mais eficientes.)
  • Caso a requisição seja bem sucedida com Status Code 200: OK, deve ser retornado seu conteúdo de texto;
  • Caso a resposta tenha o código de status diferente de 200, deve-se retornar None;
  • Caso a requisição não receba resposta em até 3 segundos, ela deve ser abandonada (este caso é conhecido como "Timeout") e a função deve retornar None.

📌 Você vai precisar definir o header user-agent para que a raspagem do blog da Trybe funcione corretamente. Para isso, preencha com o valor "Fake user-agent" conforme exemplo abaixo:

{ "user-agent": "Fake user-agent" }
✍️ Teste manual

Abra um terminal Python importando estas funções através do comando:

python3 -i tech_news/scraper.py

Agora invoque as funções utilizando diferentes parâmetros. Exemplo:

html = fetch(url_da_noticia)
scrape_noticia(html)
🤖 O que será verificado pelo avaliador
  • A função utiliza o método get() da biblioteca requests

  • A função executada com uma URL correta retorna o conteúdo html

  • A função, sofrendo timeout, retorna None

  • A função retorna None quando recebe uma resposta com código diferente de 200

  • A função respeita o rate limit

👣Requisito 2 - Crie a função scrape_novidades

local: tech_news/scraper.py

Para conseguirmos fazer o scrape da página de uma notícia, primeiro precisamos de links para várias páginas de notícias. Estes links estão contidos na página inicial do blog da Trybe (https://blog.betrybe.com).

Esta função fará o scrape da página Novidades para obter as URLs das páginas de notícias. Vamos utilizar as ferramentas que aprendemos no curso, como a biblioteca Parsel, para obter os dados que queremos de cada página.

  • A função deve receber uma string com o conteúdo HTML da página inicial do blog
  • A função deve fazer o scrape do conteúdo recebido para obter uma lista contendo as URLs das notícias listadas.
    • ⚠️ Atenção: NÃO inclua a notícia em destaque da primeira página, apenas as notícias dos cards.
  • A função deve retornar esta lista.
  • Caso não encontre nenhuma URL de notícia, a função deve retornar uma lista vazia.
✍️ Teste manual

Abra um terminal Python importando estas funções através do comando:

python3 -i tech_news/scraper.py

Agora invoque as funções utilizando diferentes parâmetros. Exemplo:

html = fetch(url_da_noticia)
scrape_novidades(html)
🤖 O que será verificado pelo avaliador
  • A função retorna os dados esperados quando chamada com os parâmetros corretos

  • A função retorna uma lista vazia quando chamada com parâmetros incorretos

👣Requisito 3 - Crie a função scrape_next_page_link

local: tech_news/scraper.py

Para buscar mais notícias, precisaremos fazer a paginação, e para isto, vamos precisar do link da próxima página. Esta função será responsável por fazer o scrape deste link.

  • A função deve receber como parâmetro uma string contendo o conteúdo HTML da página de novidades (https://blog.betrybe.com)
  • A função deve fazer o scrape deste HTML para obter a URL da próxima página.
  • A função deve retornar a URL obtida.
  • Caso não encontre o link da próxima página, a função deve retornar None
🤖 O que será verificado pelo avaliador
  • A função retorna os dados esperados quando chamada com os parâmetros corretos

  • A função retorna None quando chamada com os parâmetros incorretos

👣Requisito 4 - Crie a função scrape_noticia

local: tech_news/scraper.py

Agora que sabemos pegar páginas HTML, e descobrir o link de notícias, é hora de fazer o scrape dos dados que procuramos!

  • A função deve receber como parâmetro o conteúdo HTML da página de uma única notícia

  • A função deve, no conteúdo recebido, buscar as informações das notícias para preencher um dicionário com os seguintes atributos:

    • url - link para acesso da notícia.
    • title - título da notícia.
    • timestamp - data da notícia, no formato dd/mm/AAAA.
    • writer - nome da pessoa autora da notícia.
    • comments_count - número de comentários que a notícia recebeu.
      • Se a informação não for encontrada, salve este atributo como 0 (zero)
    • summary - o primeiro parágrafo da notícia.
    • tags - lista contendo tags da notícia.
    • category - categoria da notícia.
  • Exemplo de um retorno da função com uma notícia fictícia:

{
  "url": "https://blog.betrybe.com/novidades/noticia-bacana",
  "title": "Notícia bacana",
  "timestamp": "04/04/2021",
  "writer": "Eu",
  "comments_count": 4,
  "summary": "Algo muito bacana aconteceu",
  "tags": ["Tecnologia", "Esportes"],
  "category": "Ferramentas",
}

📌 Muita atenção aos tipos dos campos, por exemplo, tags é uma lista, enquanto que comments_count é numérico e category é uma string.

📌 Os textos coletados em title e summary podem conter alguns caracteres vazios ao final. O teste espera que esses caracteres sejam removidos.

📌 Como nem todas as páginas têm tags, você pode utilizar esta notícia como base para conseguir raspar essa informação.

📌 Para o campo comments_count, como há poucas notícias com comentários, utilizem esta notícia como referência para scrape desta informação.

📌 É bom saber que ao fazer scraping na vida real, você está sempre "refém" de quem construiu o site. Por exemplo, pode ser que nem toda notícia tenha exatamente o mesmo HTML/CSS e você precise de criatividade para contornar isso.

🤖 O que será verificado pelo avaliador
  • Será verificado se a função retorna o conteúdo correto e no formato correto, dada uma página de notícia exemplo.

👍 Terminou o requisito 4?

Parabéns! Este é o requisito mais longo do projeto, e também a funcionalidade central do nosso tech-news. Faça um break, tome uma água, e #vamoquevamo para os próximos requisitos!


👣Requisito 5 - Crie a função get_tech_news para obter as notícias!

local: tech_news/scraper.py

Agora, chegou a hora de aplicar todas as funções que você acabou de fazer. Com estas ferramentas prontas, podemos fazer nosso scraper mais robusto com a paginação.

  • A função deve receber como parâmetro um número inteiro n e buscar as últimas n notícias do site.
  • Utilize as funções fetch, scrape_novidades, scrape_next_page_link e scrape_noticia para buscar as notícias e processar seu conteúdo.
  • As notícias buscadas devem ser inseridas no MongoDB; Para acessar o banco de dados, importe e utilize as funções que já temos prontas em tech_news/database.py
  • Após inserir as notícias no banco, a função deve retornar estas mesmas notícias.

📌 De aqui em diante, usaremos o MongoDB.

Rodar MongoDB via Docker: docker-compose up -d mongodb no terminal. Para mais detalhes acerca do mongo com o docker, olhe o arquivo docker-compose.yml

Caso queira instalar e rodar o servidor MongoDB nativo na máquina, siga as instruções no tutorial oficial: Ubuntu: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
MacOS: https://docs.mongodb.com/guides/server/install/

Com o banco de dados rodando, o nosso módulo conseguirá acessá-lo sem problemas. Importe o módulo tech_news/database.py e chame as funções contidas nele. Não altere as funções deste módulo; elas serão utilizadas nos testes.

🤖 O que será verificado pelo avaliador
  • A função create_news do tech_news/database.py foi chamada corretamente

  • A função retorna a quantidade correta de notícias

👣Requisito 6 - Crie a função search_by_title

local: tech_news/analyzer/search_engine.py

Agora que temos meios de popular nosso banco de dados com notícias, podemos começar a fazer as buscas! Esta função irá fazer buscas por título.

  • A função deve receber uma string com um título de notícia
  • A função deve buscar as notícias do banco de dados por título
  • A função deve retornar uma lista de tuplas com as notícias encontradas nesta busca. Exemplo:
[
  ("Título1_aqui", "url1_aqui"),
  ("Título2_aqui", "url2_aqui"),
  ("Título3_aqui", "url3_aqui"),
]
  • A busca deve ser case insensitive
  • Caso nenhuma notícia seja encontrada, deve-se retornar uma lista vazia.

📌 Lembre-se; para acesso ao banco de dados importe db definido no módulo tech_news/database.py.

✍️ Teste manual Abra um terminal Python importando esta função através do comando

python3 -i tech_news/analyzer/search_engine.py

Agora invoque a função utilizando diferentes parâmetros. Exemplo:

search_by_title("Algoritmos").

🤖 O que será verificado pelo avaliador
  • Será validado que é possível buscar uma notícia pelo título com sucesso

  • Será validado que ao buscar por um título que não existe, o retorno deve ser uma lista vazia

  • Será validado que é possível buscar uma notícia com sucesso, tanto pelo título em maiúsculas como em minúsculas.

👣Requisito 7 - Crie a função search_by_date

local: tech_news/analyzer/search_engine.py

Esta função irá buscar as notícias do banco de dados por data.

  • A função deve receber como parâmetro uma data no formato ISO AAAA-mm-dd
  • A função deve buscar as notícias do banco de dados por data.
  • A função deve ter retorno no mesmo formato do requisito anterior.
  • Caso a data seja inválida, ou esteja em outro formato, uma exceção ValueError deve ser lançada com a mensagem Data inválida.
  • Caso nenhuma notícia seja encontrada, deve-se retornar uma lista vazia.

📌 Lembre-se: A função recebe uma data no formato ISO AAAA-mm-dd, mas no banco a data está salva no formato dd/mm/AAAA. Dica: Lembrem-se de como trabalhamos com datas nos projetos anteriores.

✍️ Teste manual Abra um terminal Python importando esta função através do comando

python3 -i tech_news/analyzer/search_engine.py

Agora invoque a função utilizando diferentes parâmetros. Exemplo:

search_by_date("2021-04-04")

🤖 O que será verificado pelo avaliador
  • Será validado que é possível buscar uma notícia pela data com sucesso

  • Será validado que ao buscar por uma data que não existe, o retorno deve ser uma lista vazia

  • Sera validado que ao buscar por uma data com formato inválido, deve lançar um erro ValueError com a mensagem Data inválida.

👣Requisito 8 - Crie a função search_by_tag,

local: tech_news/analyzer/search_engine.py

Esta função irá buscar as notícias por tag.

  • A função deve receber como parâmetro o nome da tag completo.
  • A função deve buscar as notícias do banco de dados por tag.
  • A função deve ter retorno no mesmo formato do requisito anterior.
  • Caso nenhuma notícia seja encontrada, deve-se retornar uma lista vazia.
  • A busca deve ser case insensitive
✍️ Teste manual Abra um terminal Python importando esta função através do comando:

python3 -i tech_news/analyzer/search_engine.py

Agora invoque a função utilizando diferentes parâmetros. Exemplo:

search_by_tag("Tecnologia").

🤖 O que será verificado pelo avaliador
  • Será validado que é possível buscar uma notícia pela tag com sucesso

  • Será validado que ao buscar por uma tag que não existe, o retorno deve ser uma lista vazia

  • Será validado que é possível buscar uma notícia tanto pela tag em maiúsculas como em minúsculas

👣Requisito 9 - Crie a função search_by_category

local: tech_news/analyzer/search_engine.py

Esta função irá buscar as notícias por categoria.

  • A função deve receber como parâmetro o nome da categoria completo.
  • A função deve buscar as notícias do banco de dados por categoria.
  • A função deve ter retorno no mesmo formato do requisito anterior.
  • Caso nenhuma notícia seja encontrada, deve-se retornar uma lista vazia.
  • A busca deve ser case insensitive
✍️ Teste manual

Abra um terminal Python importando esta função através do comando:

python3 -i tech_news/analyzer/search_engine.py

Agora invoque a função utilizando diferentes parâmetros. Exemplo:

search_by_category("Ferramentas").

🤖 O que será verificado pelo avaliador
  • Será validado que é possível buscar uma notícia pela categoria com sucesso

  • Será validado que ao buscar por uma categoria que não existe, o retorno deve ser uma lista vazia

  • Será validado que é possível buscar uma notícia tanto pela categoria em maiúsculas como em minúsculas

#### 👣Requisito local: tech_news/analyzer/ratings.py

Esta função irá listar as cinco notícias mais populares; nosso critério de popularidade será a quantidade de comentários.

  • A função deve buscar as notícias do banco de dados e calcular a sua "popularidade" com base no número de comentários.
  • A função deve ordenar as notícias por ordem de popularidade.
  • Em caso de empate, o desempate deve ser por ordem alfabética de título.
  • A função deve ter retorno no mesmo formato do requisito anterior, porém limitado a 5 notícias.
  • Caso haja menos de cinco notícias, no banco de dados, deve-se retornar todas as notícias existentes;
  • Caso não haja notícias disponíveis, deve-se retornar uma lista vazia.
✍️ Teste manual Abra um terminal Python importando esta função através do comando:

python3 -i tech_news/analyzer/ratings.py

Agora invoque a função utilizando diferentes parâmetros. Exemplo:

top_5_news().

O que será verificado:

  • Será validado que é possível buscar as cinco top notícias
  • Será validado que é possível buscar as cinco top notícias e retornar vazio caso não tenha nenhuma notícia
  • Caso houver menos de 5 notícias, serão retornadas quantas houverem

About

Projeto desenvolvido e proposto no curso da Trybe.


Languages

Language:HTML 99.8%Language:Python 0.2%Language:Shell 0.0%Language:Dockerfile 0.0%