実現したいこと
スクレイピングの際に、データをもれなく正確に取得したいです。
ご教授よろしくお願いいたします。
前提
1ページあたり320ほどのデータがあります。現在のコードでは、プログラム動作直後は問題なく動きますが、すこしづつ処理に遅れが生じます。最終的に出来上がったデータフレームは当然漏れだらけという状況です。これを正確にきちんと取得したいです。
サイトについてですが、スクレイピングは許可されており、極力負荷をかけないようにしています。
発生している問題・エラーメッセージ
エラーは特に発現していない。
該当のソースコード
python
1from selenium import webdriver 2from selenium.webdriver.chrome.service import Service 3from selenium.webdriver.chrome.options import Options 4from selenium.webdriver.common.keys import Keys 5from selenium.webdriver.common.by import By 6from selenium.webdriver.support.ui import WebDriverWait 7from selenium.webdriver.support import expected_conditions as EC 8 9import time 10import warnings 11 12warnings.simplefilter('ignore', FutureWarning) 13 14#Optionsで画像非読込などの設定 15options = Options() 16options.add_argument('--disable-extensions') 17options.add_argument('--blink-settings=imagesEnabled=false') 18service = Service('C:/Users/detec/pg/chromedriver.exe') 19driver = webdriver.Chrome(service=service, options=options) 20wait = WebDriverWait(driver,60) 21 22#webdriver起動 23TARGET_URL = "#" 24driver.get(TARGET_URL) 25time.sleep(4) 26 27# create an empty DataFrame 28df = pd.DataFrame(columns=['A, 'B', 'C', 'D']) 29 30 31while True: 32 #A,B,C,Dの値を取得するまで待機する 33 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.#A'))) 34 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.#B'))) 35 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.#C'))) 36 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.#D'))) 37 38 #A,B,C,Dの値を見つけて、変数として格納する 39 A = driver.find_elements(By.CSS_SELECTOR, '.#A') 40 B = driver.find_elements(By.CSS_SELECTOR, '.#B') 41 C = driver.find_elements(By.CSS_SELECTOR, '.#C') 42 D = driver.find_elements(By.CSS_SELECTOR, '.#D') 43 44 # Next Pageのボタンを探して、次のページへ。もしdisableならbreak 45 next_button = driver.find_element(By.CLASS_NAME, 'pagination-next') 46 driver.execute_script("arguments[0].scrollIntoView();", next_button) 47 if next_button.get_attribute('disabled') == 'true': 48 break 49 50 next_url = next_button.get_attribute('href') 51 driver.get(next_url) 52 time.sleep(3) 53
試したこと
- time.sleep(n)の挿入。nの部分は0.5~10まで変更させました。また、スリープの場所はある程度試し済みです。
- time.sleep(n)を使わず、wait.untilに置き換えました。前者ではアクセス負荷をかけないためには使えるが、取得などを待つことはできないということで置き換えました。
- ChatGPTを使って、細かい部分の変更は調整しましたが、解決できていません。
補足情報(FW/ツールのバージョンなど)
Python 3.9
「1ページあたり320ほどのデータ」というのは、どういう風に取得していますか?
#A #B 相当が実は4個じゃなくてが320個あると言うことでしょうか?
コメントありがとうございます。
取得してるデータはA~Bの4つなのですが、その塊が40個~80個あるということです。
ECサイトをイメージしていただければと思いますが、商品が横に4つ並んでいて、その中に価格などのデータがあります。さらにそれが20行~あるというような感じです。
> すこしづつ処理に遅れが生じます。
上記はどういうことでしょうか?”遅れ”とはseleniumの動作が重くなる?ということでしょうか?(メモリの問題?)
> 最終的に出来上がったデータフレームは当然漏れだらけという状況です。
すみませんが何が”当然”なのか説明いただけますでしょうか?サイトの情報更新速度がとても速いのでしょうか??
失礼しました。#が目立ったので、てっきりidかと思ったのですが、よく見るとピリオドがあるので、クラスでしたね。
データを取得し始めてから取得し終わるまでに、ページが更新されているとかですかね。
wait.untilが全部終わった時点と、次ページに遷移する直前のそれぞれで、
page_souceを取得して比べてみるとかでしょうか。
それが原因だとすると、ページ更新状況を把握しながらデータを取得しないといけなさそうです。
もしくは検索条件で時間指定が出来れば、ちょっと前までのデータだけ見るとか。
print(data)やprint(len(df))で出力したデータや数字を比較すると明らかに少ない数が表示されます。
その後、CSV出力などをしてもデータ数が少ないため、漏れがあると考えられます。
動作が重くなるというよりは、データを取得する処理もしくはdfに格納する処理が遅れていると思います。
「当然」という言葉を使ったのは、処理が遅れておりprintされるデータが少ないため、最終的に取得できるデータも当然少ないという意味で使っておりましたが、わかりづらく表現してしまい申し訳ありません。
page_sourceをしてみたところ、かなり容量が重いようで読み込みに時間がかかってしまっているのかもしれません。
漏れているというか、単純に欲しい要素が取得できていないという可能性は無いのでしょうか?
調べてみたところ、HTMLファイルが大きいのでmeg_様のおっしゃる通り取得できていないという可能性が高そうです。
ループのそれぞれの回で、それぞれ2つのpage_souceは全部一致したのでしょうか、一致しなかった回があったのでしょうか?まだ調査中ですか?
すいません。HTMLファイルが大きく、Jupiterではさばききれないみたいです、、、
> HTMLファイルが大きく、Jupiterではさばききれないみたいです、、、
もしかして、画面に表示して、目検で比較しようとしていた??目検では無理では?
コードを書くために回答にに書きます。
> 1ページあたり320ほどのデータがあります。
上記はスクレイピングで取得した情報から得た数値でしょうか?(目視の情報と合っているかの確認です)
いえ、ウェブサイトを訪問し、目視で確認した情報です。
そしてスクレイピングで取得した情報から得た数値はおよそその80%(1ページ目)でした。
処理が進むにつれて、その数値の%は減っていきます。
> スクレイピングで取得した情報から得た数値はおよそその80%(1ページ目)でした。
1ページ目で既に欠損が発生しているのですね。
そのページをローカルに保存してスクレイピングした場合は欲しいデータを全て取得出来ますか?
ダウンロードするとデータがきちんと表示されないみたいです。
「ご指定のページが見つかりませんでした」となります。
