導入
セレクタで大きなブロックを取ってから、その中でさらに探す、という段階的な取り方が実務では効きます。「商品カードを取る → 各カードの中で名前と価格を取る」のような流れです。
説明
find / select は、soup 全体だけでなく、取り出した要素に対しても呼べます。
from bs4 import BeautifulSoup
html = """
<div class="product">
<span class="name">りんご</span>
<span class="price">120</span>
</div>
<div class="product">
<span class="name">みかん</span>
<span class="price">80</span>
</div>
"""
soup = BeautifulSoup(html, "html.parser")
# まず商品カードごとに取り、そのカードの中で名前と価格を取る
for card in soup.select(".product"):
name = card.find("span", class_="name").text
price = card.find("span", class_="price").text
print(f"{name}: {price}円")
- 外側のループで
.productを1つずつ取り出し、そのcardの中だけでcard.find(...)を呼ぶのがポイント。 - こうすると「1件ぶんの名前と価格」が正しく対応します。全体に対して
find_all("name")とfind_all("price")を別々に取ると、対応がずれやすいので、この「カード単位でループ」が安全です。
実行結果:
りんご: 120円
みかん: 80円
やってみよう
3つ目の商品 <div class="product"><span class="name">ぶどう</span><span class="price">300</span></div> を足すと、ループがそのまま3件ぶん回ります。「まとまり(カード)でループ → 中を取る」は、この後の抽出でずっと使う型です。
演習
上の HTML で、各商品の名前だけを「商品: りんご」の形で1行ずつ print してください。
ヒント1を見る
for card in soup.select(".product"): print("商品:", card.find("span", class_="name").text)。