🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
スクレイピング

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

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

Q&A

解決済

2回答

1056閲覧

Pythonでのスクレイピングについて教えてください。

mugen0905

総合スコア1

スクレイピング

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

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

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

0グッド

0クリップ

投稿2021/02/04 14:20

編集2021/02/05 15:36

Pythonでのスクレイピングのコードについてご教示いただきたいです。

スクレイピングを利用し、ブラウザ上のシステムから情報を取得しエクセルへ入力していく
操作をしたいと思っています。管理番号で検索を行い、検索結果があった際はページが切り替わり、
情報が表示されます。検索結果がなかった際はアラートが表示されます。

if文などを使い、アラートが出た際と出なかった際で条件分岐し、操作を指定したいのですが、条件分岐がうまくいきません。

パターン①if文でid属性を指定

python

1NoId = 0000 2 3#while文 4while NoId <= 1000: 5 6 # 検索ボックスに「ID番号」を入力して、Enterキーを押す 7 driver.find_element(By.ID, "j_id0:KeiyakuNoId").send_keys(str(NoId) + Keys.ENTER) 8 9 # [検索]ボタンをクリック 10 driver.find_element(By.ID, "search").click() 11 time.sleep(1) 12 13 #id属性を確認 14 if len(driver.find_elements_by_id("j_id0:j_id1"))>0: 15 16 #ID属性の指定 17 body = driver.find_element(By.ID, "keiyaku-itiran") 18 19 #dd要素の指定 20 links = driver.find_elements(By.TAG_NAME, "dd") 21 22 #リスト作成 23 data_list = [] 24 25 for link in links: 26 link_text = link.text 27 data_list.append(link_text) 28 29 #エクセル出力 30 for data in data_list: 31 ws_new["A"+str(row_num)].value = data_list[3] 32 ws_new["B"+str(row_num)].value = data_list[5] 33 ws_new["C"+str(row_num)].value = data_list[6] 34 ws_new["D"+str(row_num)].value = data_list[7] 35 36 wb_new.save("管理情報.xlsx") 37 38 #ページを更新して戻る 39 driver.refresh() 40 41 NoId += 1 42 43 else: 44 45 # アラートを消す 46 Alert(driver).accept() 47 48 #ページを更新して戻る 49 driver.refresh() 50 51 NoId += 1

条件を満たす際は、if以降の操作を実行しますが、elseの際がエラーとなり以下のメッセージが表示されます。

Message: unexpected alert open: {Alert text : 指定されたお客様の情報がございません。

検索条件をご確認のうえ、再度操作してください。(処理結果コード 1:正常完了 業務処理結果コード 2:対象契約なしエラー)}

elseの際は、ページを更新して、次のID番号に進んでほしいのですが、上記の条件分岐したコードでは、ページが更新されずそこで止まってしまいます。
条件分岐を入れず、アラート消すコードだけで下記のように記載した際は、アラートを消し、ページを更新し、次々とID番号を更新して進んでいきます。

python

1NoId = 0000 2 3while NoId <= 1000: 4 5 # 検索ボックスに「ID番号」を入力して、Enterキーを押す 6 driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys(str(NoId) + Keys.ENTER) 7 8 # [検索]ボタンをクリック 9 driver.find_element(By.ID, "search").click() 10 11 # 1秒待つ 12 time.sleep(1) 13 14 # アラートを消す 15 Alert(driver).accept() 16 17 #ページを更新して戻る 18 driver.refresh() 19 20 NoId += 1

パターン②if文でアラートを指定

python

1NoId = 0000 2 3#while文 4while NoId <= 1000: 5 6 # 検索ボックスに「ID番号」を入力して、Enterキーを押す 7 driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys(str(NoId) + Keys.ENTER) 8 9 # [検索]ボタンをクリック 10 driver.find_element(By.ID, "search").click() 11 time.sleep(1) 12 13 #アラートを確認 14 if driver.switch_to.alert: 15 16 # アラートを消す 17 Alert(driver).accept() 18 19 #ページを更新して戻る 20 driver.refresh() 21 22 NoId += 1 23 24 else: 25 26 #ID属性の指定 27 body = driver.find_element(By.ID, "keiyaku-itiran") 28 29 #dd要素の指定 30 links = driver.find_elements(By.TAG_NAME, "dd") 31 32 #リスト作成 33 data_list = [] 34 35 for link in links: 36 link_text = link.text 37 data_list.append(link_text) 38 39 #エクセル出力 40 for data in data_list: 41 ws_new["A"+str(row_num)].value = data_list[3] 42 ws_new["B"+str(row_num)].value = data_list[5] 43 ws_new["C"+str(row_num)].value = data_list[6] 44 ws_new["D"+str(row_num)].value = data_list[7] 45 46 wb_new.save("管理情報.xlsx") 47 48 #ページを更新して戻る 49 driver.refresh() 50 51 NoId += 1

