Baixe o app para aproveitar ainda mais
Prévia do material em texto
Portal Fóruns 7Masters Revista MacMagazine iMasters Shop Cursos Online Vagas para Devs Eventos: PHP Experience iMasters JS Experience Android Conf /DESENVOLVIMENTO DESENVOLVIMENTO, LINGUAGENS Charming Python: Fácil Coleta de Dados da Web com Mechanize e Beautiful Soup Por developerWorks Brasil em 21/09/2010 CURTIRAM0 0 SHARES COMPARTILHE! Para coletar dados de páginas da Web, a biblioteca mechanize automatiza a análise e a interação com Web sites. O mechanize permite preencher formulários e configurar e salvar cookies e oferece outras ferramentas variadas para fazer um script Python se parecer com um navegador da Web genuíno para um Web site interativo. Uma ferramenta associada frequentemente usada chamada Beautiful Soup ajuda um programa Python a entender o confuso “quase HTML” que Web sites tendem a conter. Escrever scripts para interagir com Web sites é possível com os módulos básicos do Python, mas prefira não fazer isso se não for preciso. Os módulos urllib e urllib2 no Python 2.x, junto com os subpacotes urllib.* em Python 3.0, fazem uma tarefa transitável de busca de recursos nas extremidades de URLs. Porém, quando você deseja fazer qualquer tipo de interação moderadamente sofisticada com o conteúdo que localiza em uma página da Web, você realmente precisa da biblioteca mechanize. Uma das grandes dificuldades com a automação de análise da Web ou outras simulações de interação do usuário com Web sites é o uso do servidor de cookies para controlar o progresso da sessão. Obviamente, os cookies fazem parte de cabeçalhos HTTP e são inerentemente visíveis quando urllib abre recursos. Além disso, os módulos padrão Cookie (http.cookie em Python 3) e cookielib (http.cookiejar em Python 3) ajudam na manipulação desses cabeçalhos em um nível mais alto do que o processamento de texto bruto. Mesmo assim, fazer esta manipulação neste nível é mais incômodo do que necessário. A biblioteca mechanize /DESIGN /DEV /BD /MKT DIGITAL /INFRA + IMASTERS SHOP Facebook Twitter NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais seu nome seu e-mail ENVIAR X considera esta manipulação em um nível mais alto de abstração e permite que o seu scriptou seu shell Python interativoaja de maneira muito parecida com um navegador da Web real. O mechanize do Python é inspirado pelo WWW:Mechanize do Perl, que tem uma gama de recursos parecida. É claro que, como um Pythonista de longa data, eu acho o mechanize mais robusto, o que parece seguir o padrão geral das duas linguagens. Um amigo íntimo do mechanize é a igualmente excelente biblioteca Beautiful Soup. Ela é um ótimo “parser medíocre” para códigos HTML não estritamente válidos que você frequentemente encontra em páginas da Web reais. Você não precisa usar o Beautiful Soup com o mechanize, nem vice-versa, mas, mais frequentemente do que o contrário, você desejará usar as duas ferramentas juntas à medida que interagir com a “Web existente de verdade”. Um exemplo da vida real Eu uso o mechanize em vários projetos de programação. O mais recente foi um projeto para reunir uma lista de nomes correspondentes a alguns critérios de um Web site popular. Este site vem com alguns recursos de busca, mas não vem com nenhuma API oficial para executar tais buscas. Ainda que os leitores possam conseguir imaginar mais especificamente o que eu estava fazendo, eu mudarei aspectos específicos do código que vou apresentar para evitar fornecer informações em excesso sobre o site analisado ou sobre meu cliente. De forma geral, código muito parecido com o que eu apresento será comum para tarefas similares. Ferramentas para iniciar No processo de desenvolvimento real de código de análise da Web, eu acho inestimável poder efetuar peek, poke e prod no conteúdo das páginas da Web de uma maneira interativa para descobrir o que realmente ocorre em páginas da Web relacionadas. Geralmente, esses são conjuntos de páginas dentro de um site, que são gerados dinamicamente a partir de consultas (mas, por isso, tendo padrões consistentes) ou são pré-gerados seguindo modelos razoavelmente rígidos. Uma maneira valioso de fazer esta experimentação interativa é usar o próprio mechanize dentro de um shell Python, especificamente dentro de um shell aprimorado como o IPython (consulte Recursos ao final do artigo para obter um link). Ao fazer a exploração desta maneira, é possível solicitar vários recursos vinculados, enviar formulários, manter ou manipular cookies de site e assim por diante, antes de gravar seu script final que executa a interação que você deseja em produção. NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais Porém, eu acredito que grande parte da minha interação experimental com Web sites é mais bem executada dentro de um real navegador da Web moderno. Visualizar uma página convenientemente renderizada fornece um gestalt muito mais rápido de o que está acontecendo com uma determinada página ou formulário. O problema é que renderizar uma página sozinha somente fornece metade da história, talvez menos que a metade. Ter a “origem de página” o leva um pouco mais adiante. Para realmente entender o que está por trás de uma determinada página da Web ou de uma sequência de interações com um servidor da Web, acho que é necessário mais. Para chegar tão fundo, geralmente eu uso o Firebug ou plug-ins Web Developer para Firefox (ou o menu integrado opcional Develop nas versões recentes do Safari, mas isso é para um público diferente). Todas essas ferramentas permitem fazer coisas como revelar campos de formulário, mostrar senhas, examinar o DOM de uma página, efetuar peek em Javascript ou executar Javascript, observar tráfego Ajax e mais. Comparar os benefícios e peculiaridades dessas ferramentas é um outro artigo completo, mas familiarize-se com eles se você faz qualquer programação orientada para Web. Seja qual for a ferramenta específica que você experimente com um Web site com o qual deseja automatizar a interação, provavelmente você gastará mais horas descobrindo o que, de fato, um site está fazendo do que escrevendo o código mechanize incrivelmente compacto necessário para executar sua tarefa. A análise de resultado da procura Para os propósitos do projeto que eu mencionei acima, eu dividi meu script de centenas de linhas em duas funções: Eu organizei o script desta maneira como uma conveniência de desenvolvimento; quando eu iniciei a tarefa, sabia que precisaria descobrir como fazer cada uma dessas duas coisas. Eu tinha noção de que as informações que eu queria estavam em uma coleta geral de páginas, mas eu ainda não havia examinado o layout específico dessas páginas. Ao recuperar primeiro um lote de páginas e somente salvá-las em disco, eu poderia voltar à tarefa de extrair as informações Recuperar todos os resultados que me interessam Extrair as informações que me interessam a partir dessas páginas recuperadas NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais do meu interesse desses arquivos salvos. É claro que, se a sua tarefa envolver o uso dessas informações recuperadas para formular novas interações dentro da mesma sessão, você precisará usar uma sequência um pouco diferente de etapas de desenvolvimento. Desta forma, primeiro, vamos dar uma olhada em minha função fetch(): Lista 1. Buscando o conteúdo da página import sys, time, os from mechanize import Browser LOGIN_URL = 'http://www.example.com/login' USERNAME = 'DavidMertz' PASSWORD = 'TheSpanishInquisition' SEARCH_URL= 'http://www.example.com/search?' FIXED_QUERY = 'food=spam&' 'utensil=spork&' 'date=the_future&' VARIABLE_QUERY = ['actor=%s' % actor for actor in ('Graham Chapman', 'John Cleese', 'Terry Gilliam', 'Eric Idle', 'Terry Jones', 'Michael Palin')] def fetch(): result_no = 0 # Number the output files br = Browser() # Create a browser br.open(LOGIN_URL) # Open the login page br.select_form(name="login") # Find the login form br['username'] = USERNAME # Set the form values br['password'] = PASSWORD resp = br.submit() # Submit the form # Automatic redirect sometimes fails, follow manually when needed if 'Redirecting' in br.title(): resp = br.follow_link(text_regex='click here') # Loop through the searches, keeping fixed query parameters for actor in in VARIABLE_QUERY: # I like to watch what's happening in the console print >> sys.stderr, '***', actor # Lets do the actual query now br.open(SEARCH_URL + FIXED_QUERY + actor) # The query actually gives us links to the content pages we like, # but there are some other links on the page that we ignore nice_links = [l for l in br.links() NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais if 'good_path' in l.url and 'credential' in l.url] if not nice_links: # Maybe the relevant results are empty break for link in nice_links: try: response = br.follow_link(link) # More console reporting on title of followed link page print >> sys.stderr, br.title() # Increment output filenames, open and write the file result_no += 1 out = open(result_%04d' % result_no, 'w') print >> out, response.read() out.close() # Nothing ever goes perfectly, ignore if we do not get page except mechanize._response.httperror_seek_wrapper: print >> sys.stderr, "Response error (probably 404)" # Let's not hammer the site too much between fetches time.sleep(1) Tendo feito minha exploração interativa deste site de interesse, eu descubro que as consultas que eu desejo executar possuem alguns elementos fixos e alguns elementos variáveis. Eu simplesmente as concateno juntas em um grande pedido GET e dou uma olhada na página “resultados”. Em troca, essa lista de resultados contém links para os recursos que eu realmente desejo. Assim, eu os sigo (com alguns blocos try/except lançados para o caso de alguma coisa não funcionar ao longo do caminho) e salvo qualquer coisa que localizar nessas páginas de conteúdo. Bem simples, não? O mechanize pode fazer mais que isso, mas este pequeno exemplo mostra uma ampla gama de seus recursos. Processando os resultados Neste ponto, terminamos com o mechanize; tudo o que falta é compreender esse monte de arquivos HTML que salvamos durante o loop fetch() . A natureza do processo em lote nos permite separá-los de forma limpa, mas, obviamente, em um programa diferente, fetch() e process() pode interagir mais intimamente. O Beautiful Soup torna o pós-processamento ainda mais fácil que a busca inicial. Para esta tarefa em lote, desejamos produzir dados tabulares de valores separados por vírgula (CSV) a partir de algumas pequenas coisas que encontramos nessas várias páginas da Web que buscamos. Lista 2. Criando dados ordenados a partir de um conjunto de dados randômicos com a Beautiful Soup NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais from glob import glob from BeautifulSoup import BeautifulSoup def process(): print "!MOVIE,DIRECTOR,KEY_GRIP,THE_MOOSE" for fname in glob('result_*'): # Put that sloppy HTML into the soup soup = BeautifulSoup(open(fname)) # Try to find the fields we want, but default to unknown values try: movie = soup.findAll('span', {'class':'movie_title'})[1].contents[0] except IndexError: fname = "UNKNOWN" try: director = soup.findAll('div', {'class':'director'})[1].contents[0] except IndexError: lname = "UNKNOWN" try: # Maybe multiple grips listed, key one should be in there grips = soup.findAll('p', {'id':'grip'})[0] grips = " ".join(grips.split()) # Normalize extra spaces except IndexError: title = "UNKNOWN" try: # Hide some stuff in the HTML <meta> tags moose = soup.findAll('meta', {'name':'shibboleth'})[0]['content'] except IndexError: moose = "UNKNOWN" print '"%s","%s","%s","%s"' % (movie, director, grips, moose) O código aqui em process() é uma primeira visualização impressionista do Beautiful Soup. Os leitores devem ler sua documentação para saber mais sobre detalhes do módulo, mas a sensação geral é bem representada neste fragmento. A maioria do código soup consiste em algumas chamadas .findAll() em uma página que pode ser apenas HTML aproximadamente bem formatado. Lançados aqui, estão alguns atributos .parent, nextSibling e previousSibling parecidos com DOM. Eles são semelhantes ao modo “quirks” de navegadores da Web. O que localizamos no soup não é bem uma árvore de análise; se parece mais com um saco cheio de vegetais que podem entrar na sopa (para forçar uma metáfora). Conclusão NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais Pessoas antiquadas como eu, e mesmo alguns leitores mais jovens, se lembrarão do grande deleite do script com TCL Expect (ou com seus semelhantes escritos em Python e muitas outras linguagens). Automatizar a interação com shells, incluindo os remotos como telnet, ftp, ssh e parecidos, é relativamente direto desde que tudo seja exibido na sessão. A interação da Web é um pouco mais sutil quanto às informações que são divididas entre cabeçalhos e corpos, e vários recursos dependentes são frequentemente compactados juntos com links href , quadros, Ajax, e assim por diante. Em princípio, porém, você poderia somente usar uma ferramenta como wget para recuperar cada byte que um servidor da Web poderia fornecer e, então, executar o mesmo estilo dos scripts Expect como com outros protocolos de conexão. Na prática, poucos programadores são tão comprometidos com abordagens antigas como a minha abordagem sugerida de wget + Expect. O mechanize ainda tem muito da mesma sensação familiar e confortante daqueles bons scripts Expect e é tão fácil de escrever quanto eles, se não for mais fácil. Os comando do objeto Browser() como .select_form(), .submit() e .follow_link() são, realmente, a maneira mais simples e mais óbvia de dizer “procure por isso e envie aquilo” enquanto compacta toda a beleza do estado sofisticado e da manipulação de sessão que gostaríamos em uma estrutura de automação da Web. Recursos Aprender Obter produtos e tecnologias “Criar um Web spider no Linux” discute os Web spiders e analisadores e mostra como construir vários scrapers simples usando o Ruby. “Debug and tune applications on the fly with Firebug” mostra como usar o Firebug para ir muito além da visualização da origem da página para aplicativos da Web e do Ajax. “Using Net-SNMP and IPython” detalha como o IPython e o Net-SNMP podem se combinar para fornecer gerenciamento de rede interativo baseado em Python. Na zona Linux do developerWorks,encontre mais recursos para desenvolvedores Linux e confira nossos mais populares artigos e tutoriais. Consulte todas as dicas de Linux e os tutoriais do Linux no developerWorks. Mantenha-se atualizado com os eventos técnicos e Webcasts do developerWorks. Faça o download do mechanize e de sua documentação. Faça o download do Beautiful Soup e de sua documentação. IPython é uma versão maravilhosamente aprimorada do shell interativo nativo do NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais Discutir artigo publicado originalmente no developerWorks Brasil, por David Mertz Para David Mertz, o mundo todo é um teste; ele devota sua carreira a fornecer instruções de testes marginais. Para saber mais sobre sua carreira, consulte sua página pessoal na Web. Ele escreve as colunas Charming Python e XML Matters do developerWorks desde 2000. Consulte seu livro, Text Processing in Python. É possível entrar em contato com David em mertz@gnosis.cx. Mais Lidos da Última Semana Python que pode fazer coisas bem singulares como auxiliar em cálculos de paralelização; eu o uso principalmente por seus auxílios de interatividade como colorização de código, rechamada de linha de comandos melhorada, conclusão de guia, recursos de macro e ajuda interativa melhorada. É possível instalar o Firebugque oferece uma abundância de ferramentas de edição, depuração e monitoramento de desenvolvimento na Web ao alcance de suas mãos enquanto você navega diretamente do menu Tools/Add-ons do Firefox 3.0+. É possível incluir a Web Developer extensionque inclui um menu e uma barra de ferramentas no navegador com várias ferramentas de desenvolvedor da Web da mesma forma. Com o software de avaliação IBM, disponível para download diretamente do developerWorks, construa seu próximo projeto de desenvolvimento no Linux. Participar do fórum de discussão. Participe da comunidade do My developerWorks; com seu perfil pessoal e a página inicial customizada, é possível padronizar o developerWorks para seus interesses e interagir com outros usuários do developerWorks. CURTIU? 0 COMPARTILHE! Clojure Por Uncle Bob Programação Funcional Pragmática Análise de Dados Por Uber Engineering Criando análises de dados com o Presto e o Parquet na Uber Desenvolvimento Por Pedro Minatel Sensor DS18B20 com ESP8266 e tago.io Desenvolvimento Por Thiago Adriano Conhecendo a fundo a estrutura de um projeto criado com o Angular Cli .NET Por Jéssica Nathany Segurança em aplicações Web .NET com o guia OWASP TOP 10 Desenvolvimento Por Redação iMasters Desenvolvimento de soluções cognitivas IoT para detecção de anomalias através de deep learning 2 Deixe um comentário! O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com * Comentando como Anônimo Qual é o seu nome? Qual é o seu e-mail? 1 2 3 4 5 6 NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais Postar comentário Participe da discussão, lembre-se de ser respeitoso e construtivo :) Muito bom artigo! Responder 21 de setembro de 2010 às 15:09 0 Bom artigo mas tem um erro logo na primeira linha do código. O “from mechanize” ficou na 1a linha é na verdade o começo da segunda linha (“from mechanize import Browser”). Seria legal corrigir ou pelo menos, deixar o comentário por aqui caso alguém tente e não consiga rodar. Responder Carlos Ribeiro 21 de outubro de 2010 às 9:39 0 developerWorks Brasil 217 ARTIGOS 0 CURTIDAS 333 SHARES é o portal de tecnologia da IBM para profissionais de TI de todo o mundo. Colabore, aprenda a criar aplicativos inovadores e compreenda tecnologias avançadas. Acesse mais artigos e tutoriais em www.ibm.com/developerworks/br Saiba Mais Últimos artigos de developerWorks Brasil Agile 15/08/2013 às 09:08 Como sobreviver com requisitos de compliance em projetos ágeis?1 Desenvolvimento 12/08/2013 às 14:08 Saindo do básico com Git2 Desenvolvimento 08/08/2013 às 14:08 Desenvolva um aplicativo de análise e visualização de texto3 Acompanhe o iMasters em tempo real > Este projeto é mantido e patrocinado pelas empresas: NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais Hospedado por: Capacitação e Seleção: Desenvolvimento Agile Ajax Análise de Dados CakePHP CSS Front End HTML Java JavaScript PHP Python Ruby Design 3ds max Acessibilidade Arquitetura de Informação Design Responsivo Games Usabilidade User Experience Banco de dados Interbase MongoDB MySQL Oracle PostgreSQL SQL Server Infra e Cloud Cloud Computing Linux Microsoft Azure Segurança Site Blindado Marketing Digital Conteúdo Digital E-commerce E-mail Marketing Mercado Publicidade Online Redes Sociais Tendências Mobile Android iPhone & iPad Agenda Fórum 7Masters InterCon Revista iMasters Cursos Online Hospedado por Empresa de Recrutamento e Seleção do Grupo iMasters Sobre o iMasters Política de Privacidade Fale conosco iMasters.com Twitter Facebook Google Plus LinkedIn NEWSLETTER Fique por dentro de todas as novidades, eventos, cursos e muito mais
Compartilhar