Em nosso post Web Crawler - Python + Beautiful Soup - Parte 1, introduzimos o conceito de web crawler e como pode ser importante extrair informações da web. No post de hoje, vamos construir um RSS Reader com o Python e armazenar o conteúdo extraído em um banco no MongoDB.
Para quem não está familiarizado com o conceito, um RSS é um subconjunto de "dialetos" XML que servem para agregar conteúdo, podendo ser acessado mediante programas ou sites agregadores. É usado principalmente em sites de notícias e blogs. A tecnologia do RSS permite aos usuários da internet se inscreverem em sites que fornecem feeds RSS. Estes são tipicamente sites que mudam ou atualizam o seu conteúdo regularmente. Aqui, vamos coletar e armezar os feeds do Google News, edição US, disponível em https://news.google.com/news/feeds?cf=all&ned=us&hl=en&output=rss.
A biblioteca chave utilizada em nosso código é a feedparser, que pode ser instalada via easy_install feedparser. Assim, vamos importá-la, junto com as demais bibliotecas que usaremos em nosso código.
import feedparser # manipular os feeds
import unicodedata # converter o formato unicode para ASCII
import sys # tratamento de exceções
import pymongo # conexão com o MongoDB
Agora, vamos para a função de coleta dos feeds:
def feadReader():
feedLink = feedparser.parse('https://news.google.com/news/feeds?cf=all&ned=us&hl=en&output=rss')
for entry in feedLink.entries:
try:
a = unicodedata.normalize('NFKD', entry.title).encode('ascii','ignore')
b = unicodedata.normalize('NFKD', entry.published).encode('ascii','ignore')
c = unicodedata.normalize('NFKD', entry.link).encode('ascii','ignore')
writeHeadlines(a,b,c)
except:
print '--- ERRO NA ABERTURA DO FEED ---', sys.exc_info()[0]
continue
Após a definição da função, entramos em um loop criado para executá-la algumas vezes, repetidamente. A função feedparser.parse realiza a coleta e "quebra" do código XML do feed. O resultado é um dicionário de dados contendo as informações. Para percorrer este dicionário, usamos o loop for entry in feedLink.entries e, para cada entry, armazenamos em a o título do feed convertido para ASCII (entry.title), bem como em b temos a data (entry.published). Por fim, em c temos o link da notícia (entry.link). Todos estes são os parâmetros de entrada da função writeHeadlines(), que é a função para armazenar os dados no MongoDB.
Explicando a função de armazenamento, temos:
def writeHeadlines (headline,data,linkF):
# Conectando com o Mongo
connection = pymongo.Connection("mongodb://localhost", safe=True)
# handles para a base de dados
db = connection.news
feeds = db.feeds
query = {'headline':headline, 'data':data, 'link':linkF}
doc = None
try:
doc = feeds.find_one(query) #Se o headline ja existir na base
#altera o valor de doc para não haver novo insert
except:
print '--- ERRO NO findOne() ---', sys.exc_info()[0]
if (doc == None):
doc = {'headline':headline, 'data':data, 'link':linkF}
feeds.insert(doc)
O básico desta função foi explicado em nosso post Python e MongoDB: porque usar e primeiros passos. A grande diferença no post de hoje é o bloco de código
doc = None
try:
doc = feeds.find_one(query) #Se o headline ja existir na base
#altera o valor de doc para não haver novo insert
except:
print '--- ERRO NO findOne() ---', sys.exc_info()[0]
if (doc == None):
doc = {'headline':headline, 'data':data, 'link':linkF}
feeds.insert(doc)
pois começamos com a verificação se aquele feed já está armazenamo no banco, para evitar duplicação de registros. Se já existir um registro igual, o valor de doc é alterado e o bloco do comando feeds.insert não é realizado. Caso contrário, armazenamos a informação no banco. Aqui vale um agradecimento para meu amigo Danilo Ré (@dscorzoni), que me ensinou este truque quando eu ainda estava iniciando meus estudos em MongoDB e Python.
Código completo disponível no GitHub Arte dos Dados - arquivo feed_reader.py
Código completo disponível no GitHub Arte dos Dados - arquivo feed_reader.py
Um abraço e até o próximo post!
0 comentários:
Postar um comentário