23
Parser HTML <Titulo Provisório> Danilo Vaz São Paulo, 05/01/2015 http://unknownsec.wordpress.com

Parser HTML

Embed Size (px)

DESCRIPTION

Apostila sobre parser HTML

Citation preview

Page 1: Parser HTML

 

Parser HTML <Titulo Provisório>    

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 2: Parser HTML

   

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 3: Parser HTML

 Introdução Pré­requisitos Case para uso de um parser HTML Começando a brincar ­ Coleta de dados do IBGE 

O que é um parser? Iniciando a coleta 

Primeiros passos ­ Navegando nos links Entendendo o que foi feito e usado 

Urllib2 BeautifulSoap 

Manipulando pagina HTML e pegando o resultado Gravando dados em um arquivo CSV 

Coleta e parser sistema Itaú Unibanco Preparando para a coleta 

 

   

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 4: Parser HTML

Introdução  De acordo com uma necessidade que eu tive, eu precisei estudar métodos para realizar uma consulta em uma pagina HTML e retornar valores contidos nela de forma automática para inserção em um banco de dados, preencher formulários online e até mesmo realizar trabalhos de web spider  coletando conteúdos relacionados nas páginas. Nessas pesquisas 1

e estudos eu acabei achando métodos para as linguagens JAVA, PERL, PYTHON e PHP. Com elas eu consegui desenvolver e trabalhar as paginas HTML, eu vou mostrar aqui códigos de exemplos em Python para coletar conteúdos. Todos os exemplos descritos nesse paper são cases reais de uso, todos foram usados em alguma parte dos meus projetos.  

Pré-requisitos  Acredito que você que esteja lendo, já tenha um conhecimento de lógica de programação e já programa em alguma linguagem, caso contrário esse conteúdo pode ser um pouco confuso para você.  Todo o conteúdo foi feito utilizando o sistema operacional Debian 7, então utilizarei apenas o Linux e não o Windows. É preciso também um conhecimento básico em Python.  

Case para uso de um parser HTML  Como disse, vou basear esse paper em cases reais de uso, assim acho que o entendimento fica mais simplificado. Digamos que você precise saber alguns dados dos municípios do Brasil para elaborar estratégias para sua empresa, tais como:  

➔ População estimada 2014  ➔ População 2010 ➔ Área da unidade territorial (km²) ➔ Densidade demográfica (hab/km²) ➔ Código do Município ➔ Gentílico ➔ Prefeito 

 

1 Web crawler, em português rastreador web, é um programa de computador que navega pela World Wide Web de uma forma metódica e automatizada. Outros termos para Web crawlers são indexadores automáticos, bots, web spiders, Web robot, ou Web scutter.(Wikipédia) 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 5: Parser HTML

