Skip to content

Instantly share code, notes, and snippets.

@magnunleno
Last active September 26, 2015 18:37
Show Gist options
  • Save magnunleno/1141065 to your computer and use it in GitHub Desktop.
Save magnunleno/1141065 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from platform import architecture
from BeautifulSoup import BeautifulSoup
import urllib2
from sys import argv
BASE_URL = "http://vabs.archlinux-br.org/"
if '64bit' == architecture():
BASE_URL += "x86_64/"
else:
BASE_URL += "i686/"
REPOS = (
'community-testing',
'community',
'core',
'extra',
'kde-unstable',
'multilib',
'testing',
)
def valida_args():
if len(argv) <= 2 or len(argv) > 3:
# Argumentos de menos ou de mais
print "Por favor informe os argumentos corretamente"
print "Utilização: vabs-tool [-s|-d] <nome_do_pacote>\n"
exit(1)
if argv[1] not in ("-d", "-s"):
# Argumento desconhecido
print "Por favor informe uma das seguintes opções: -d ou -s\n"
exit(1)
if argv[1] == "-d":
# Função a ser criada
baixa_pacote(argv[2])
else:
# Função a ser criada
busca_pacote(argv[2])
def busca_pacote_em(repo, nome_pkt):
'''
Função repensável por buscar e imprimir todos os pacotes que coincidem
com o nome informado pelo usuário.
'''
# URL é $BASE_URL/$repo/$letra_M/
url = BASE_URL + repo + "/" + nome_pkt[0].upper() + "/"
# onde:
# -BASE_URL: vabs.archlinux-br.org/ seguido pela arquitetura
# que pode ser x86_64 ou i686
# -repo: É o nome do repositório (valores da tupla REPO)
# -letra_M: Primeira letra do nome do pacote em Maiúsculo
# Baixa a página indicada pela variável url
try:
# A página pode não ser encontrada (404) uma vez que nem todas as
# letras constam em todos os repos.
resposta = urllib2.urlopen(url)
except urllib2.HTTPError as err:
# Se o erro for diferente de 404 (não encontrado) mostra a exceção
if '404' not in str(err):
raise err
# Finaliza a execução da função.
return
# Processa a resposta com a biblioteca BeautifulSoup
html = resposta.read()
soup = BeautifulSoup(html)
# Busca todos os elementos do tipo a
# Isto porque (se você olhar o código fonte da página do vABS
# verá que) todo pacote esta dentro de uma tag <a href=""></a>
for line in soup.findAll('a'):
# Converte o objeto para string
line = str(line)
if '[DIR]' not in line:
# Descarta todas as linhas que não tenham o texto [DIR].
# Esse texto faz parte do elemento alt dos links dos pacotes
continue
if 'parent' in line:
# Descarta o 'parent folder' que também é identificado por [DIR]
continue
# Retira o somente o texto entre aspas (") da linha encontrada
line = line[line.index('"')+1:]
line = line[:line.index('"')]
if nome_pkt in line:
# Imprime os pacotes encontrados no formato "nome_repo/nome_pkt"
print repo+"/"+line[:-1]
def busca_pacote(nome_pkt):
for repo in REPOS:
busca_pacote_em(repo, nome_pkt)
def valida_url(url):
'''
Requisita uma página e retorna True caso ela exista e
Fale caso não exista.
'''
try:
urllib2.urlopen(urllib2.Request(url))
return True
except:
return False
def baixa(url):
'''
Responsável por tentar baixar um arquivo do vABS para o diretório corrente.
'''
# Inicia a variável resposta
resposta = None
# Separa o nome do arquivo para utilizar na criação do arquivo de destino
nome = url.split("/")[-1]
# Instrução try utilizada para "captar" qualquer erro de página
# Uma página pode não ser encontrada (404) uma vez que nem todas as
# letras constam em todos os repos.
try:
# Solicita a página através do módulo urllib2
resposta = urllib2.urlopen(url)
except urllib2.HTTPError as err:
if '404' not in str(err):
# Se o erro for diferente de 404 (não encontrado) mostra uma
# exceção não tratada
raise err
# Finaliza a execução da função caso o erro seja 404
print "Pacote não encontrado:", nome
print "URL buscada:",url
return
# Cria uma arquivo vazio (em modo binário) no diretório corrente
f = open(nome, 'wb')
# Obtêm metadados da página para deduzir a porcentagem do download
meta = resposta.info()
# Converte para int o tamanho do arquivo
tamanho = int(meta.getheaders("Content-Length")[0])
print "Realizando Download: %s Bytes: %s" % (nome, tamanho)
# Inicia a variável que indica quantos bytes já foram baixados
tamanho_baixado = 0
# Tamanho do bloco (8 KBytes)
tamanho_bloco = 8192
while True:
# Lê 8 KBytes do servidor
buffer = resposta.read(tamanho_bloco)
# Caso a resposta esteja vazia, significa que o download acabou
if not buffer:
# fim do download
break
# Incrementa o tamanho baixado com o tamanho de buffer
tamanho_baixado += len(buffer)
# Escreve o conteúdo baixado no arquivo
f.write(buffer)
# Cria linha de status
status = r"%10d [%3.2f%%]" % \
(tamanho_baixado, tamanho_baixado * 100.0/tamanho)
# Adiciona à linha de status alguns caracteres de backspace
# (0x8 na tabela ASCII). Isso faz com que ele volte para o
# início da linha, assim criamos uma "barra de progresso"
status = status + chr(8)*(len(status)+1)
print status,
f.close()
def baixa_pacote(nome_pkt):
'''
Função utilizada para solicitar a verificação de links e o download
do pacote tgz.
Ela é dividida em 2 pelo primeiro if:
- A parte do if é executada quando o usuário informa um pacote com
seu respectivo repositório: "nome_repo/nome_pkt". Essa parte é
responsável por separar o nome do repositório e do pacote e chamar
a função "baixa".
- Já a parte do else é executada quando o usuário não informa o nome
do repositório e força a aplicação a buscar o pacote em todos os
repositórios. A função joga todas as ocorrência exatas do pacote
e adiciona-o em uma lista. Ao final é verificado se essa lista possui:
- uma ocorrência: baixa essa única ocorrência
- nenhuma ocorrência: emite uma mensagem de erro
- mais de uma: e emite uma mensagem de inconsistência.
'''
if '/' in nome_pkt:
#Nome do pacote inclui o repositório
repo, nome_pkt = nome_pkt.split("/")
# Cria a URL
url = BASE_URL + repo + "/" + nome_pkt[0].upper() + "/" + nome_pkt + \
"/" + nome_pkt + ".tgz"
# Solicita o Download
baixa(url)
else:
print "Repositório não especificado"
print "Buscando pacote nos repositórios..."
repos_encontrados = []
for repo in REPOS:
# Cria URL para o repo/pacote desta interação
url = BASE_URL + repo +"/"+ nome_pkt[0].upper() +\
"/" + nome_pkt + "/" + nome_pkt + ".tgz"
# Solicita verificação da URL
if valida_url(url):
# Se ela existir insere na lista
repos_encontrados.append(repo)
# Pacote não encontrado em nenhum repositório
if len(repos_encontrados) == 0:
print "\nNão foi possível encontrar o pacote em nenhum repositório.\n"
return
# Pacote encontrado em mais de um repositório
if len(repos_encontrados) != 1:
print "\nNão foi possível baixar o pacote pois ele existe em mais "+\
"de um repositório."
print "Repositorios encontrados:", ", ".join(repos_encontrados)
return
# Apenas um pacote encontrado. Extrai o nome e adiciona a barra
repo = repos_encontrados[0] + "/"
# Monta a URL
url = BASE_URL + repo + nome_pkt[0].upper() + "/" + nome_pkt + "/" + nome_pkt + ".tgz"
# Solicita o download do pacote
baixa(url)
if __name__ == '__main__':
valida_args()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment