本ページには PR が含まれます。
XPathでのWeb要素の取得ってどうやるの…?
今回はseleniumライブラリを使ったWebスクレイピングのなかでも、XPathを使って要素を取得する方法を解説します。
サンプルコードと処理の流れを見ながら、サクサク処理を試せるのでぜひ参考にしてみてください。
seleniumライブラリの詳しい使い方を知りたい方はこちら!!
Pythonの実践的なWebスクレイピング技術について学びたいという方に向けてUdemy学習コースを公開しています。
\10/27(金)までの 90%OFFクーポンで Webスクレイピングを学べる!!/
30日間返金保証!
すぐにでもスクレイピング技術を活かせるようになりますよ!
XPathとは
XPath(XML Path Language)はHTML/XMLの要素や属性値をカンタンな構文で表現する言語です。
例として下記のようなHTMLドキュメント内のaタグをXPathで表現してみます。
HTML
<!DOCTYPE html>
<html>
<head>
<title>XPathの使ったスクレイピングを学ぼう</title>
</head>
<body>
<h1 class="title">Welcome to my Website!!
<a href="https://junpage.com/">プログラミングLab</a>
</h1>
<p class="explanation">Python seleniumライブラリを使ったスクレイピングをマスターしよう</p>
<h2 class="note">このHTMLドキュメントは取得結果の確認に使用します
<a class="blog-link" href="https://junpage.com/">トップページへ</a>
</h2>
</body>
<footer>
<p>サンプルHTML</p>
</footer>
</html>
XPathで要素を指定
/html/body/h2/a
<a class="blog-link" href="https://junpage.com/">トップページへ</a>
XPathを使うことで複雑な要素で構成されるHTMLドキュメントの内容から、カンタンな記述で要素を特定できます。
XPathを省略して記述
XPathは//(ダブルスラッシュ)
を使うことで省略して記述することもできます。
前項の例では、
/html/body/h2/a
と先頭のhtmlからすべてを記述していましたが、
//h2/a
としても同じ要素を取得できます。下図のように「h2」-「a」が連続するつながりは一つしかないので、省略した記法でも取得要素は同じです。
一方で、XPathの「h2」まで省略して
//a
とすると、a要素までのつながりをひとつに絞れないため2つのa要素が取得されます。
seleniumでXPathを指定して要素を取得
seleniumではfind_element()
メソッドやfind_elements()
メソッドを使って要素を取得できます。
- 指定した条件の要素をひとつだけ取得する
driver.find_element(by=By.XPATH, value=指定したXPath)
- 指定した条件の要素をすべて取得する
driver.find_elements(by=By.XPATH, value=指定したXPath)
XPathを使えばさまざまな条件で要素を取得できます。
引数byのByクラスはあらかじめimportが必要です。
# find_element()メソッドの引数byを使用するByクラスをあらかじめインポート
from selenium.webdriver.common.by import By
タグ名と属性名・属性値を指定して取得
XPath構文でタグ名と属性名・属性値を指定して取得できます。
driver.find_element(by=By.XPATH, value="//タグ名[@属性名=属性値]")
例として、Googleトップページからclass属性値が”MV3Tnb”であるaタグの要素をすべて取得してみます
※<a class="MV3Tnb" ...>テキストテキスト</a>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Googleトップページにアクセス
url = "https://www.google.com/?hl=ja"
driver.get(url)
# class属性値が'MV3Tnb'であるaタグを探索
xpath = "//a[@class='MV3Tnb']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<a class="MV3Tnb" href="https://about.google/?fg=1&utm_source=google-JP&utm_medium=referral&utm_campaign=hp-header" ping="/url?sa=t&rct=j&source=webhp&url=https://about.google/%3Ffg%3D1%26utm_source%3Dgoogle-JP%26utm_medium%3Dreferral%26utm_campaign%3Dhp-header&ved=0ahUKEwj0lrmjsfb7AhXG1GEKHQnzBPwQkNQCCAI">Googleについて</a>
<a class="MV3Tnb" href="https://store.google.com/JP?utm_source=hp_header&utm_medium=google_ooo&utm_campaign=GS100042&hl=ja-JP" ping="/url?sa=t&rct=j&source=webhp&url=https://store.google.com/JP%3Futm_source%3Dhp_header%26utm_medium%3Dgoogle_ooo%26utm_campaign%3DGS100042%26hl%3Dja-JP&ved=0ahUKEwj0lrmjsfb7AhXG1GEKHQnzBPwQpMwCCAM">ストア</a>
このように指定したXPathの条件に合う要素を取得できました。
属性名・属性値を指定して取得
XPath構文で*(アスタリスク)使うことで、属性名・属性値を指定して要素を取得することもできます。
driver.find_element(by=By.XPATH, value="//*[@属性名=属性値]"]
アスタリスクを使えばタグ名にかかわらず、属性名と属性値で探索することができます。
ここでは例としてYahoo! JAPANからclass属性の属性値が”_2j0udhv5jERZtYzddeDwcv”である要素をすべて取得してみます。
※ <タグ名 class="_2j0udhv5jERZtYzddeDwcv" ...>テキストテキスト</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# *(アスタリスク)を使って、class属性の属性値が"_2j0udhv5jERZtYzddeDwcv"の要素をすべて取得
xpath = "//*[@class='_2j0udhv5jERZtYzddeDwcv']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:71b87963e9b9c0fcbdce7cf98a92395934f73cd0;element_id:first-news-topics-text" data-ual-content-key="58a70bad-8ad4-4848-9823-115502af9620"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447548" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:1;tpid:6447548;imgsize:s;cmt_num:116" data-ual-gotocontent="true" data-cl_cl_index="1"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">14日は全国的に真冬の寒さ 防寒を</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">116</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:0a25f8040d87350702587194abee0183e2cb7c19;element_id:first-news-topics-text" data-ual-content-key="db24dfef-2be2-42e3-8c80-90816a673bf1"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447546" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:2;tpid:6447546;imgsize:s;cmt_num:305" data-ual-gotocontent="true" data-cl_cl_index="2"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">薗浦氏の聴取要請 収入不記載か</span></h1><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">305</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:89c426532bdbb821d371e5beb4bd847726e3f3ca;element_id:first-news-topics-text" data-ual-content-key="0c61c049-a58e-424f-bdd3-a567df0cc767"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447545" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:3;tpid:6447545;imgsize:s;cmt_num:0" data-ual-gotocontent="true" data-cl_cl_index="3"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">商業施設にバス突っ込む 複数けが</span></h1></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:045703adec483cfc22f2051915b995017dd606d1;element_id:first-news-topics-text" data-ual-content-key="e584a467-c660-47c9-bce4-64668f66dd42"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447547" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:4;tpid:6447547;imgsize:s;cmt_num:34" data-ual-gotocontent="true" data-cl_cl_index="4"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">住宅に2遺体 事件の可能性で捜査</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">34</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:fb00b3b1e6834aced7377de319fa567bb2644672;element_id:first-news-topics-text" data-ual-content-key="eeb800fd-e853-4e99-8a8d-980db3c1d989"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447542" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:5;tpid:6447542;imgsize:s;cmt_num:51" data-ual-gotocontent="true" data-cl_cl_index="5"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">沖縄の不発弾 過去には死亡事故も</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">51</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:c2823df90ce387250e5860d404f8d4e616e236c9;element_id:first-news-topics-text" data-ual-content-key="8c0cacdc-8899-40d8-b4c3-8689f45491cd"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447540" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:6;tpid:6447540;imgsize:s;cmt_num:108" data-ual-gotocontent="true" data-cl_cl_index="6"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">阪神、右腕ビーズリー獲得を発表</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">108</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:9c55ed182711225dc8bc6a7878b8cd430187e069;element_id:first-news-topics-text" data-ual-content-key="3251a590-76ae-44c8-adeb-160cbef2a065"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447544" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:7;tpid:6447544;imgsize:s;cmt_num:0" data-ual-gotocontent="true" data-cl_cl_index="7"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">達成は過去8人 井上尚弥の挑戦</span></h1></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:9e0d5b1b2f8680717b15ef4d33d2389a2615c1d5;element_id:first-news-topics-text" data-ual-content-key="59b8e31e-aabd-4359-ae11-d4ae930f5208"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447537" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:8;tpid:6447537;imgsize:s;cmt_num:887" data-ual-gotocontent="true" data-cl_cl_index="8"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">宮崎駿監督10年ぶり長編 7月公開</span></h1><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">887</span></span></span></div></div></a></article></li>
属性値だけを指定して取得
属性名の指定に*(アスタリスク)使うことで、属性値だけを指定して要素を取得することもできます。
driver.find_element(by=By.XPATH, value="//*[@*=属性値]")
このように@(アットマーク)直後の属性名の指定を*(アスタリスク)とすれば、すべての属性名について属性値を指定して要素を取得できます。
例としてYahoo! JAPANから属性値が”_2j0udhv5jERZtYzddeDwcv”である要素をすべて取得してみます。
※ <タグ名 属性値="_2j0udhv5jERZtYzddeDwcv" ...>テキストテキスト</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# [@*(アスタリスク)=属性値]を使って、属性値が"_2j0udhv5jERZtYzddeDwcv"の要素をすべて取得
xpath = "//*[@*='_2j0udhv5jERZtYzddeDwcv']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:71b87963e9b9c0fcbdce7cf98a92395934f73cd0;element_id:first-news-topics-text" data-ual-content-key="d8e9b790-5067-4da6-9734-f5c7be8b679a"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447548" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:1;tpid:6447548;imgsize:s;cmt_num:115" data-ual-gotocontent="true" data-cl_cl_index="1"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">14日は全国的に真冬の寒さ 防寒を</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">115</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:0a25f8040d87350702587194abee0183e2cb7c19;element_id:first-news-topics-text" data-ual-content-key="5b5a1394-9cd3-49ad-820b-f50dc5492cc0"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447546" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:2;tpid:6447546;imgsize:s;cmt_num:305" data-ual-gotocontent="true" data-cl_cl_index="2"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">薗浦氏の聴取要請 収入不記載か</span></h1><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">305</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:89c426532bdbb821d371e5beb4bd847726e3f3ca;element_id:first-news-topics-text" data-ual-content-key="494208a5-028f-4b05-9cf6-f12220d20593"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447545" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:3;tpid:6447545;imgsize:s;cmt_num:0" data-ual-gotocontent="true" data-cl_cl_index="3"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">商業施設にバス突っ込む 複数けが</span></h1></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:045703adec483cfc22f2051915b995017dd606d1;element_id:first-news-topics-text" data-ual-content-key="e5563db4-38e5-4235-85c9-447c75f45a04"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447547" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:4;tpid:6447547;imgsize:s;cmt_num:34" data-ual-gotocontent="true" data-cl_cl_index="4"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">住宅に2遺体 事件の可能性で捜査</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">34</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:fb00b3b1e6834aced7377de319fa567bb2644672;element_id:first-news-topics-text" data-ual-content-key="7dcd8021-8db0-413e-9c20-42255d66f9f9"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447542" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:5;tpid:6447542;imgsize:s;cmt_num:49" data-ual-gotocontent="true" data-cl_cl_index="5"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">沖縄の不発弾 過去には死亡事故も</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">49</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:c2823df90ce387250e5860d404f8d4e616e236c9;element_id:first-news-topics-text" data-ual-content-key="28734ecb-6c27-4980-ae95-bcd098f311d5"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447540" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:6;tpid:6447540;imgsize:s;cmt_num:108" data-ual-gotocontent="true" data-cl_cl_index="6"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">阪神、右腕ビーズリー獲得を発表</span></h1><span class="_2obRU_TgAxzHaYqOXrZYlv"><span class="h4yLXygiSc5wwNlJOQEdz _1dr5aVDbNPF63JCS2bJhij _2M3AyDfFaeJl3Uo7lUPMAp" style="width:30px;height:12px">NEW</span></span><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">108</span></span></span></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:9c55ed182711225dc8bc6a7878b8cd430187e069;element_id:first-news-topics-text" data-ual-content-key="bb12c5e5-373b-4c73-a0c4-95e0e71afcdf"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447544" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:7;tpid:6447544;imgsize:s;cmt_num:0" data-ual-gotocontent="true" data-cl_cl_index="7"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">達成は過去8人 井上尚弥の挑戦</span></h1></div></div></a></article></li>
<li class="_2j0udhv5jERZtYzddeDwcv"><article class="QLtbNZwO-lssuRUcWewbd" data-ual-view-type="list" data-ual="id_type:shannon_article;content_id:9e0d5b1b2f8680717b15ef4d33d2389a2615c1d5;element_id:first-news-topics-text" data-ual-content-key="beaf3a55-faa0-46fc-a5f9-e2f0b75a2bf2"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://news.yahoo.co.jp/pickup/6447537" data-cl-params="_cl_vmodule:tpto;_cl_link:title;_cl_position:8;tpid:6447537;imgsize:s;cmt_num:887" data-ual-gotocontent="true" data-cl_cl_index="8"><div class="_2cXD1uC4eaOih4-zkRgqjU"><div class="TRuzXRRZHRqbqgLUCCco9"><h1 class="_3cl937Zpn1ce8mDKd5kp7u"><span class="fQMqQTGJTbIMxjQwZA2zk _1alzSpTqJzvSVUWqpx82d4">宮崎駿監督10年ぶり長編 7月公開</span></h1><span class="_2dkkFdF6iwwsvj59371Trg"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1I_5hzC8N7rC_DyCqrkXsj" style="width:10px;height:10px"></span><span class="fQMqQTGJTbIMxjQwZA2zk _2VDw54wcDejORZkozpOysW"><span class="ASQOQKzZhjBC7R0_pxI3g">887</span></span></span></div></div></a></article></li>
タグ内のテキストを指定して要素を取得
XPath構文を使えzzば、タグ内のテキストを指定して要素を取得できます。
driver.find_element(by=By.XPATH, value="//*[text()=指定する文字列]")
例としてYahoo! JAPANからテキストが「ニュース」である要素をすべて取得してみます。
※ <タグ名 属性値="..." ...>ニュース</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[text()=指定する文字列]を使って、テキストが「ニュース」である要素をすべて取得
xpath = "//*[text()='ニュース']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">ニュース</span>
<h1 class="_2LJWWRbnY7KqEPyWQukxFD _9YxVmCAhrwLz2V6qXWqBJ" aria-label="Yahoo!ニュース">ニュース</h1>
<a class="_1fWTm2E47ymhMM3suCaCGi _3aR1Wl7JOyOEug4F-C-ZyI cl-nofollow" data-cl-params="_cl_vmodule:tpto;_cl_link:tab;_cl_position:0;type:link" href="https://news.yahoo.co.jp/" data-cl_cl_index="1">ニュース</a>
属性値やテキストが部分一致する要素を取得
XPathではcontains()
を使って部分一致(あいまい)検索によって要素を取得できます。
部分一致とは「〇〇が含まれる」文字列のことを指します。
例. 「amazon」が部分一致する文字列
- amazonプライム
- https://www.amazon.co.jp/
- AAAamazon
属性値の部分一致で取得
属性値が部分一致する要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[contains(@*, 属性値に含まれる文字列)]")
例としてYahoo! JAPANからhref属性に”search.yahoo.co.jp”が含まれる要素をすべて取得してみます。
※ <タグ名 属性名="~~~search.yahoo.co.jp~~~">...</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[contains(@属性名, 属性値に含まれる文字列)]を使って、href属性に"search.yahoo.co.jp"が含まれる要素をすべて取得
xpath = "//*[contains(@href, 'search.yahoo.co.jp')]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<a href="https://search.yahoo.co.jp/" class="ygDfdPUPK5OPiqKG4UtuU" aria-label="ウェブで検索" tabindex="-1"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="_2n9xMCYzZ6JYW3o0ool3t- _28WZAuJKwm0WdhSe1Ahuyx">ウェブ</span></span></a>
<a href="https://search.yahoo.co.jp/image" class="ygDfdPUPK5OPiqKG4UtuU" aria-label="画像で検索" tabindex="-1"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="_2n9xMCYzZ6JYW3o0ool3t-">画像</span></span></a>
<a href="https://search.yahoo.co.jp/video" class="ygDfdPUPK5OPiqKG4UtuU" aria-label="動画で検索" tabindex="-1"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="_2n9xMCYzZ6JYW3o0ool3t-">動画</span></span></a>
<a href="https://search.yahoo.co.jp/realtime" class="ygDfdPUPK5OPiqKG4UtuU" aria-label="リアルタイムで検索" tabindex="-1"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="_2n9xMCYzZ6JYW3o0ool3t-">リアルタイム</span></span></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime/search?rkf=1&fr=rts_bzmod_ytop_pc&p=%E5%90%9B%E3%81%9F%E3%81%A1%E3%81%AF%E3%81%A9%E3%81%86%E7%94%9F%E3%81%8D%E3%82%8B%E3%81%8B&btid=MTYwMjU2ODQ0ODA2Mzk4MzYxNw==" data-cl-params="_cl_link:word;_cl_position:1" data-cl_cl_index="1"><div class="_3D3l_A2VUrmL3ULwa7X84T"><span class="_1h-0xGVnyOwxN58PfK-Waf _3F4bJnV5jen0SENf3TRnY8" aria-label="1位"><span class="Bg8j2T4mhSQsnpFn6ZtwQ">1</span></span><div class="_2mqYS6ECHFfHOrV9EKTrdC"><span class="_1SuLHmJ-pKGuSXLac1MV28 _1dr5aVDbNPF63JCS2bJhij _26dXlwH9CEaGPT1VUH4CE5">stay</span></div><div class="_2XIN33dSPHFseABwaaChy3"><div class="_1y-kKQ4PtsqxCSGRqjLzth"><p class="_35gOEPVmLqF0YTra3WRwfD">君たちはどう生きるか</p><span class="_2wtXm5oCkQgndxV394_wB5 _1dr5aVDbNPF63JCS2bJhij">写真あり</span></div><p class="_2-peiJPu-JYS_o8nnhEpdL _3v9VCsGKsktTB7eaN70w-n">関連ワード</p><ul class="_1jpo0Xpl0IaWUNyc7YkBZ9"><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">吉野源三郎</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">風立ちぬ</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">宮崎駿</span></li></ul></div></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime/search?rkf=1&fr=rts_bzmod_ytop_pc&p=%E9%98%AA%E7%A5%9E%E8%A5%BF%E5%AE%AE%E9%A7%85&btid=MTYwMjU3NjI4MjUxMjE2MjgxNg==" data-cl-params="_cl_link:word;_cl_position:2" data-cl_cl_index="2"><div class="_3D3l_A2VUrmL3ULwa7X84T"><span class="_1h-0xGVnyOwxN58PfK-Waf _3sD0Jis9J7GC1kcsocd0HN" aria-label="2位"><span class="Bg8j2T4mhSQsnpFn6ZtwQ">2</span></span><div class="_2mqYS6ECHFfHOrV9EKTrdC"><span class="_1SuLHmJ-pKGuSXLac1MV28 _1dr5aVDbNPF63JCS2bJhij _26dXlwH9CEaGPT1VUH4CE5">stay</span></div><div class="_2XIN33dSPHFseABwaaChy3"><div class="_1y-kKQ4PtsqxCSGRqjLzth"><p class="_35gOEPVmLqF0YTra3WRwfD">阪神西宮駅</p></div><p class="_2-peiJPu-JYS_o8nnhEpdL _3v9VCsGKsktTB7eaN70w-n">関連ワード</p><ul class="_1jpo0Xpl0IaWUNyc7YkBZ9"><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">エビスタ</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">エビスタ西宮</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">阪神バス</span></li></ul></div></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime/search?rkf=1&fr=rts_bzmod_ytop_pc&p=%E5%8D%83%E8%91%89%E7%9C%8C%E8%AD%A6&btid=MTYwMjU3MzEyNzUwMjE1OTg3NA==" data-cl-params="_cl_link:word;_cl_position:3" data-cl_cl_index="3"><div class="_3D3l_A2VUrmL3ULwa7X84T"><span class="_1h-0xGVnyOwxN58PfK-Waf rnqNfNVaqdS7WXDVBRwOS" aria-label="3位"><span class="Bg8j2T4mhSQsnpFn6ZtwQ">3</span></span><div class="_2mqYS6ECHFfHOrV9EKTrdC"><span class="_1SuLHmJ-pKGuSXLac1MV28 _1dr5aVDbNPF63JCS2bJhij _26dXlwH9CEaGPT1VUH4CE5">stay</span></div><div class="_2XIN33dSPHFseABwaaChy3"><div class="_1y-kKQ4PtsqxCSGRqjLzth"><p class="_35gOEPVmLqF0YTra3WRwfD">千葉県警</p><span class="_2wtXm5oCkQgndxV394_wB5 _1dr5aVDbNPF63JCS2bJhij">写真あり</span></div><p class="_2-peiJPu-JYS_o8nnhEpdL _3v9VCsGKsktTB7eaN70w-n">関連ワード</p><ul class="_1jpo0Xpl0IaWUNyc7YkBZ9"><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">パレード中</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">パレード</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">ディズニーランド</span></li></ul></div></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime/search?rkf=1&fr=rts_bzmod_ytop_pc&p=%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%88%E3%81%95%E3%82%93&btid=MTYwMjU4NDc3OTQ1NDgzMjY0MQ==" data-cl-params="_cl_link:word;_cl_position:4" data-cl_cl_index="4"><div class="_3D3l_A2VUrmL3ULwa7X84T"><span class="_1h-0xGVnyOwxN58PfK-Waf" aria-label="4位"><span class="Bg8j2T4mhSQsnpFn6ZtwQ">4</span></span><div class="_2mqYS6ECHFfHOrV9EKTrdC"><span class="_1SuLHmJ-pKGuSXLac1MV28 _1dr5aVDbNPF63JCS2bJhij _26dXlwH9CEaGPT1VUH4CE5">stay</span></div><div class="_2XIN33dSPHFseABwaaChy3"><div class="_1y-kKQ4PtsqxCSGRqjLzth"><p class="_35gOEPVmLqF0YTra3WRwfD">キャストさん</p></div><p class="_2-peiJPu-JYS_o8nnhEpdL _3v9VCsGKsktTB7eaN70w-n">関連ワード</p><ul class="_1jpo0Xpl0IaWUNyc7YkBZ9"><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">パレード乱入</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">パレード</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">クリスト</span></li></ul></div></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime/search?rkf=1&fr=rts_bzmod_ytop_pc&p=%E5%9B%BD%E6%B0%91%E3%81%8C%E8%87%AA%E3%82%89%E3%81%AE%E8%B2%AC%E4%BB%BB&btid=MTYwMjU3NjA2MzY1MzE5MTY4Mw==" data-cl-params="_cl_link:word;_cl_position:5" data-cl_cl_index="5"><div class="_3D3l_A2VUrmL3ULwa7X84T"><span class="_1h-0xGVnyOwxN58PfK-Waf" aria-label="5位"><span class="Bg8j2T4mhSQsnpFn6ZtwQ">5</span></span><div class="_2mqYS6ECHFfHOrV9EKTrdC"><span class="_1SuLHmJ-pKGuSXLac1MV28 _1dr5aVDbNPF63JCS2bJhij _26dXlwH9CEaGPT1VUH4CE5">stay</span></div><div class="_2XIN33dSPHFseABwaaChy3"><div class="_1y-kKQ4PtsqxCSGRqjLzth"><p class="_35gOEPVmLqF0YTra3WRwfD">国民が自らの責任</p></div><p class="_2-peiJPu-JYS_o8nnhEpdL _3v9VCsGKsktTB7eaN70w-n">関連ワード</p><ul class="_1jpo0Xpl0IaWUNyc7YkBZ9"><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">国民の責任</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">自らの責任</span></li><li class="_1YqQ_PoFDNS-A0ZnGCm8SL"><span class="_1Fcx6C1h1h2MgqRSdGImkX">岸田文雄</span></li></ul></div></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://search.yahoo.co.jp/realtime" data-cl-params="_cl_link:more;_cl_position:0" data-cl_cl_index="6">話題のキーワードをもっと見る</a>
タグに囲まれたテキストの部分一致で取得
同じようにタグに囲まれたテキストの部分一致で取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[contains(text(), 任意の文字列)]")
例としてYahoo! JAPANからテキストに”スポーツ”が含まれる要素をすべて取得してみます。
※ <タグ名 属性名="...">~~~スポーツ~~~</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[contains(text(), 任意の文字列)]を使って、テキストに"スポーツ"が含まれる要素をすべて取得
xpath = "//*[contains(text(), 'スポーツ')]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">スポーツナビ</span>
<a class="_1fWTm2E47ymhMM3suCaCGi cl-nofollow" data-cl-params="_cl_vmodule:tpsp;_cl_link:tab;_cl_position:0;type:switch" href="https://news.yahoo.co.jp/categories/sports" data-cl_cl_index="4">スポーツ</a>
<cite class="O9jggTRv0zy3XcPayfJLa">スポーツ報知</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">日刊スポーツ</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">スポーツ報知</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">スポーツ報知</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">スポーツ報知</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">スポーツ報知</cite>
<dd>スポーツデポ・アルペン</dd>
<cite class="O9jggTRv0zy3XcPayfJLa">デイリースポーツ</cite>
<cite class="O9jggTRv0zy3XcPayfJLa">デイリースポーツ</cite>
属性値やテキストが前方一致する要素を取得
XPathではstarts-with()
を使えば、前方一致の検索によって要素を取得できます。
前方一致とは「〇〇で始まる」文字列のことを指します。
例. 「https://」の前方一致である文字列
- https://junpage.com/
- https://www.amazon.co.jp/
- https://www.google.com/?hl=ja
属性値の前方一致で要素を取得
属性値の前方一致で要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[starts-with(@*, 任意の文字列)]")
例としてYahoo! JAPANからhref属性が”https://s.yimg.jp/”で始まる要素を取得してみます。
※ <タグ名 href="https://s.yimg.jp/~~~">...</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[starts-with(@*, 任意の文字列)]を使って、href属性が"https://s.yimg.jp/"で始まる要素をすべて取得
xpath = "//*[starts-with(@href, 'https://s.yimg.jp/')]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<link rel="shortcut icon" href="https://s.yimg.jp/c/icon/s/bsc/2.0/favicon.ico" type="image/vnd.microsoft.icon">
<link rel="icon" href="https://s.yimg.jp/c/icon/s/bsc/2.0/favicon.ico" type="image/vnd.microsoft.icon">
<link rel="apple-touch-icon-precomposed" href="https://s.yimg.jp/c/icon/s/bsc/2.0/y120.png">
タグに囲まれたテキストの前方一致で要素を取得
テキストの前方一致で要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[starts-with(text(), 任意の文字列)]")
例としてYahoo! JAPANからタグに囲まれたテキストが”Yahoo!”で始まる要素を取得してみます。
※ <タグ名 属性名="...">Yahoo!~~~</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[starts-with(text(), 任意の文字列)]を使って、テキストが"Yahoo!"で始まる要素をすべて取得
xpath = "//*[starts-with(text(), 'Yahoo!')]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<title>Yahoo! JAPAN</title>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://support.yahoo-net.jp/PccBb/s/" data-cl-params="_cl_link:bbhelp;_cl_position:0" data-cl_cl_index="4">Yahoo! BBヘルプ</a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://www.yahoo.co.jp" data-cl-params="_cl_vmodule:header;_cl_link:logo;_cl_position:0" data-cl_cl_index="1">Yahoo! JAPAN</a>
<legend>Yahoo!検索</legend>
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">Yahoo!モバゲー</span>
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">Yahoo!基金で支援助成</span>
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">Yahoo! JAPAN SDGs</span>
<text y="12px" style="display:block;position:initial;background:none;border:none;float:none;width:auto;height:auto;margin:0;opacity:1;padding:0;line-height:17px;font-size:inherit;font-weight:normal;color:#000;top:auto;bottom:auto;left:auto;right:auto;visibility:inherit;-webkit-text-size-adjust:none;font-family:sans-serif;text-decoration:none;vertical-align:middle;white-space:nowrap;overflow-wrap:normal;word-wrap:normal;" data-i-elm="textBody">Yahoo! JAPAN広告</text>
<h1 class="_2LJWWRbnY7KqEPyWQukxFD _2vlyNSs41eUR8HDyQ8iUvQ">Yahoo! BB会員メニュー</h1>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://ybb.yahoo.co.jp/hikitsugi/" data-cl-params="_cl_link:id;_cl_position:0" data-cl_cl_index="1">Yahoo! BB用IDの変更</a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://shopping.yahoo.co.jp/?sc_e=ytedit_shptop_gridvg" data-cl-params="_cl_vmodule:service;_cl_link:shp_svc;_cl_position:0;sid:106148;oid:135284;agid:1106372;pid:pctop_serv_pc;tid:2" data-cl_cl_index="1">Yahoo!ショッピング</a>
seleniumでは「部分一致」「前方一致」で取得が可能ですが、「後方一致」はサポートされていません。
複数の条件を指定して要素を取得 and/or
XPathではand
やor
を使って複数条件を指定して要素を取得できます。
複数条件を満たす要素を取得 and
and
演算子を使って複数条件を満たす要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[条件1 and 条件2]"
例としてYahoo! JAPANから(条件1)タグに囲まれたテキストに”ショッピング”が含まれる、かつ(条件2)class属性値が”t_jb9bKlgIcajcRS2hZAP”である要素をすべて取得してみます。
※ <タグ名 class="t_jb9bKlgIcajcRS2hZAP">~~~ショッピング~~~</タグ名>
のような要素を取得
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[条件1 and 条件2]を使って要素を取得
xpath = "//*[contains(text(), 'ショッピング') and @class='t_jb9bKlgIcajcRS2hZAP']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<span class="t_jb9bKlgIcajcRS2hZAP">ショッピング</span>
複数条件のいずれかを満たす要素を取得 or
or
演算子を使って複数条件のうちいずれかを満たす要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[条件1 or 条件2]")
例としてYahoo! JAPANから(条件1)タグに囲まれたテキストに”ショッピング”が含まれる、もしくは(条件2)class属性値が”t_jb9bKlgIcajcRS2hZAP”であるかのいずれかを満たす要素を取得してみます。
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[条件1 or 条件2]を使って要素を取得
xpath = "//*[contains(text(), 'ショッピング') or @class='t_jb9bKlgIcajcRS2hZAP']"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<span class="t_jb9bKlgIcajcRS2hZAP">プレミアム</span>
<span class="t_jb9bKlgIcajcRS2hZAP">カード</span>
<span class="t_jb9bKlgIcajcRS2hZAP">メール</span>
<span class="t_jb9bKlgIcajcRS2hZAP">トラベル</span>
<span class="t_jb9bKlgIcajcRS2hZAP">ヤフオク!</span>
<span class="t_jb9bKlgIcajcRS2hZAP">ショッピング</span>
<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">ショッピング</span>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://shopping.yahoo.co.jp/?sc_e=ytedit_shptop_gridvf" data-cl-params="_cl_vmodule:service;_cl_link:shp_svc;_cl_position:0;sid:106148;oid:135282;agid:1106372;pid:pctop_serv_pc;tid:2" data-cl_cl_index="1">Yahoo!ショッピング</a>
否定を使った条件で要素を取得 not
not
演算子を使って否定を使った条件で要素を取得してみましょう。
driver.find_element(by=By.XPATH, value="//*[not(条件)]")
例としてYahoo! JAPANからhref属性値が”https://”を含まないaタグの要素を取得してみます。
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[not(条件)]を使って要素を取得
xpath = "//a[not(contains(@href, 'https://'))]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt cl-nofollow" href="#wrapper" data-cl-params="_cl_vmodule:perorin;_cl_link:close;_cl_position:0" data-cl_cl_index="2">閉じる</a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt cl-nofollow" href="#wrapper"><span class="_3d6HchK_pEvGBdfqXSYkpH _3v9VCsGKsktTB7eaN70w-n">キーワード入力補助を開く</span></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="http://yahoo-mbga.jp/" aria-label="Yahoo!モバゲーへ遷移する" data-cl-params="_cl_vmodule:tool;_cl_link:mbga_97;_cl_position:20;svcid:97" data-cl_cl_index="20"><p class="_2bBRLhI5ZpVYu0tuHZEFrn"><span class="pz0On1w4yAviBGMdKItoQ"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">Yahoo!モバゲー</span></span><span class="_1Al3K70np2V_Ev1eGkfsBm"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij HqaQUEWYZUMU4tqNw11D8" style="width:20px;height:20px"></span></span></p></a>
<a href="javascript:void(0);" style="box-sizing: content-box; background-color: transparent; display: block; position: absolute; width: 100%; height: 100%; top: 0px; left: 0px;"></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt cl-nofollow" data-cl-params="_cl_vmodule:today;_cl_link:notice;_cl_position:0;" data-cl_cl_index="8"><div class="_3ENWZejXZd0Cpi58_B5sQ2"><h1 class="_3YW1btm38YdgS5RvQqoZsb"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="RF5FG4AYLHpEgWQyIWERX">お知らせ</span></span></h1><div class="AuCGmXot8FfPBs4aL7sqP"><span class="_2IL_NdIA8M06bMU_n1lpZI"></span></div><p class="_23pgd8WkXk89cGZm2tFRU1"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR"><span class="_17DLFvrjLTG-r-kafdGm9D">新着があります<span class="_2c0yknE97YVk1nrD1Vaowv GE2DdyRWIy0u0V7jt6Fhs"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _1WtwLO3DMdw_RX_CO224-R" style="width:9px;height:9px"></span></span></span></span></p></div></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="http://ybb.softbank.jp/support/mysoftbank/?adid=sprt_210714_sprt_m_r_o_o_1_005" data-cl-params="_cl_link:procedure;_cl_position:0" data-cl_cl_index="2"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">各種お手続き</span></a>
<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="http://ybb.softbank.jp/support/?adid=sprt_210714_sprt_m_r_o_o_1_004" data-cl-params="_cl_link:support;_cl_position:0" data-cl_cl_index="3"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">お客様サポート</span></a>
<a href="#wrapper" class="_2kuOwgtsPgkVQ2ydbUQUmo _1dr5aVDbNPF63JCS2bJhij">ページ上部に戻る</a>
<a href="javascript:void(0);" style="box-sizing: content-box; background-color: transparent; display: block; width: 100%; height: 100%; pointer-events: none;"></a>
<a href="javascript:void(0);" style="box-sizing: content-box; background-color: transparent; display: block; width: 100%; height: 100%; pointer-events: none;"></a>
<a href="javascript:void(0);" style="box-sizing: content-box; background: url("https://s.yimg.jp/images/listing/tool/yads/richad/assets/pc/gyj_close.png") 50% 50% / contain no-repeat transparent; position: absolute; display: block; width: 65px; height: 17px; top: 10px; left: 10px; z-index: 1; pointer-events: auto;"></a>
<a href="javascript:void(0);" style="box-sizing: content-box; background-color: transparent; position: absolute; top: 10px; left: 10px; color: rgb(24, 99, 196); font-size: 12px; z-index: 1; text-decoration: none; pointer-events: auto;">広告を再表示</a>
順番を指定してn番目の要素を取得
XPath構文でposition()
を使えば、出現する要素の順番から任意の要素を取得できます。
- n番目の要素を取得
driver.find_element(by=By.XPATH, value="//*[position()=n]")
- m番目とn番目の要素を取得
driver.find_element(by=By.XPATH, value="//*[position()=m or position()=n]")
- n番目より前の要素を取得
driver.find_element(by=By.XPATH, value="//*[position()<n]")
- n番目以降の要素を取得
driver.find_element(by=By.XPATH, value="//*[position()>=n]")
- 順番の最後の要素を取得
driver.find_element(by=By.XPATH, value="//*[position()=last()]")
例としてYahoo! JAPANからclass属性が”_1glrFPJpWbefWf8qr3k4FU”であるulタグ内の3番目のliタグの要素を取得してみます。
サンプルコード
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome import service as fs
# chromedriverのパスを指定
driver_path = "/Users/「PCのユーザ名」/Downloads/chromedriver"
chrome_service = fs.Service(executable_path=driver_path)
driver = webdriver.Chrome(service=chrome_service)
# Yahoo! JAPANにアクセス
driver.get(url="https://www.yahoo.co.jp/")
# //*[position()条件]を使って要素を取得
xpath = "//ul[@class='_1glrFPJpWbefWf8qr3k4FU']/li[position()=3]"
result = driver.find_elements(by=By.XPATH, value=xpath)
# 取得した要素のHTMLを表示
for element in result:
print(element.get_attribute("outerHTML"))
# driverを終了する
driver.quit()
出力結果
<li><div class="_3Ip8DQAJYKfPeByyVN-utZ"><a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="https://app.adjust.com/1kmi1m2?redirect=https%3A%2F%2Fpaypayfleamarket.yahoo.co.jp%2F%3Fcpt_s%3Dytopmedia%26cpt_m%3Dkotei%26cpt_n%3Dcontent%26cpt_c%3Dytopmedia" aria-label="PayPayフリマへ遷移する" data-cl-params="_cl_vmodule:tool;_cl_link:paypayflea_139;_cl_position:3;svcid:139" data-cl_cl_index="3"><p class="_2bBRLhI5ZpVYu0tuHZEFrn"><span class="pz0On1w4yAviBGMdKItoQ"><span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">PayPayフリマ</span></span><span class="_1Al3K70np2V_Ev1eGkfsBm"><span class="_2Uq6Pw5lfFfxr_OD36xHp6 _1dr5aVDbNPF63JCS2bJhij _3zb-zxOYGPoHJ2-_Ie8y8T" style="width:20px;height:20px"></span></span></p></a></div></li>
まとめ
今回はseleniumライブラリでXPathを使った要素の取得方法を紹介しました。
Webスクレイピングをマスターすると、情報収集が圧倒的にラクになります。
- 仕事で毎日行うデータ収集
- 予約サービスへの自動登録・応募
- ショッピングサイトの価格監視
などなど、さまざまな分野で応用できます。
PythonのWebスクレイピング技術を体系的に学びたい、という方に向けてUdemyで動画学習コースを公開しています!
\ Webスクレイピング技術が一気に学べる!! /
Webスクレイピングで日々の作業を自動化し、より有意義な時間を増やしましょう!!