質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

2回答

414閲覧

seleniumで2周目のループで詰まってしまう

noggi

総合スコア8

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2024/01/18 18:52

編集2024/01/19 20:53

実現したいこと

初心者質問で申し訳ありませんがよろしくお願いします。

こちらのHP
より、seleniumを使って商品名とリンクを抽出したいです。
1、ブランド名入力
2、素材名入力
3、商品データがあれば抽出
4、抽出終了、または商品データがなければ素材名をクリアして次の素材名入力
5、素材名を1周したら次のブランド名で同様の処理
6、dfをつくる

3までできていますが、4の処理でうまくいきません。

発生している問題・分からないこと

ループ処理でうまくいきません。else:内が、browser.back()だと動くのですが、2周目の処理でエラーになります。本当はブラウザバックではなく、最上部にスクロールでも同様の入力ボックスがあるので大丈夫?なので、そちらも試してみましたがうまくいきませんでした。
スクロール後画面にある、入力ボックスをクリアし、次の素材名を入力できるようにしたいです。

そもそもループ処理について学習中ですので、whileの使い方に不安があります・・。

(追記)
ブランド名入力→素材名入力→Nextpageがないので戻って素材名クリア→次の素材名入力→データ抽出・完了→Nextpageがでなくなるまで読み込んだので戻って次の素材名入力、としたいのですがここで以下のエラーが出ます。

該当のソースコード

python

1from selenium import webdriver 2from selenium.webdriver.common.by import By 3import time 4import tqdm 5import pandas as pd 6from selenium.webdriver.chrome.options import Options 7from selenium.webdriver.common.keys import Keys 8 9df = pd.read_excel("2.xlsx") 10INCI = df["INCI"].to_list() 11df_brand = pd.read_excel('2.xlsx', sheet_name='Brands') 12Brand = df_brand["Brand List"].to_list() 13 14MIN_INTERVAL = 0.5 15INTERVAL = 2.5 16MINUTE_INTERVAL = 60 17 18#options = Options() 19#options.add_argument("--headless") 20browser = webdriver.Chrome() 21time.sleep(INTERVAL) 22browser.get("https://incidecoder.com") 23time.sleep(INTERVAL) 24action = webdriver.ActionChains(browser) 25 26#roop 27for B in Brand: 28 browser.find_element(By.ID, "query").send_keys(B) 29 browser.find_element(By.XPATH, "//div[1]/div[2]/div[1]/form/input[2]").click() 30 time.sleep(INTERVAL) 31 32 for I in INCI: 33 FIND_BOX = browser.find_element(By.XPATH, "//*[@id='products']/form/div[1]/div/div/span/span[1]/span/ul/li/input") 34 PUT_ING = FIND_BOX.send_keys(I) 35 time.sleep(INTERVAL) 36 action.send_keys(Keys.ENTER).perform() 37 38 FILTER = browser.find_element(By.XPATH, "//*[@id='products']/form/input[2]") 39 FILTER.click() 40 time.sleep(INTERVAL) 41 42 browser.execute_script("window.scrollTo(0,document.body.scrollHeight);") 43 #input("continue?") 44 time.sleep(INTERVAL) 45 46 FIND_PLACE = browser.find_elements(By.CSS_SELECTOR, "div[class=std-side-padding] > a") 47 for i in FIND_PLACE: 48 print(i.text) 49 print(i.get_attribute('href')) 50 time.sleep(INTERVAL) 51 52 browser.execute_script("window.scrollTo(0,document.body.scrollHeight);") 53 time.sleep(INTERVAL) 54 55 while True: 56 if len(browser.find_elements(By.PARTIAL_LINK_TEXT, "Next page")) >0: 57 NEXT = browser.find_element(By.PARTIAL_LINK_TEXT, "Next page") 58 NEXT.click() 59 time.sleep(INTERVAL) 60 61 FIND_PLACE = browser.find_elements(By.CSS_SELECTOR, "div[class=std-side-padding] > a") 62 for i in FIND_PLACE: 63 print(i.text) 64 print(i.get_attribute('href')) 65 time.sleep(INTERVAL) 66 67 else: 68 browser.back() 69 time.sleep(INTERVAL) 70 CLEAR = browser.find_element(By.CLASS_NAME, "select2-selection__choice__remove") 71 CLEAR.click() 72 break 73

html

1<div class="my-select2-wrapper"> 2 <span class="my-select2-prerender select2 select2-container select2-container--default select2-container--below" dir="ltr"> 3 4 <span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1"> 5 <span class="selection"> 6 <ul class="select2-selection__rendered"> 7 8 <li class="select2-selection__choice"> 9 <span class="select2-selection__choice__remove" role="presentation">×</span>Sodium PCA 10 </li>

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

・action.move_to_element(CLEAR).perform()
・browser.execute_script("window.scrollTo(0,0);")
など、ネットで調べながら色々試してみましたがうまくいきませんでした。

補足

エラーメッセージ
Traceback (most recent call last):
File "/main.py", line 73, in <module>
CLEAR.click()
File "/webelement.py", line 94, in click
self._execute(Command.CLICK_ELEMENT)
File "/webelement.py", line 395, in _execute
return self._parent.execute(command, params)
File "/webdriver.py", line 348, in execute
self.error_handler.check_response(response)
File "/errorhandler.py", line 229, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
(Session info: chrome=120.0.6099.234)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2024/01/19 13:23

> ループ処理でうまくいきません。 発生している現象を書きましょう。エラーメッセージが出て止まるとか、実行が1時間以上続いているとか、エラーは出ずに正常終了するが期待と違う結果が出力されるとか。。 「【うまくいく】ことが発生していない」のように「発生していないこと」を書くのは無意味です。
guest

回答2

0

