前提・実現したいこと
python seleniumでウェブサイトをスクレイピングするプログラムを作成しています。
次のようなHTMLで記述されたウェブサイトの数値を取得する方法を教えてほしいです。
下記のように、<li>...</li>でくくられた項目が複数あります。
その中の「item-name」を検索し、指定した文字と同じものがあった場合、
その下の「number」の数値を取得したいです。
例:検索文字が「ABCD」の場合、「5」の数値を取得したい。
初歩的な質問かと思いますが、よろしくお願いいたします。
HTMLの例
<li>
<div class="item-name">
ABCD
</div>
<div>
<span class="count">
<i class="number">...</i>
<span>5</span>
</span>
<span>...</span>
</div>
</li>
<li>
<div class="item-name">
EFGH
</div>
<div>
<span class="count">
<i class="number">...</i>
<span>9</span>
</span>
<span>...</span>
</div>
</li>
<li>...</li>
試したこと
色々調べながらテキストを検索するとこまではできましたが、その後numberの数値を探す方法がわかりません。
name = "ABCD"
link = driver.find_element_by_partial_link_text(name)
print('itemがあります')
補足情報(FW/ツールのバージョンなど)
python3.8
selenium 3.141
追記
頂いた回答を元に作成してみましたが、エラーが出てしまいます。
なにか考えられる原因ありますでしょうか?
name = "ABCD"
number = driver.find_element_by_xpath("//div[contains(text(), name)]/following-sibling::div/span[1]/span/text()")
print(number)
とすると、エラー「Message: invalid selector: The result of the xpath expression "//div[contains(text(), name)]/following-sibling::div/span[1]/span/text()" is: [object Text]. It should be an element.」
が出ます。
"/text()"を除いて下記のようにした場合
name = "ABCD"
number = driver.find_element_by_xpath("//div[contains(text(), name)]/following-sibling::div/span[1]/span")
print(number)
エラーは出ず、
<selenium.webdriver.remote.webelement.WebElement (session="xxxxxx", element="xxxxxx")>
と出力されます。(xxxxは数字とアルファベットの文字列)
「It should be an element(エレメントじゃないとダメ)」ということなのですが意味がよくわかりません。
申し訳ありませんがヒントを頂けますでしょうか。
解決方法
皆様から頂いた回答をベースに、希望する動作ができました。
最終的なものを記載しておきます。
name = "ABCD"
number = driver.find_element_by_xpath("//div[contains(text(), '" + name + "')]/following-sibling::div/span[1]/span")
print(number.text)
※検索する文字を変数(name)に入れると、[contains(text(), name)] ではうまく行かなかったため
[contains(text(), '" + name + "')] としました。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
XPathを使って参照するのはどうでしょうか。
number = driver.find_element_by_xpath("//li/div[@class='item-name' and contains(text(), 'ABCD')]/following-sibling::div/span[1]/span/text()")
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
css_selector を用いて、以下のように書くことはできます。
number という変数へ、css_selector で指定した箇所の内容を代入します。
↓
number = driver.find_element_by_css_selector('li > div:nth-child(2) > span.count > span')
もしくは
number = driver.find_element_by_css_selector('span.count > span')
上記例で、1つめの<li></li>
内の 'ABCD' に対して、number へ '5' が代入されるかと。
<ご参考>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2021/01/14 10:55 編集
勉強になります。
2021/01/14 20:29
2021/01/14 22:03
2021/01/15 06:33 編集
「Message: invalid selector: The result of the xpath expression "//div[contains(text(), name)]/following-sibling::div/span[1]/span/text()" is: [object Text]. It should be an element.」
⇒ 末尾に text() を指定したことで、elementじゃないとエラーとなりました。
試して頂いた2つ目:※text() 指定を外す
取得したelementをそのままprintしたことで、<selenium.webdriver.remote.webelement.WebElement (session="xxxxxx", element="xxxxxx")>
と表示されました。
ただし、elementは正常に取得できています。
そこで、以下のように、取得したelement(ここではnumberへ代入)のtextを取得するために、number.text とおきます。それをprintすることで解消できます。
number = driver.find_element_by_xpath("//div[contains(text(), name)]/following-sibling::div/span[1]/span")
print(number.text)
2021/01/15 09:25
2021/01/15 09:49
2021/01/15 10:16
少しでお役に立てたならば嬉しく思います。
今回の件では、こちらも大変勉強になりました。
ありがとうございました。