yuutyoko129
@yuutyoko129

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

seleniumを用いたスクレイピングにおける、タグ指定のロジックが分からず困ってます

Q&A

Closed

解決したいこと

seleniumによるスクレイピングにおいて、特定の要素を抜き出す際にどのようにタグや要素を指定するべきなのか教えていただきたいです。

下記ソースコードで、ヤフー画像検索で「プログラミング」と入力し、出てきた画像をCSVファイルで落とし込むという練習をしていました。
そこで、find_elementを使用して要素を取得する部分で、なぜその指定方法になるのか腹落ちできず困っております。

①raw_url = element.find_element(By.CLASS_NAME,"sw-ThumbnailGrid__details").get_attribute("href")

②yahoo_image_url = element.find_element(By.TAG_NAME,"img").get_attribute("src")

こちらの2つになるのですが、ページの検証をしたところどちらもタグとクラスの両方が存在しておりました。
にも関わらず、上記のように①はクラス、②はタグを指定して要素の取得を行うのはなぜでしょうか?
自分で、①はタグ、②はクラスに変更して要素を指定してもCSVファイルには何も表示されなかったので、上記の指定方法が正しいのは理解しておりますが、どのように上記が正しいことを証明しているのでしょうか?

発生している問題・エラー

CSVファイルにした際に、何も表示されない

該当するソースコード

from time import sleep
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import pandas as pd

chrome_path = r'パス'

options = Options()
options.add_argument("--incognito")

service = Service(executable_path=chrome_path)
driver = webdriver.Chrome(service=service,options=options)


url = "https://search.yahoo.co.jp/image"
driver.get(url)

sleep(3)

query = "プログラミング"
serch_box = driver.find_element(By.CLASS_NAME,"SearchBox__searchInput")
serch_box.send_keys(query)
serch_box.submit()

sleep(3)

height = 1000

while height < 3000:
    driver.execute_script("window.scrollTo(0,{});".format(height))
    height += 100
    print(height)

    sleep(1)

elements = driver.find_elements(By.CLASS_NAME,"sw-Thumbnail")

d_list = []

for i,element in enumerate(elements,start=1):
    name = f"{query}_{i}"
    raw_url = element.find_element(By.CLASS_NAME,"sw-ThumbnailGrid__details").get_attribute("href")
    yahoo_image_url = element.find_element(By.TAG_NAME,"img").get_attribute("src")
    title = element.find_element(By.TAG_NAME,"img").get_attribute("alt")

    d = {"filename":name,"raw_url":raw_url,"yahoo_image_url":yahoo_image_url,"title":title}

    d_list.append(d)

df = pd.DataFrame(d_list)
df.to_csv("image_urls_20230705.csv",encoding="utf-8-sig")

driver.quit()

### 自分で試したこと
①raw_url = element.find_element(By.TAG_NAME,"a").get_attribute("href")

②yahoo_image_url = element.find_element(By.CLASS_NAME,"sw-Thumbnail__innerImage").get_attribute("src")

として実行も、CSVには何も表示されませんでした。
あとは何をどうしたら良いか分かりません、、
0

1Answer

raw_url = element.find_element(By.TAG_NAME,"a").get_attribute("href")

この部分でエラー落ちしているのではないでしょうか?
画像検索ページを確認したところ、class="sw-Thumbnail" を持つ要素の下には a タグが 2 つ含まれています。
find_element では複数要素見つかった場合は最初の項目が返されるはずで、その項目には href が記載されていないため get_attribute("href") のところでエラー終了しているのではないでしょうか。

①raw_url = element.find_element(By.CLASS_NAME,"sw-ThumbnailGrid__details").get_attribute("href")
②yahoo_image_url = element.find_element(By.TAG_NAME,"img").get_attribute("src")

の場合は期待通り動くというのは class="sw-Thumbnail" を持つ要素の下には class="sw-ThumbnailGrid__details" を持つ要素、img タグの要素がそれぞれ 1 つしか存在しないので想定通りに要素が取得できているからだと思います。

class名やタグ名で要素を取得する場合は「ほかに同名の要素が存在しないか?」という点に注意してください。

1Like

Comments

  1. @yuutyoko129

    Questioner

    なるほどですね!
    ものすごくわかりやすいご回答で、一瞬で腹落ちできました!

    同名のクラス名やタグ名などがある場合は、被らない方を選択して抽出する必要があるということですね。
    勉強になりました。m(__)m

    ありがとうございました!

Your answer might help someone💌