py-py’s blog

何か書くよ

スクレイピングメモ【追記あり】

以前

py-py.hatenablog.com

↑でキーを押しながら要素をクリックする、ということを書いたが、これに関連しそう&いろいろ詰まったことがあったのでメモ

結論

一覧に戻るやトップページに戻るなどのリンクやボタンを押すプログラムを組むときは、別タブを用意する

【追記】 キーを押しながらクリック→別タブ開いて処理を進めるスクレイピングについて。

webdriver.Chrome('chromedriver.exe')

とchromedriverを利用するなら別タブは開ける。

しかし、PhantomJS()を使うとキー押しながら要素クリックをするとエラーが起きる

こちらですね。

stackoverflow.com

but one thing to keep in mind is PhantomJS is a headless browser. There are no "tabs" such as what you see in Firefox, Chrome, etc.

はい、申し訳ございませんでした。

前提

一覧に戻る系のlinkやボタンがあるサイトにおいて、クローリングを行う

処理の流れ

  • find_elements_XX系関数で、欲しい要素を複数取得 ①
  • 複数要素をforで回し、それぞれclickする ②
  • なんやかんやの処理 ③

一覧に戻るやトップページに戻るなどのクリックして、一覧画面に戻ることをしないクローリングは
上の①②③の順でそのまま順々にクローリングが可能。

だが、それらをクリックする場合のクローリングプログラムを組んだ時は

  • スクレイピングプログラムを実行した際、一番最初に一覧画面に遷移する ア
  • 各種クローリングから一覧に戻るを押下→一覧画面に遷移する イ

上記アとイでは見かけやURLは同じだが、内部では違う(ような気がする)。

推定だし自分のようなプヨグラマが書いていることなので、もしかしたら同じかもしれない。
が、自分がプログラム書いているときは一緒だと思い、延々とエラーを繰り返していた。

①②を行い要素を複数取得し、forで回したところ一つ目は③まで進む。
しかし、また②に戻ってclickすると要素がないと怒られてしまう。

サイトの構造によっていろいろあるのだろうが、今回自分がスクレイピング対象としていたサイトは

  • 大カテゴリ A
  • 中カテゴリ B
  • データ   C

↑な感じで、それぞれ簡易的な説明をすると

  • A ・・ 一覧画面。トップページ。
  • B ・・ 一覧画面に戻るボタンがある。
  • C ・・ 閉じるボタンがある。

A→Bに遷移するとき、同じタブ内でBに遷移する。
B→Cに遷移するとき、新しいタブが開き遷移する。

A→B→Cと処理を進め、Cのタブを閉じ、Bの一覧へ戻るボタンからAに戻ると要素がない。

結局どうした

ActionChains()を使い、A→Bのところを新規タブで開くように変更。

今までは(適当なコード)

def click_with_control(link: WebElement):
    actions = ActionChain(driver)
    actions.key_down(Keys.CONTROL)
    actions.click(link)
    actions.key_up(Keys.CONTROL)
    actions.perfrom()
    driver.switch_to.window(driver.window_handles[1]

links: list[WebElement] = driver.find_elements_by_xpath(xpath)
for link in links:
    click_with_control(link)

新規タブを開いていたが、今回はやり方を変えて

while True:
    num = 0
    link: WebElement = driver.find_element_by_xpath(f"{num}/hogehoge")
    link.click()
    driver.switch_to.window(driver.window_handles[1]
    """別の関数呼び出し"""
    num += 1

とwhile文で毎度linkをxpathで指定して取得するように変更