条件を満たす際は、if以降の操作を実行しますが、elseの際がエラーとなり以下のメッセージが表示されます。

Message: no such alert

(Session info: chrome=87.0.4280.141)

こちらのコードでは、アラートを消して次のID番号へと進んでいくのですが、アラートをが出なかった際に、情報取得の操作が実行されず、そこで止まってしまいます。

良い条件分岐の方法があればご教示いただきたいです。
その他以下も併せて指定したいです。
・管理番号の検索範囲を「0000~1000」など指定したい
・取得情報をエクセル入力する際、1行ずつ下げていきたい

宜しくお願い致します。

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

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

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

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

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

t_obara

2021/02/04 14:48

コードは```で囲ってください。 検索結果があった場合とない場合の区別を提示された情報から判断することができないです。 例えば、検索結果がある場合は特定の要素があるのであれば、その要素をfindしてみるとかになると思います。検索結果がある場合とない場合のHTMLソースを提示いただくか、ご自身で判断していただくしかないと思います。
mugen0905

2021/02/04 15:20

ご教示いただき有難うございます。 わかりづらい質問で申し訳ございません。 仰る通り、検索結果があった場合ではページが切り替わり、HTMLソースのbody要素の中にid属性(j_id0:j_id1)がありますので、 if id属性 == "j_id0:j_id1": とコードを書けば条件が指定できますでしょうか? 上記「id属性」の部分をどのうように書けばいいのかご教示いただけますでしょうか。
guest

回答2

0

python

1 2NoId = 0000 3 4#while文開始 5while NoId <= 1000: 6 7 #ボックスに「ID番号」を入力して、Enterキーを押す 8 driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys("x"+str(NoId) + Keys.ENTER) 9 10 try: 11 driver.find_element(By.ID, "search").click() 12 body = driver.find_element(By.ID, "keiyaku-itiran") 13 links = driver.find_elements(By.TAG_NAME, "dd") 14 15 #エクセル出力 16 for (data, col) in zip(links[3:8], ["A","B","C","D","E"]): 17 ws[col+str(row_num)].value = data.text 18 19 wb.save("情報.xlsx") 20 21 row_num += 1 22 23 #ページを更新して戻る 24 driver.refresh() 25 26 except Exception as ex: 27 28 time.sleep(1) 29 30 #ページを更新して戻る 31 driver.refresh() 32 33 NoId += 1 34#while文終了 35

投稿2021/02/06 11:34

mugen0905

総合スコア1

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

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

0

ベストアンサー

まず、ページが確実に遷移したことを確認するために、検索結果がある場合でもない場合でも存在する要素を見つけるようにしましょう。単に1秒とかだと、環境によって、あるいは他のアプリの動作状況やネットの状況などで動作が異なる場合があります。

検索結果がある場合のID属性がj_id0:j_id1の場合、
遷移した後で、find_element_by_id("j_id0:j_id1")で要素を検索し、要素があるか否かで条件分岐すれば良いです。

投稿2021/02/04 15:43

t_obara

総合スコア5488

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

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

mugen0905

2021/02/04 16:36 編集

ご教示いただき有難うございます。 'if driver.find_element_by_id("j_id0:j_id1")'や 'if len(driver.find_elements_by_id("j_id0:j_id1"))>0:'を 試してみました。 ifの時の操作は正常に動作しますが、elseの時がエラーとなってしまいます。 (エラー文) Message: unexpected alert open: {Alert text : 指定された情報がございません。 検索条件をご確認のうえ、再度操作してください。(処理結果コード 1:正常完了 業務処理結果コード 2:対象契約なしエラー)} (Session info: chrome=87.0.4280.141) 原因わかりますでしょうか。
t_obara

2021/02/04 23:58

条件分岐ができていて、else時の処理(おそらくアラートを消す処理)に問題があるということですよね。 これは本当にelseと判断できたことが正しいのですか?それともアラートを消す処理に問題があるのですか? 条件分岐が正しくできたのであれば、この質問は完了ではないのですか?
mugen0905

2021/02/05 05:33

アラートを消す処理は条件分岐を付けずに単独で実行すると正常にアラートを消せるので、問題はないように思います。 ちなみに、アラートが出たかどうかで条件分岐することは可能でしょうか? 試しに'if driver.switch_to.alert:'で実行してみたところ、アラートが出た際は正常に動作しましたが、今度はアラートが出なかった際に「Message: no such alert」となりエラーとなってしまいました。
t_obara

2021/02/05 07:22

最終的なコードがどうなっているのか分からないので、問題ないか判断ができません。 例外をキャッチして判断することもできなくはないですが、あまり推奨される方法ではないです。
mugen0905

2021/02/05 12:42

NoId = 0000 #for文 while NoId <= 1000: # 検索ボックスに「ID番号」を入力して、Enterキーを押す driver.find_element(By.ID, "j_id0:KeiyakuNoId").send_keys("x"+str(NoId) + Keys.ENTER) # [検索]ボタンをクリック driver.find_element(By.ID, "search").click() time.sleep(1) #id属性を確認 if len(driver.find_elements_by_id("j_id0:j_id1"))>0: #ID属性の指定 body = driver.find_element(By.ID, "keiyaku-itiran") #dd要素の指定 links = driver.find_elements(By.TAG_NAME, "dd") #リスト作成 data_list = [] for link in links: link_text = link.text data_list.append(link_text) #エクセル出力 for data in data_list: ws_new["A"+str(row_num)].value = data_list[3] ws_new["B"+str(row_num)].value = data_list[5] ws_new["C"+str(row_num)].value = data_list[6] ws_new["D"+str(row_num)].value = data_list[7] wb_new.save("管理情報.xlsx") #ページを更新して戻る driver.refresh() NoId += 1 else: # アラートを消す Alert(driver).accept() #ページを更新して戻る driver.refresh() NoId += 1
mugen0905

2021/02/05 15:02 編集

NoId = 0000 #for文 while NoId <= 1000: # 検索ボックスに「ID番号」を入力して、Enterキーを押す driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys("x"+str(NoId) + Keys.ENTER # [検索]ボタンをクリック driver.find_element(By.ID, "search").click() time.sleep(1) #アラートを確認 if driver.switch_to.alert: # アラートを消す Alert(driver).accept() #ページを更新して戻る driver.refresh() NoId += 1 else: #ID属性の指定 body = driver.find_element(By.ID, "keiyaku-itiran") #dd要素の指定 links = driver.find_elements(By.TAG_NAME, "dd") #リスト作成 data_list = [] for link in links: link_text = link.text data_list.append(link_text) #エクセル出力 for data in data_list: ws_new["A"+str(row_num)].value = data_list[3] ws_new["B"+str(row_num)].value = data_list[5] ws_new["C"+str(row_num)].value = data_list[6] ws_new["D"+str(row_num)].value = data_list[7] wb_new.save("管理情報.xlsx") #ページを更新して戻る driver.refresh() NoId += 1
mugen0905

2021/02/05 13:03

すみません、インデントがなく見づらいですが、上記のような2パターンを試してみました。 1つ目は、id属性を指定し、id属性があればif以降を実行するようにコードを書きました。条件を満たす際には成功に動作しましたが、elseの際に動作しませんでした。 2つ目は、アラートが出た際にif以降を実行するようにコードを書きました。条件を満たす際には成功に動作しましたが、elseの際に動作しませんでした。
t_obara

2021/02/05 14:02

質問自体編集できるので、そちらに追記いただいた方が、インデントもわかります。 上の2つは同じコードでは?アラートが出たか否かを判断するコードが見当たりません。例外なしに判断できますか? もう一度確認しますが、一つ目の方法で、elseの際のどの部分が期待通りの動作をしないのでしょうか?
mugen0905

2021/02/05 15:40

質問自体を編集し、コードを記載いたしました。 一つ目の方法のelseでは、アラートを消して、ページを更新し、次のID番号へ進むことを期待しています。 実際に質問に追記した、条件分岐を含まず、アラートを消すことだけを指示したコードでは、同じ次から次へとアラートを消して、ページを更新し、次のID番号へと進みます。 一つ目の方法のelseでは、ページが更新されずそこで止まってしまいます。 以上、宜しくお願い致します。
t_obara

2021/02/05 17:09

まず、2のケースで、if driver.switch_to.alert では、判定できません。必ずインスタンスは返却されるけれど、アラートがないので、例外が出ているのだと思います。 1のケースですが、どのタイミングで例外が出ていますか?Alertの行でしょうか。 また、1と2の間に入れたコード(無条件にAlertをacceptするもの)の場合、Alertが出なくても動作するのですか?
mugen0905

2021/02/06 11:33

1と2の間に入れたコードですが、Alert(driver).accept()でアラートを消しているのではなく、driver.refresh()でリロードすることでアラートを解消していたみたいです。 if文でなく、try文で試したところエラー解消しました。色々とご教示いただき有難うございました。
t_obara

2021/02/06 13:27

acceptとrefreshの間が短時間なので、アラートが消える前にrefreshしてしまう可能性がありますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問