Pytanie w sprawie python, beautifulsoup – Python beautifulsoup iteruj po tabeli

12

Próbuję zeskrobać dane tabeli do pliku CSV. Niestety trafiłem na blokadę drogi, a poniższy kod po prostu powtarza TD z pierwszego TR dla wszystkich kolejnych TR.

<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>

To mój pierwszy w historii skrypt Pythona, więc wszelka pomoc zostanie doceniona! Przejrzałem inne odpowiedzi na pytania, ale nie mogę zrozumieć, co tu robię źle.

Twoja odpowiedź

2   odpowiedź
35

Zaczynasz od najwyższego poziomu dokumentu przy każdym użyciufind() lubfind_all(), więc kiedy pytasz o, na przykład, wszystkie znaczniki „td”, otrzymujesz wszystkie znaczniki „td”w dokumencie, nie tylko tych w tabeli i wierszu, których szukałeś. Równie dobrze możesz nie szukać tych, ponieważ nie są używane w sposób, w jaki napisany jest Twój kod.

Myślę, że chcesz zrobić coś takiego:

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

Lub, wiesz, coś bardziej podobnego, z bardziej opisowymi nazwami zmiennych do uruchomienia:

<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>
6

że za każdym razem, gdy próbujesz zawęzić wyszukiwanie (zdobądź pierwsze td w tym tr, itp.), Zamiast tego dzwonisz do zupy. Zupa jest obiektem najwyższego poziomu - reprezentuje cały dokument. Trzeba tylko raz nazwać zupę, a następnie użyć wyniku tego zamiast zupy na następny krok.

Na przykład (z nazwami zmiennych zmienionymi na bardziej wyraźne),

<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>

Nie jestem pewien, czy instrukcja print jest najlepszym sposobem na zrobienie tego, co próbujesz tutaj zrobić (przynajmniej powinieneś użyć formatowania łańcuchów zamiast dodawania), ale pozostawiam to tak, ponieważ nie jest to podstawowa kwestia.

Również do ukończenia:soup.unicode nic nie zrobię. Nie nazywasz tam metody i nie ma żadnego zadania. Nie pamiętam, żeby BeautifulSoup posiadał metodę o nazwie unicode, ale jestem przyzwyczajony do BS 3.0, więc może być nowy w 4.

Powiązane pytania