Pergunta sobre python, beautifulsoup – Python beautifulsoup iterar sobre a mesa

12

Eu estou tentando raspar dados da tabela em um arquivo CSV. Infelizmente, atingi um bloqueio de estrada e o código a seguir simplesmente repete o TD do primeiro TR para todos os TRs subsequentes.

<code>import urllib.request
from bs4 import BeautifulSoup

f = open('out.txt','w')

url = "http://www.international.gc.ca/about-a_propos/atip-aiprp/reports-rapports/2012/02-atip_aiprp.aspx"
page = urllib.request.urlopen(url)

soup = BeautifulSoup(page)

soup.unicode

table1 = soup.find("table", border=1)
table2 = soup.find('tbody')
table3 = soup.find_all('tr')

for td in table3:
    rn = soup.find_all("td")[0].get_text()
    sr = soup.find_all("td")[1].get_text()
    d = soup.find_all("td")[2].get_text()
    n = soup.find_all("td")[3].get_text()

    print(rn + "," + sr + "," + d + ",", file=f)
</code>

Este é o meu primeiro script Python, então qualquer ajuda seria apreciada! Eu olhei para outras perguntas, mas não consigo entender o que estou fazendo de errado aqui.

Sua resposta

2   a resposta
6

O problema é que toda vez que você está tentando restringir sua busca (pegue o primeiro td neste tr, etc) você está apenas ligando de volta para a sopa. Sopa é o objeto de nível superior - representa o documento inteiro. Você só precisa chamar a sopa uma vez e depois usar o resultado disso no lugar da sopa para a próxima etapa.

Por exemplo (com nomes de variáveis ​​alterados para serem mais claros),

<code>table = soup.find('table', border=1)
rows = table.find_all('tr')

for row in rows:
    data = row.find_all("td")
    rn = data[0].get_text()
    sr = data[1].get_text()
    d = data[2].get_text()
    n = data[3].get_text()

    print(rn + "," + sr + "," + d + ",", file=f)
</code>

Não tenho certeza se a instrução print é a melhor maneira de fazer o que você está tentando fazer aqui (no mínimo, você deve usar formatação de string em vez de adição), mas eu estou deixando como está, porque não é o questão central.

Além disso, para conclusão:soup.unicode não fará nada. Você não está chamando um método lá, e não há atribuição. Eu não lembro do BeautifulSoup ter um método chamado unicode em primeiro lugar, mas eu estou acostumado com o BS 3.0, então pode ser novo em 4.

35

Você está começando no nível superior do documento toda vez que usafind() oufind_all(), então quando você pede, por exemplo, todas as tags "td" que você está recebendo todas as tags "td"no documento, não apenas aqueles na tabela e linha que você pesquisou. Você também pode não procurar por eles, porque eles não estão sendo usados ​​da maneira que seu código é escrito.

Eu acho que você quer fazer algo assim:

<code>table1 = soup.find("table", border=1)
table2 = table1.find('tbody')
table3 = table2.find_all('tr')
</code>

Ou, você sabe, algo mais como isso, com nomes de variáveis ​​mais descritivos para inicializar:

<code>rows = soup.find("table", border=1).find("tbody").find_all("tr")

for row in rows:
    cells = row.find_all("td")
    rn = cells[0].get_text()
    # and so on
</code>

Perguntas relacionadas