web-dev-qa-db-ja.com

Python beautifulsoup itlate itate table

テーブルデータをCSVファイルにスクレイピングしようとしています。残念ながら、私は障害物にぶつかっており、次のコードは、最初のTRからTDを以降のすべてのTRに対して繰り返すだけです。

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)

これは私の初めてのPythonスクリプトなので、どんな助けもいただければ幸いです!私は他の質問の回答を見てきましたが、ここで私が間違っていることを理解できません。

16
Will

find()またはfind_all()を使用するたびにドキュメントのトップレベルから開始するため、たとえば、すべての「td」 `タグを要求すると、すべての「td」タグの取得ドキュメント内検索したテーブルと行のタグだけではありません。それらがコードの記述方法で使用されていないため、それらを検索しない方がよいでしょう。

あなたはこのようなことをしたいと思います:

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

または、ご存知のように、ブートするためのよりわかりやすい変数名を使用して、次のようなものを作成します。

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

問題は、検索を絞り込もうとするたびに(このtrの最初のtdを取得するなど)、代わりに単にスープにコールバックすることです。スープは最上位のオブジェクトで、ドキュメント全体を表します。スープを一度呼び出すだけで、次のステップのスープの代わりにその結果を使用できます。

たとえば(変数名がより明確になるように変更されています)、

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)

Printステートメントがここでやろうとしていることを行うための最良の方法であるかどうかはわかりません(少なくとも、追加ではなく文字列フォーマットを使用する必要があります)。コア問題。

また、完了のために:soup.unicodeは何もしません。そこでメソッドを呼び出すのではなく、割り当てもありません。そもそもBeautifulSoupにunicodeという名前のメソッドがあったことは覚えていませんが、BS 3.0に慣れているので、4で新しくなったかもしれません。

7