O que vamos fazer é criar um script em Python para acessar a pagina do IBGE onde contém essas informações e armazenar em um arquivo CSV. Então a missão é escrever um script no qual vai acessar a pagina do IBGE (http://cidades.ibge.gov.br/xtras/home.php) e armazenar as informações de cada município para uma eventual estratégia. Esse é apenas um exemplo de uso que vou abordar aqui para vocês, mas temos inúmeras utilidades para se usar um parser ou scrapper como preferirem chamar.  

Começando a brincar - Coleta de dados do IBGE  Antes de começarmos a fazer o código, vamos entender como funciona e o que vamos usar. 

O que é um parser?  “Em ciência da computação e linguística, análise sintática (também conhecida pelo termo em inglês parsing) é o processo de analisar uma sequência de entrada (lida de um arquivo de computador ou do teclado, por exemplo) para determinar sua estrutura gramatical segundo uma determinada gramática formal. Essa análise faz parte de um compilador, junto com a análise léxica e análise semântica. A análise sintática transforma um texto na entrada em uma estrutura de dados, em geral uma árvore, o que é conveniente para processamento posterior e captura a hierarquia implícita desta entrada.” (Wikipédia)  Em resumo ao descritivo acima, parsear uma pagina HTML nada mais é que você analisar os código da pagina e transcrever o conteúdo dela de uma forma que vire uma informação para você.  

Iniciando a coleta

Primeiros passos - Navegando nos links  Antes de mais nada, precisamos saber o que vamos coletar, então, como disse acima, vamos coletar dados dos municípios do Brasil, tais como:  

➔ População estimada 2014  ➔ População 2010 ➔ Área da unidade territorial (km²) ➔ Densidade demográfica (hab/km²) ➔ Código do Município ➔ Gentílico 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 6: Parser HTML

➔ Prefeito  Certo, agora temos que descobrir onde essas informações são encontradas. A estrutura do site para se chegar a essas informações são:  

1. http://cidades.ibge.gov.br/xtras/home.php 2. http://cidades.ibge.gov.br/xtras/uf.php?lang=&coduf=<NUM_ESTADO>&search=<EST

ADO> 3. http://cidades.ibge.gov.br/xtras/perfil.php?lang=&codmun=<COD_MUNICIPIO>&searc

h=<ESTADO>|<MUNICIPIO>  Certo, sabendo que temos 3 tipos de links para obter o conteúdo, já temos uma base para pensar em como desenvolver o código.   Pensando nisso eu comecei com uma estrutura básica do código, nela vamos usar o BeautifulSoup  e urllibs2 . 2 3

 1. #!/usr/bin/python

2. import urllib2

3. from bs4 import BeautifulSoup

4.

5. # Abre a pagina principal do IBGE onde contem os links para os estados.

6. html = urllib2.urlopen('http://cidades.ibge.gov.br/xtras/home.php').read()

7.

8. # Pega o conteudo da pagina em HTML e joga para o BeautifulSoup mapear as tags

9. soup = BeautifulSoup(html)

10.

11. # Apenas um contador para verificar se o loop esta correto e pegando os 27 estados do pais

12. a = 1

13.

14. # For, pegando os links. Ele busca no codigo HTML todas as tags que começam com "<a"

15. # exemplo: <a href="../xtras/uf.php?lang=&coduf=12&search=acre" title="Acre">AC</a></li>

16. # Ele vai buscar todo o conteudo de tags de links

17. for link in soup.find_all('a'):

18. # Aqui podemos ver também que ele faz um get para pegar o conteúdo da href

19. # ou seja, o que estiver entre aspas em href ele vai trazer como texto.

20. # no caso do exemplo acima, ele vai trazer ../xtras/uf.php?lang=&coduf=12&search=acre

21. pagina = link.get('href')

22.

23. # Eu coloquei esse IF para distinguir as URLs, assim ele me traz apenas as URLs

24. # que contem uf.php que é o que nos interessa para pegar os estados.

25. if "uf.php" in pagina:

26.

27. # Aqui foi feito um "pulo do gato" para conseguir extrair o conteudo e fazer uma juncao

28. # com a pagina principal para acessar o link, note que ele traz "../xtras/uf.php?lang=&coduf=12&search=acre"

2 http://www.crummy.com/software/BeautifulSoup/ 3 https://docs.python.org/2/library/urllib2.html 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 7: Parser HTML

29. # o que eu fiz foi fazer um split para separar em um vetor tudo que vem antes de "xtras/" e depois dele.

30. # Assim pegamos apenas o final e concatenamos com o link certo da pagina.

31. pagina = pagina.split('xtras/')[1]

32.

33. # Na variavel abaixo é feita a concatenacao.

34. url = "http://cidades.ibge.gov.br/xtras/"+pagina

35.

36. # Aqui nos abrimos uma nova pagina com o conteudo coletado, assim fica automatico

37. # a navegacao nos links de estados.

38. html = urllib2.urlopen(url).read()

39. print a

40. a+=1

  Source: https://gist.github.com/danilovazb/03fae9a7c4900fa245a3  No source acima, podemos ver que ele faz a navegação nos links a partir do principal que é http://cidades.ibge.gov.br/xtras/home.php  Agora vamos começar a trabalhar isso, o código acima ele apenas mostra no output a contagem dos estados, vamos pega o conteúdo da pagina e começar a tratar agora, ainda temos que acessar os links dos municípios de cada estado.  Acesse uma pagina de algum estado e usando o Google Chrome(Ou qualquer outro de sua preferencia) e clique com o botão direito do mouse a fim de inspecionar elemento, procure pelos municípios e veja o conteúdo do href que eles lhe oferecem, assim vamos conseguir montar a próxima parte do código. Veja na imagem abaixo: 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 8: Parser HTML

  Como podemos ver, eu selecionei o link de Acrelandia(O Acre existe?!?!) e obtemos parte do link que vai nos ajudar a montar a proxima parte do código.  href="perfil.php?lang=&codmun=120001&search=acre|acrelandia"  Depois que achamos algo que nos leve ao link unico, montamos o código, veja abaixo:  

1. #!/usr/bin/python

2.

3. import urllib2

4. from bs4 import BeautifulSoup

5. # Abre a pagina principal do IBGE onde contem os links para os estados.

6. html = urllib2.urlopen('http://cidades.ibge.gov.br/xtras/home.php').read()

7. # Pega o conteudo da pagina em HTML e joga para o BeautifulSoup mapear as tags

8. soup = BeautifulSoup(html)

9. # Apenas um contador para verificar se o loop esta correto e pegando os 27 estados do pais

10. a = 1

11. # For, pegando os links. Ele busca no codigo HTML todas as tags que começam com "<a"

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 9: Parser HTML

12. # exemplo: <a href="../xtras/uf.php?lang=&coduf=12&search=acre" title="Acre">AC</a></li>

13. # Ele vai buscar todo o conteudo de tags de links

14. for link in soup.find_all('a'):

15. # Aqui podemos ver também que ele faz um get para pegar o conteúdo da href

16. # ou seja, o que estiver entre aspas em href ele vai trazer como texto.

17. # no caso do exemplo acima, ele vai trazer ../xtras/uf.php?lang=&coduf=12&search=acre

18. pagina = link.get('href')

19. # Eu coloquei esse IF para distinguir as URLs, assim ele me traz apenas as URLs

20. # que contem uf.php que é o que nos interessa para pegar os estados.

21. if "uf.php" in pagina:

22. # Aqui foi feito um "pulo do gato" para conseguir extrair o conteudo e fazer uma juncao

23. # com a pagina principal para acessar o link, note que ele traz "../xtras/uf.php?lang=&coduf=12&search=acre"

24. # o que eu fiz foi fazer um split para separar em um vetor tudo que vem antes de "xtras/" e depois dele.

25. # Assim pegamos apenas o final e concatenamos com o link certo da pagina.

26. pagina = pagina.split('xtras/')[1]

27.

28. # Na variavel abaixo é feita a concatenacao.

29. url = "http://cidades.ibge.gov.br/xtras/"+pagina

30. # Aqui nos abrimos uma nova pagina com o conteudo coletado, assim fica automatico

31. # a navegacao nos links de estados.

32. html = urllib2.urlopen(url).read()

33.

34. # Agora, fiz basicamente o que está lá em cima no código.

35. # eu estou filtrando novamente os links, mas agora das paginas dos estados

36. soup = BeautifulSoup(html)

37. for link in soup.find_all('a'):

38. pagina = link.get('href')

39.

40. # Um novo IF, agora ele verifica se perfil.php contem no link da pagina, exatamente como o acima.

41. # Lembra que visualizamos na pagina dos estados com o "Inspecionar Elemento" para ver

42. # algo que pudesse fazer a distinção de links, então, achei o "perfil.php"

43. if "perfil.php" in pagina:

44. print a

45. a+=1

  Source: https://gist.github.com/danilovazb/a3736881b82bacee87a7    

Entendendo o que foi feito e usado  Bom, até agora apenas navegamos nos links, vou aprofundar mais em detalhes já que a intenção é entender o que estamos fazendo.  O que usamos até agora foram duas libs, como havia dito acima, usamos o urllib2 e o BeautifulSoup. 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 10: Parser HTML

 

Urllib2 O urllib2 é um módulo do Python que define funções e classes(Objetos) que manipulam URL(s), seja ela uma URL simples baseado no protocolo HTTP, autenticação Digest, envio de dados GET e POST download de arquivos, cookies, sessão etc. (Fonte: http://www.nacaolivre.com.br/python/python­usando­urllib2/)   Achei uma boa explicação a da galera do nacaolivre.com.br e nem precisa falar muito, mas o que basicamente o urllib2 faz é uma manipulação de URL, um bom exemplo de uso dele você pode encontrar no link da matéria acima, no github do Fernando Massanori (https://gist.github.com/fmasanori) ou na pagina de documentação (http://kodumaro.blogspot.com.br/2007/04/beautiful­soup­e­html­scrapping­em.html).   

BeautifulSoap O Beautiful Soup é um parser de HTML/XML para Python que pode transformar até mesmo marcação inválida em uma árvore analítica. Ele provê um modo idiomático de navegar, procurar e modificar a árvore de elementos. (Fonte: http://kodumaro.blogspot.com.br/2007/04/beautiful­soup­e­html­scrapping­em.html)  Como já disse acima, o parser nada mais é que você transformar marcações/tags em um forma legível, o BeautifulSoap pega o conteúdo HTML e faz uma árvore analítica a fim de separar, organizar e disponibilizar o conteúdo de forma que possamos manipular.    Basicamente o que fizemos foi, usar o urllib2 para acessar a pagina principal do IBGE, em seguida manipulamos o resultado HTML com BeautifulSoap a fim de encontrar os links para as paginas de municípios. No nosso código foi feito meio que manual o processo de encontrar os links, afinal, o interesse real é pegar os dados de todos os municípios do Brasil, mas o interessante é que podemos usar desses truques acima para brincar com os links das paginas e fazer igual o Google, ir de link em link, acessando e visualizando as paginas. É dessa forma que o robô do Google faz para maperar as paginas. Claro que com um processamento terrivelmente maior(rsrsrs).  

Manipulando pagina HTML e pegando o resultado  Depois que entendemos como navegar nos links, vamos agora partir para o get dos dados que queremos, vamos continuar com o código feito acima, apenas vamos mudar o final dele, deixando ele de um modo que pegue o resultado das tags que queremos. Antes de escrever nosso código, vamos analisar o modelo da pagina que vamos fazer o get das informações que queremos.  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 11: Parser HTML

Como exemplo, eu vou acessar a pagina de Acrelandia, assim podemos ter uma ideia do que pegar.  http://cidades.ibge.gov.br/xtras/perfil.php?lang=&codmun=120001&search=acre|acrelandia  

  A imagem acima, podemos ver na análise de elementos que os dados que queremos está abaixo das tags <table>, <tbody>, <tr> e dentro da <td>  Certo, primeira parte já temos. Vamos montar um esboço de código para trazer esse resultado. Sabemos as tags que eles se encontram, agora é só selecionar ele com o código, não se preocupe com o código, vou explicar ele detalhado mais pra frente.  

1. #!/usr/bin/python

2. import urllib2

3. from bs4 import BeautifulSoup

4.

5. # Abre a pagina principal do IBGE onde contem os links para os estados.

6. html = urllib2.urlopen('http://cidades.ibge.gov.br/xtras/home.php').read()

7.

8. # Pega o conteudo da pagina em HTML e joga para o BeautifulSoup mapear as tags

9. soup = BeautifulSoup(html)

10.

11. # Apenas um contador para verificar se o loop esta correto e pegando os 27 estados do pais

12. a = 1

13.

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 12: Parser HTML

14. # For, pegando os links. Ele busca no codigo HTML todas as tags que comecam com "<a"

15. # exemplo: <a href="../xtras/uf.php?lang=&coduf=12&search=acre" title="Acre">AC</a></li>

16. # Ele vai buscar todo o conteudo de tags de links

17. for link in soup.find_all('a'):

18. # Aqui podemos ver tambem que ele faz um get para pegar o conteudo da href

19. # ou seja, o que estiver entre aspas em href ele vai trazer como texto.

20. # no caso do exemplo acima, ele vai trazer ../xtras/uf.php?lang=&coduf=12&search=acre

21. pagina = link.get('href')

22.

23. # Eu coloquei esse IF para distinguir as URLs, assim ele me traz apenas as URLs

24. # que contem uf.php que eh o que nos interessa para pegar os estados.

25. if "uf.php" in pagina:

26.

27. # Aqui foi feito um "pulo do gato" para conseguir extrair o conteudo e fazer uma juncao

28. # com a pagina principal para acessar o link, note que ele traz "../xtras/uf.php?lang=&coduf=12&search=acre"

29. # o que eu fiz foi fazer um split para separar em um vetor tudo que vem antes de "xtras/" e depois dele.

30. # Assim pegamos apenas o final e concatenamos com o link certo da pagina.

31. paginaUF = pagina.split('xtras/')[1]

32.

33. # Na variavel abaixo e feita a concatenacao.

34. urlUF = "http://cidades.ibge.gov.br/xtras/"+paginaUF

35.

36. # Aqui nos abrimos uma nova pagina com o conteudo coletado, assim fica automatico

37. # a navegacao nos links de estados.

38. htmlUF = urllib2.urlopen(urlUF).read()

39.

40. # Agora, fiz basicamente o que esta la em cima no codigo.

41. # eu estou filtrando novamente os links, mas agora das paginas dos estados

42. soupUF = BeautifulSoup(htmlUF)

43. print urlUF

44. for link in soupUF.find_all('a'):

45. paginaMun = link.get('href')

46.

47. # Adicionei o TRY para tratar os erros que podem dar, assim ele nao para o programa em tempo de execucao

48. try:

49. # Um novo IF, agora ele verifica se perfil.php contem no link da pagina, exatamente como o acima.

50. # Lembra que visualizamos na pagina dos estados com o "Inspecionar Elemento" para ver

51. # algo que pudesse fazer a distincao de links, entao, achei o "perfil.php"

52. if "perfil.php" in paginaMun and "/estadosat/" not in paginaMun:

53.

54. # As 3 variaveis abaixo, sao basicamente o que fiz acima, eu seleciono a pagina

55. # e faco o request no urllib2 e trato com o beautifulsoap

56. urlMun = "http://cidades.ibge.gov.br/xtras/"+paginaMun

57. htmlMun = urllib2.urlopen(urlMun).read()

58. soupMun = BeautifulSoup(htmlMun)

59.

60. # As variaveis abaixo, sao os dados que queriamos pegar

61. # com calma vou explicar o que cada funcao do BeautifulSoap que usei faz

62. # mas a principio, podemos ver que ela cria um vetor com o conteudo

63. # puxando o resultado.

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 13: Parser HTML

64. popu_estimada2014 = soupMun.find_all('td',{'class': 'desc'})[0].get_text()

65. val_popu_estimada2014 = soupMun.find_all('td',{'class': 'valor'})[0].get_text()

66.

67. popu_estimada2010 = soupMun.find_all('td',{'class': 'desc'})[1].get_text()

68. val_popu_estimada2010 = soupMun.find_all('td',{'class': 'valor'})[1].get_text()

69.

70. uni_territorial = soupMun.find_all('td',{'class': 'desc'})[2].get_text().strip()

71. val_uni_territorial = soupMun.find_all('td',{'class': 'valor'})[2].get_text()

72.

73. dens_demografica = soupMun.find_all('td',{'class': 'desc'})[3].get_text()

74. val_dens_demografica = soupMun.find_all('td',{'class': 'valor'})[3].get_text()

75.

76. cod_municipio = soupMun.find_all('td',{'class': 'desc'})[4].get_text()

77. val_cod_municipio = soupMun.find_all('td',{'class': 'valor'})[4].get_text()

78.

79. gentilico = soupMun.find_all('td',{'class': 'desc'})[5].get_text()

80. val_gentilico = soupMun.find_all('td',{'class': 'valor'})[5].get_text()

81.

82. prefeito = soupMun.find_all('td',{'class': 'desc'})[6].get_text()

83. val_prefeito = soupMun.find_all('td',{'class': 'valor'})[6].get_text()

84.

85. mun = soupMun.find('title').get_text().split("|")[3].strip()

86.

87. # Apenas um print para demonstrar como estao saindo as informacoes

88. # antes de colocar elas em um banco de dados.

89. print mun + "\n" +\

90. popu_estimada2014 + ": " + val_popu_estimada2014 + "\n" +\

91. popu_estimada2010 + ": " + val_popu_estimada2010 + "\n" +\

92. uni_territorial + ": " + val_uni_territorial + "\n" +\

93. dens_demografica + ": " + val_dens_demografica + "\n" +\

94. cod_municipio + ": " + val_cod_municipio + "\n" +\

95. gentilico + ": " + val_gentilico + "\n" +\

96. prefeito + ": " + val_prefeito + "\n"

97.

98. # Uma excessao para caso de erro o programa nao parar.

99. except Exception:

100. pass

  Source: https://gist.github.com/danilovazb/e768c094235c3a0ebbbe  Vamos entender o ultimo código e o que foi feito nele, nesse ultimo eu trabalhei bem com o BeautifulSoap, o urllib2 fez o mesmo trabalho de antes, apenas serviu como um request na página.  Certo, agora vamos detalhar a fim de entender o BeatifulSoap, para ele interpretar a pagina HTML. O que eu fiz foi, quando eu usei o urllib2 para dar o request na pagina (Ex: Linha 6) eu “falei” para o ele o seguinte: 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 14: Parser HTML

html = urllib2.urlopen(“http://site.com.br”).read()   

  Certo, até ai, temos dentro da variável “html” a pagina toda como ela é, ou seja, está o HTML dela lá sem tratar. Agora entra o nosso amigo BeautifulSoap para trabalhar a pagina a fim de extrair as informações que precisamos. Vamos usar a variável html com a página salva em HTML no BeautifulSoap da seguinte forma(Ex: Linha 9):  soup = BeautifulSoup(html)  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 15: Parser HTML

No comando acima eu estou carregando o BeautifulSoup com a variável html dentro de uma nova variável chamada soup. Agora temos a variável soup com o conteúdo da variável html pronto para ser tratado. Vamos percorrer todos os links da página que está salva na variável soup onde já está mapeada pelo nosso amigo BeautifulSoap, para fazer isso, vamos usar um laço condicional FOR (Ex: Linha 17), mas antes, sabemos que a tag que contém hyperlinks no HTML é a <a>, então, vamos forçar o BeautifulSoap a pesquisar em todo o código pelas tags <a> da seguinte maneira:  for link in soup.find_all('a'):  

  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 16: Parser HTML

Assim ele vai preencher a variável link a cada ciclo com o conteúdo da tag <a>, mas ainda assim nós precisamos pegar o link que fica na propriedade href da tag <a>. Se dermos um print da variável link ele vai nos retornar esse output:  

  Para pegar o conteúdo da propriedade href, faremos da seguinte forma(Ex: Linha 21):  pagina = link.get('href')  O que estamos dizendo acima é, pegue o conteúdo do href contido na variável link e jogue para a variável pagina. Agora sim nós temos o conteúdo da propriedade href, ela está armazenada na variável pagina. Mesmo assim, eu tive algumas complicações, pois ele estava pegando todas as tags <a> de hiperlinks e eu queria apenas as que me levassem ao meu objetivo, foi então que precisei entender os links e filtrar. Lembra que na pagina 8 deste paper eu pedi que reparassem no link? Enfim, justamente para notar com detalhe se havia algo que pudéssemos usar em um IF afim de separar somente os links que gostaríamos que o scrapper visitasse. Veja na linha 25 como fiz isso:  if "uf.php" in pagina:  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 17: Parser HTML

O que a linha acima vai fazer, eu disse ao programa o seguinte: Se o resultado da variável pagina contiver uf.php então continue executando o código. Assim eu consigo filtrar o resultado e fazer com que ele acesse os links corretos. Logo abaixo desse IF eu coloquei um “pulo do gato” para montar a URL de acesso aos municípios para conseguir extrair o conteúdo do href e fazer uma junção com a pagina principal para acessar o link, note que ele traz dentro do href o conteúdo "../xtras/uf.php?lang=&coduf=12&search=acre", o que eu fiz foi fazer um split  para separar em um vetor tudo que vem antes de "xtras/" e depois dele. 4

Assim pegamos apenas o final e concatenamos com o link certo da pagina. (Ex: Linha 31 e Linha 34)  31. paginaUF = pagina.split('xtras/')[1]  34. urlUF = "http://cidades.ibge.gov.br/xtras/"+paginaUF  Certo, após isso, foi basicamente CTRL+C e CTRL+V da linha 52 a linha 58. Única diferença fica por conta do IF da linha 52 que coloquei um E(and) condicional para dizer ao IF que eu queria apenas o resultado que tivesse “perfil.php” e rejeitasse tudo que tivesse "/estadosat/" na variável paginaMun. Logo abaixo, da linha 64 a 83 eu criei as variáveis para pegar os dados que queremos, nele eu faço um filtro nas tags da página com o método “find_all” do BeautifulSoap, veja no exemplo abaixo como faço a separação das tags e pego o texto delas.  64. popu_estimada2014 = soupMun.find_all('td',{'class': 'desc'})[0].get_text()

Repare que pedi ao BeautifullSoap para procurar em todo o código da pagina por uma tag que contivesse a estrutura acima, veja no código abaixo.  

  Pedi para ele procurar a tag TD que tivesse a CLASS chamada DESC, mas ele vai trazer todas as tags que contenham as informações que passei dentro de um vetor, sendo assim, vamos identificar nossas informações dentro do vetor, depois que achar o que precisamos, vamos acessar e colocar em variáveis.  64. popu_estimada2014 = soupMun.find_all('td',{'class': 'desc'})[0].get_text()

65. val_popu_estimada2014 = soupMun.find_all('td',{'class': 'valor'})[0].get_text()

4 https://docs.python.org/2/library/stdtypes.html#str.split 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 18: Parser HTML

66. popu_estimada2010 = soupMun.find_all('td',{'class': 'desc'})[1].get_text()

67. val_popu_estimada2010 = soupMun.find_all('td',{'class': 'valor'})[1].get_text()

68. uni_territorial = soupMun.find_all('td',{'class': 'desc'})[2].get_text().strip()

69. val_uni_territorial = soupMun.find_all('td',{'class': 'valor'})[2].get_text()

70. dens_demografica = soupMun.find_all('td',{'class': 'desc'})[3].get_text()

71. val_dens_demografica = soupMun.find_all('td',{'class': 'valor'})[3].get_text()

72. cod_municipio = soupMun.find_all('td',{'class': 'desc'})[4].get_text()

73. val_cod_municipio = soupMun.find_all('td',{'class': 'valor'})[4].get_text()

74. gentilico = soupMun.find_all('td',{'class': 'desc'})[5].get_text()

75. val_gentilico = soupMun.find_all('td',{'class': 'valor'})[5].get_text()

76. prefeito = soupMun.find_all('td',{'class': 'desc'})[6].get_text()

77. val_prefeito = soupMun.find_all('td',{'class': 'valor'})[6].get_text()

 

Gravando dados em um arquivo CSV  Depois que fiz isso, apenas fiz um print das informações como podemos ver da linha 89 a linha 96. Agora que temos todas as informações sendo apresentadas na tela, vamos gravar em um arquivo CSV. Para gravar o conteúdo em um arquivo, vamos mudar um pouco as linhas de 89 a 96 para o código abaixo:  

1. from datetime import datetime #####>>>>> Adicionar no INICIO do script

2. arquivoIBGE = "ResultadoIBGE" + "-" + str(now.day) + str(now.month) + str(now.year) + ".csv"

3. arquivoGrava = open(arquivoIBGE,'a')

4. arquivoGrava.write("%s,%s,%s,%s,%s,%s,%s,%s" % \

5. (mun.strip(),val_popu_estimada2014.strip(),val_popu_estimada2010.strip(),val_uni_territorial.strip(),\

6. val_dens_demografica.strip(),val_cod_municipio.strip(),val_gentilico.strip(),val_prefeito.strip()+"\n")

 Com essas 6 linhas acima, vamos gravar um arquivo chamado ResultadoIBGE­DIAMESANO.csv com os dados que obtivemos do IBGE.    

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 19: Parser HTML

Coleta e parser sistema Itaú Unibanco  Como vimos anteriormente, é bem útil você fazer parser de paginas HTML para adquirir dados e até mesmo elaborar uma estratégia. Dessa vez eu precisei pegar alguns dados do site do Itaú, mas tive problemas com o javascript deles, então, eu dei um “jeitinho brasileiro” para conseguir os dados. Vamos acompanhar abaixo:  O site que gostaria de acessar é o https://www.itau.com.br/pague­aqui/ e coletar os dados de lojas onde possa fazer pagamentos, a missão que foi dada pra mim era coletar esses dados e popular nossa base de dados para ter isso interno na empresa, enfim, fui atrás, missão dada parceiro, é missão cumprida.  

Preparando para a coleta  Para ter uma ideia gráfica do que estou falando, veja a imagem abaixo, eu preciso “selecionar” estado por estado, cidade por cidade, bairro por bairro para que eu possa coletar TODAS as lojas que façam os tipos de “Recebimento e pagamentos por convênios” e de “Produtos e serviços atrelados ao cartão de crédito”.  

  Mas analisando o código da pagina, ela fica atrás de javascript, o que eu fiz para coletar, eu achei os links que geram as informações dessa pagina em JSON, veja abaixo o trecho do código da pagina do Itaú.  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 20: Parser HTML

  Vendo o que eu tinha para acessar era javascript eu realizei novamente a pesquisa e analisei na aba “Network” as conexões que ele faz com o servidor, consegui pegar ali o link correto para conseguir ver o resultado em JSON.  

  Só que se você reparar no link que obtive, alguns dados são substituídos por códigos numéricos.  https://ww18.itau.com.br/wsinvestnet/Corban.asmx/BuscarCorrespondenteBancario?cidade=197921&estado=AC&servico=3&segmento=8&bairro=1330426&nomeFantasiaCorrespondente=&callback=_jqjsp&_1420543918772=  Eu pintei de vermelho os códigos que obtive no link acima, veja que não tem nem como fazer um “brute­force” para descobrir a numeração, é muito número. O que eu fiz, a cada combo­box que selecionava ele me dava o link para o JSON correspondente. Como assim?!?!   Certo, deixa explicar melhor, toda vez que eu selecionava uma opção ele me dava um link para o JSON daquele combo­box, eu atualizer a pagina para limpar as conexões e depois que atualizei eu abri novamente a guia de desenvolvedor e abri a aba network novamente, assim ele “limpa” as conexões, agora, selecionei apenas um combo­box para obter o link, veja na imagem abaixo.  

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 21: Parser HTML

  Certo, agora vamos abrir o link do JSON e descobrir o que temos nele, mas antes, eu selecionei os 2 primeiros campos que pra mim não vão alterar em nada, logo em seguida eu selecionei o campo estado para pegar o link do JSON com todos os estados, veja a imagem abaixo.  

  https://ww18.itau.com.br/wsinvestnet/Corban.asmx/MontarCombosCorbanCidade?estado=AC&servico=3&segmento=8&callback=_jqjsp&_1420545033151=  Certo, entendendo o link acima. Esse link é o de listagem de cidades, podemos ver que temos uma propriedade passando no link chamada “estado”, como sabemos todas as siglas dos estados, nós conseguimos montar um script simples para conseguir coletar as cidades, 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 22: Parser HTML

me adiantando um pouco, o que eu fiz, eu olhei da mesma maneira o link para coletar os bairros, assim montei o script abaixo para coletar os dados.  

1. import urllib2

2. import json

3.

4. UF

=['AC','AL','AM','AP','BA','CE','DF','ES','GO','MA','MG','MS','MT','PA','PB','PE','PI','PR','RJ','RN','RO','RR','RS','SC','SE','SP',

'TO']

5. #UF = ['AC','AL','AM','AP','BA','CE']

6.

7. for estado in UF:

8. #print estado

9. urlCidade = 'https://ww18.itau.com.br/wsinvestnet/Corban.asmx/MontarCombosCorbanCidade?estado=' + estado

+'&servico=3&segmento=8&callback=_jqjsp&_1412367567213='

10.

11. resp = urllib2.urlopen(urlCidade).read()

12. resp =

resp.replace('_jqjsp({"d":"{\\"?xml\\":{\\"@version\\":\\"1.0\\",\\"@encoding\\":\\"utf-8\\"},\\"root\\":{\\"listaCidade\\":{\\"row\

\":','[')

13. resp = resp.replace('}}}"});',']')

14. resp = resp.replace('\\','')

15. resp = resp.replace('[[{"','[{"')

16. resp = resp.replace('"}]]','"}]')

17.

18. for mun in json.loads(resp.decode('utf-8')):

19. #print estado + " - " + mun['DescricaoMunicipio'].strip() + " - " + mun['CodigoMunicipio']

20. codMun = mun['CodigoMunicipio']

21. municip = mun['DescricaoMunicipio'].strip()

22. urlCidade = 'https://ww18.itau.com.br/wsinvestnet/Corban.asmx/MontarCombosCorbanBairro?codCidade=' + codMun

+'&estado=' + estado + '&servico=3&segmento=8&callback=_jqjsp&_1412624740327='

23. respA = urllib2.urlopen(urlCidade).read()

24. respA =

respA.replace('_jqjsp({"d":"{\\"?xml\\":{\\"@version\\":\\"1.0\\",\\"@encoding\\":\\"utf-8\\"},\\"root\\":{\\"listaBairro\\":{\\"row

\\":','[')

25. respA = respA.replace('}}}"});',']')

26. respA = respA.replace('\\','')

27. respA = respA.replace('[[{"','[{"')

28. respA = respA.replace('"}]]','"}]')

29.

30. #print respA

31. try:

32. if 'null' in respA:

33. urlCorrespondente

='https://ww18.itau.com.br/wsinvestnet/Corban.asmx/BuscarCorrespondenteBancario?cidade=' + codMun + '&estado=' + estado

+'&servico=3&segmento=8&bairro=Bairro&nomeFantasiaCorrespondente=&callback=_jqjsp&_1412625558140='

34. respB = urllib2.urlopen(urlCorrespondente).read()

35. respB =

respB.replace('_jqjsp({"d":"{\\"?xml\\":{\\"@version\\":\\"1.0\\",\\"@encoding\\":\\"utf-8\\"},\\"root\\":{\\"listaCorrespondente\\"

:{\\"row\\":','[')

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com 

Page 23: Parser HTML

36. respB = respB.replace('}}}"});',']')

37. respB = respB.replace('\\','')

38. respB = respB.replace('[[{"','[{"')

39. respB = respB.replace('"}]]','"}]')

40. respB = respB.replace('{"@xml:space":"preserve","#significant-whitespace":" "}','" "')

41. #print respB

42. for correspondente in json.loads(respB.decode('utf-8')):

43. print estado + " - " + municip + " - " + codMun + " - " + bairro['DescricaoBairro'].strip()

+ " - " + bairro['CodigoBairro'] + " - " + correspondente['NomeFantasiaCorrespondente'].strip()+ " - " +

correspondente['CnpjCorrespondente'] + " - " + correspondente['DescricaoEnderecoCorrespondente'].strip()

44. else:

45. for bairro in json.loads(respA.decode('utf-8')):

46. codBairro = bairro['CodigoBairro']

47. urlCorrespondente

='https://ww18.itau.com.br/wsinvestnet/Corban.asmx/BuscarCorrespondenteBancario?cidade=' + codMun + '&estado=' + estado

+'&servico=3&segmento=8&bairro=' + codBairro + '&nomeFantasiaCorrespondente=&callback=_jqjsp&_1412625558140='

48. respB = urllib2.urlopen(urlCorrespondente).read()

49. respB =

respB.replace('_jqjsp({"d":"{\\"?xml\\":{\\"@version\\":\\"1.0\\",\\"@encoding\\":\\"utf-8\\"},\\"root\\":{\\"listaCorrespondente\\"

:{\\"row\\":','[')

50. respB = respB.replace('}}}"});',']')

51. respB = respB.replace('\\','')

52. respB = respB.replace('[[{"','[{"')

53. respB = respB.replace('"}]]','"}]')

54. respB = respB.replace('{"@xml:space":"preserve","#significant-whitespace":" "}','" "')

55. respB = respB.replace(', ',' ')

56. # print respB

57. for correspondente in json.loads(respB.decode('utf-8')):

58. print estado + " - " + municip + " - " + codMun + " - " +

bairro['DescricaoBairro'].strip() + " - " + bairro['CodigoBairro'] + " - " + correspondente['NomeFantasiaCorrespondente'].strip()+

" - " + correspondente['CnpjCorrespondente'] + " - " + correspondente['DescricaoEnderecoCorrespondente'].strip()

59. except Exception:

60.

print"_______________________________________________________________________________________________________________"

61. pass

 Source: https://gist.github.com/danilovazb/4fc06732cd7b0a40c315  Outra coisa muito importante, o formato que o banco adotou foi o JSONP, o que eu fiz para facilitar minha vida foi remover as tags que são parte do JSONP e deixei ele no formato do JSON para o parser ser efetivo. 

Danilo Vaz São Paulo, 05/01/2015 

http://unknownsec.wordpress.com