質問: 上記サイトの各地方・各裁判所・全物件の全データを並べたcsvファイルを作成したいと考えています。 GoogleChromeで各地方のリンクをSeleniumから要素を取得、クリック、ページ遷移ができません。 該当場所のリンクがhref="javascript:void(0)"となっており、調べてみたところ以下のサイトがヒットし、Javascript特有の挙動で、それに合わせたスクレイピングをしなければいけないことはわかりました。 ブラウザの表示内容を取得するには? | requestsで取得できないWebページをスクレイピングする方法 しかし、以下の項目がいまいちわかっておらず、躓いています。 * そもそもJavascriptの要素をseleniumで操作可能なのか * 様々なリンクテキストのhrefが"javascript:void(0)"でどうやって各ページ異なる内容を表示しているのか * requests_htmlのHeadlessモードでどうやって要素の検索や絞り込みをすればよいのか 初心者で至らない点多々あるかと思いますが、よろしくご教授いただけますと幸いです。 環境 OS: Windows 10 Python: 3.8 Pycharm
回答: **そもそもJavascriptの要素をseleniumで操作可能なのか** 可能です。例えばドキュメントにはこんなのが記載されています。 selenium-webdriver ページ内でJavascriptを実行する > > Python > > PythonでJavascriptを実行するには、 execute_script("javascript script here")ます。 execute_scriptはwebdriverインスタンスで呼び出され、有効なjavascriptにすることができます。 > > > > ``` > from selenium import webdriver > driver = webdriver.Chrome() > driver.execute_script("alert('running javascript');") > > ``` > > **様々なリンクテキストのhrefが"javascript:void(0)"でどうやって各ページ異なる内容を表示しているのか** html/css/javascriptのソースを見ると、各要素にIDや番号を割り振って`.click()`処理を登録しておき、それらをパラメータにしてページを呼び出しているようです。 のhtmlソース のSCPT003.js, common.js, common_env.jsソース `common.js`に各都道府県のIDと名前のリストおよび相互変換ルーチンとか下記で使っている`commonSubmit()`があります。 呼び出し処理は`SCPT003.js`の以下のあたりが該当しそうです。 > > > ``` > $("#map a").click(function () { > idName = $(this).attr("id"); > tdfId = getTdfNameToId(idName); > $("#prefecturesId").val(tdfId); > eventID = "h02"; > copyToHiddenValue(); > (event.preventDefault) ? event.preventDefault():event.returnValue=false; > (event.stopPropagation) ? event.stopPropagation():event.returnValue=false; > commonSubmit(eventID); > }); > > $(".arrow_list li a").click(function () { > courtId = $(this).closest("li").find("span")[0].innerText; > $("#courtId").val(courtId); > eventID = "h03"; > copyToHiddenValue(); > (event.preventDefault) ? event.preventDefault():event.returnValue=false; > (event.stopPropagation) ? event.stopPropagation():event.returnValue=false; > commonSubmit(eventID); > }); > > $("#search").click(function(event) { > var eventID = "h20"; > copyToHiddenValue(); > (event.preventDefault) ? event.preventDefault():event.returnValue=false; > (event.stopPropagation) ? event.stopPropagation():event.returnValue=false; > commonSubmit(eventID); > }); > > ``` > > **requests_htmlのHeadlessモードでどうやって要素の検索や絞り込みをすればよいのか** 古いですが、以下記事によるとrequests_htmlでは簡単な呼び出し方法は無いようです。 最新のものには何かあるかもしれませんし、2つ目記事のようにJavaScriptを記述して呼び出す方法が取れるのかもしれません。 Sending a click with requests_html and pyppeteer python 結局動かなくてSeleniumに切り替えたというコメントがあります。 Python requests_html submit a form by clicking a button using JQuery 質問自身もそうですが、生のJavaScript処理を書いて実行しています。 あるいはこちらの記事のようにアクセス方法によっては直接全件取得出来るのかもしれません。 How to click 'Next' for pagination using Requests-HTML library データは最初に全件取得されているという例です。 Python スクレイピング テーブル取得不可 裏技的に全件取得する方法があるというコメントがあります。 さらには都道府県IDと裁判所IDが分かっているので、こちら記事の@metropolisさん回答のようにフォームデータを組み立てて要求を出すというのでも良いかもしれません。 Pythonのスクレイピングでデータが取得できない `Selenuim`だと以下のような手順で出来るでしょう。 1. 過去データ検索のページを取得する `driver.get('http://bit.sikkou.jp/app/past/pt003/h01/')` 2. 都道府県を選択してクリックする(以下は東京都の例) `driver.find_element_by_xpath('//*[@id="tokyo"]').click()`か`driver.find_element_by_id('tokyo').click()` 3. 裁判所を選択してクリックする リストの1番目は`driver.find_element_by_xpath('//*[@id="left_box"]/div[3]/div[2]/ul/li[1]/a').click()` リストの2番目は`driver.find_element_by_xpath('//*[@id="left_box"]/div[3]/div[2]/ul/li[2]/a').click()` それぞれの都道府県に裁判所が幾つあるかはリストの要素数で判断する 4. 必要ならば検索条件選択・指定を行う 5. 「検索する」ボタンをクリックする `driver.find_element_by_xpath('//*[@id="search"]').click()`か`driver.find_element_by_id('search').click()` 6. 読み取ったデータから物件情報をリスト化して取得する