ブラウザの Developer Tools で HTTP 通信を覗いてみると、HTTP GET でクエリを発行していることが判ります。(HTML form) 例えば、ブランド名が chanel で素材名が Water の場合は以下の URL にアクセスします。

https://incidecoder.com/search/product?query=chanel&include=Water

レスポンス(商品データ)が複数のページに分割される場合は page(ページ番号)を指定します。

https://incidecoder.com/search/product?query=chanel&include=Water&page=2

なので、Selenium の代わりに requests + BeautifulSoup でも必要な情報を取得することができます。

python

1import requests 2from bs4 import BeautifulSoup 3from urllib.parse import urljoin, urlparse, parse_qs 4from pprint import pprint 5 6SEARCH_URL = 'https://incidecoder.com/search/product' 7 8def extract_products_info(brand_name, ingredient, nth_page=1): 9 # query by brand name 10 params = { 'query': brand_name, 'include': ingredient, 'page': nth_page } 11 response = requests.get(SEARCH_URL, params=params) 12 response.raise_for_status() 13 14 # extract products name and url 15 soup = BeautifulSoup(response.text, 'html.parser') 16 link = soup.select('a.klavika.simpletextlistitem') 17 products = [] 18 for l in link: 19 products.append({'name': l.text, 'url': urljoin(SEARCH_URL, l['href'])}) 20 21 # follow next page 22 next_page = soup.select_one('a:-soup-contains("Next page")') 23 if next_page is None: # last page 24 return products 25 26 # next page 27 page = parse_qs(urlparse(next_page['href']).query)['page'][0] 28 products += extract_products_info(brand_name, ingredient, page) 29 return products 30 31if __name__ == '__main__': 32 Brand = ['chanel', 'skinceuticals'] 33 INCI = ['Water', 'Silica'] 34 35 result = [] 36 for B in Brand: 37 for I in INCI: 38 products = extract_products_info(B, I) 39 result.append({'Brand': B, 'Ingredient': I, 'Products': products}) 40 41 pprint(result) 42 43# [{'Brand': 'chanel', 44# 'Ingredient': 'Water', 45# 'Products': [{'name': 'Chanel Signature De Chanel', 46# 'url': 'https://incidecoder.com/products/chanel-signature-de-chanel'}, 47# {'name': 'Chanel N°1 De Chanel Revitalizing Serum', 48# 'url': 'https://incidecoder.com/products/chanel-ndeg1-de-chanel-revitalizing-serum'}, 49# : 50# 51# {'Brand': 'chanel', 52# 'Ingredient': 'Silica', 53# 'Products': [{'name': 'Chanel N°1 De Chanel Revitalizing Foundation', 54# 'url': 'https://incidecoder.com/products/chanel-ndeg1-de-chanel-revitalizing-foundation'}, 55# {'name': 'Coco chanel CHANEL JOUES CONTRASTE 71 Malice', 56# 'url': 'https://incidecoder.com/products/coco-chanel-chanel-joues-contraste-71-malice'}, 57# : 58# 59# {'Brand': 'skinceuticals', 60# 'Ingredient': 'Water', 61# 'Products': [{'name': 'SkinCeuticals Emollience', 62# 'url': 'https://incidecoder.com/products/skinceuticals-emollience'}, 63# {'name': 'SkinCeuticals Gentle Cleanser', 64# 'url': 'https://incidecoder.com/products/skinceuticals-gentle-cleanser'}, 65# : 66# 67# {'Brand': 'skinceuticals', 68# 'Ingredient': 'Silica', 69# 'Products': [{'name': 'SkinCeuticals A.G.E. Eye Complex', 70# 'url': 'https://incidecoder.com/products/skinceuticals-a-g-e-eye-complex-2'}, 71# {'name': 'SkinCeuticals Sheer Physical Uv Defense Spf 50', 72# 'url': 'https://incidecoder.com/products/skinceuticals-sheer-physical-uv-defense-spf-50'}, 73# : 74#

投稿2024/01/20 13:30

編集2024/01/20 13:38
melian

総合スコア19825

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noggi

2024/01/21 18:38

わざわざコード全容を記載していただいてありがとうございます、beautiful soupは使った事がないので、やってみます。勉強になりました、ありがとうございました。
guest

0

ベストアンサー

エラーメッセージでは、73行目のCLEAR.click()でエラーとなっていますが、掲載のプログラムは73行目にCLEAR.click()がありません。エラーメッセージは、掲載のプログラムを実行した時に出た物を載せましょう。

71行目にCLEAR.click()があるので、これのこととして続けます。

click()に対しての Message: element not interactable は、該当エレメントがその時クリックできないという意味です。原因は色々考えられます。
1.そもそも要素が違う
2.属性などでクリックできなくなっている。人手でクリックできるなら、最初はクリックできないが1秒とか待つとクリックできるようになっている可能性がある
3.上に別の要素が重なっている。これも人手でクリックできるなら、時間を待てば良いかも
4.その他

1の可能性としては、クラス名select2-selection__choice__removeで検索していますが、同じクラス名を持つ要素は1つとは限りません。もし複数あった場合、find_elementはそのうちの1つ目のものを選択しますが、実際は2番目以降が目的の要素だったというケース。
これは、find_elementsと複数形のメソッドにして、
print( len(browser.find_elements(By.CLASS_NAME, "select2-selection__choice__remove")))
が1かどうかで分かります。
2,3の可能性は、click()の直前に、input("OK?")等と入れて、プログラムの実行を一旦待ちにして、その段階で手動でクリックできるかどうか。出来るなら、しばらく待てば良いでしょう。

投稿2024/01/20 07:00

otn

総合スコア84572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noggi

2024/01/21 18:35

ページ遷移後の要素が指定できていませんでした。一旦止めて、その時点でコードがどうなっているのか確認することで、修正できました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問