在Python中如何使用多个刮表?

时间:2018-02-25 15:44:30

标签: python html web-scraping beautifulsoup

在Python 3中,我需要在表格中的网站上抓取大量信息(第一个网站是:http://www.portaltransparencia.gov.br/ceis?pagina=1

from bs4 import BeautifulSoup
import requests
from time import sleep

def sopa(link):
    res = requests.get(link)
    sopa =  BeautifulSoup(res.text, "lxml")
    blocos = sopa.findAll("tr", {"class": "nome-divergente"})
    return blocos

planilha = []
for i in range(1,819):
    link = "http://www.portaltransparencia.gov.br/ceis?pagina="
    link = link + str(i)
    print(link)
    blocos = sopa(link)
    sleep(random.uniform(0.2, 10))
    conta = 0
    print(blocos)
    input("# This is the content of blocos")
    for linha in blocos:
        if conta > 0:
            cnpj = linha.find("a").text.strip()
            link = linha.find("href")
            nome = linha.find("td")[1].text.strip()
            tipo = linha.find("td")[2].text.strip()
            data = linha.find("td")[3].text.strip()
            nome_orgao = linha.find("td")[4].text.strip()
            uf = linha.find("td")[5].text.strip()
            dicionario = {"cnpj": cnpj, "link": link, "nome": nome, "tipo": tipo, "data": data, "nome_orgao": nome_orgao, "uf": uf}
            print(dicionario)
            planilha.append(dicionario)
        conta = conta + 1

显示的内容:

http://www.portaltransparencia.gov.br/ceis?pagina=1
[<tr class="nome-divergente">
<td>
<a href="/ceis/empresa/08307727000128">
                                08.307.727/0001-28
                            </a>
</td>
<td> TECK SHOCK COMERCIO E SERVICO EIRELI  - ME   ** </td>
<td>Suspensão - Lei de Licitações</td>
<td>16/05/2018</td>
<td>Governo do Estado do Espírito Santo (ES)</td>
<td>ES</td>
</tr>, <tr class="nome-divergente">
<td>
<a href="/ceis/empresa/05236586000101">
                                05.236.586/0001-01
                            </a>
</td>
<td> META TERCEIRIZACOES E SERVICOS LTDA   ** </td>
<td>Suspensão - Legislação Estadual</td>
<td>26/12/2018</td>
<td>Governo do Estado da Bahia</td>
<td>BA</td>
</tr>, <tr class="nome-divergente">
<td>
<a href="/ceis/empresa/05236586000101">
                                05.236.586/0001-01
                            </a>
</td>
<td> META TERCEIRIZACOES E SERVICOS LTDA   ** </td>
<td>Suspensão - Legislação Estadual</td>
<td>22/08/2018</td>
<td>Governo do Estado da Bahia (BA)</td>
<td>BA</td>
</tr>, <tr class="nome-divergente">
<td>
<a href="/ceis/empresa/05236586000101">
                                05.236.586/0001-01
                            </a>
</td>
<td> META TERCEIRIZACOES E SERVICOS LTDA   ** </td>
<td>Inidoneidade - Legislação Estadual</td>
<td></td>
<td>Governo do Estado da Bahia (BA)</td>
<td>BA</td>
</tr>, <tr class="nome-divergente">
<td>
<a href="/ceis/empresa/04125082000151">
                                04.125.082/0001-51
                            </a>
</td>
<td> PRIMEIRA OPCAO LOCACAO TRANSPORTE E TURISMO LTDA - ME   ** </td>
<td>Inidoneidade - Lei da ANTT e ANTAQ </td>
<td>16/01/2021</td>
<td>AGÊNCIA NACIONAL DE TRANSPORTES TERRESTRES</td>
<td>DF</td>
</tr>]
# This is the content of blocos

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-63-dae9be7999b3> in <module>()
     12             cnpj = linha.find("a").text.strip()
     13             link = linha.find("href")
---> 14             nome = linha.find("td")[1].text.strip()
     15             tipo = linha.find("td")[2].text.strip()
     16             data = linha.find("td")[3].text.strip()

~/Documentos/Code/knight/lib/python3.6/site-packages/bs4/element.py in __getitem__(self, key)
   1009         """tag[key] returns the value of the 'key' attribute for the tag,
   1010         and throws an exception if it's not there."""
-> 1011         return self.attrs[key]
   1012 
   1013     def __iter__(self):

KeyError: 1

所以&#34; blocos&#34;对于表中的每一行都有一系列 我以为我会在#34; blocos&#34;阅读 我尝试访问该号码,例如linha.find("td")[1].text.strip() 但是出现了错误消息 请问,有谁知道如何访问使用的表行?

1 个答案:

答案 0 :(得分:2)

你需要首先遍历 tr ,然后在该循​​环内部循环遍历 td's 。下面是一个简单的例子。我还建议动态获取总页数(819)并远离使用硬编码数字(就像你在for循环中所做的那样)。

import requests
from bs4 import BeautifulSoup

if __name__ == '__main__':
    requestUrl = "http://www.portaltransparencia.gov.br/ceis?pagina=2"
    response = requests.get(requestUrl)
    soup = BeautifulSoup(response.content, "html.parser")

    data = []
    for tr in soup.find_all('tr'):
        col = 0
        for td in tr.find_all('td'):
            td_text = td.get_text().strip()
            if col == 0:
                cnpj_cpf = td_text
                cnpj_cpf_link = 'http://www.portaltransparencia.gov.br{}'
                cnpj_cpf_link = cnpj_cpf_link.format(td.find('a').get('href'))
            if col == 1:
                nome = td_text
            if col == 2:
                tipo = td_text
            if col == 3:
                data_final = td_text
            if col == 4:
                nome_do_orago = td_text
            if col == 5:
                uf = td_text
                data.append({
                    'cnpj_cpf' : cnpj_cpf,
                    'cnpj_cpf_link' : cnpj_cpf_link,
                    'nome' : nome, 
                    'tipo' : tipo,
                    'data_final' : data_final,
                    'nome_do_orago' : nome_do_orago,
                    'uf' : uf
                })
            col += 1
    print (data)