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

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

ただいまの
回答率

87.50%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 398

score 1

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

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

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

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

NoId = 0000

#while文
while NoId <= 1000:

    # 検索ボックスに「ID番号」を入力して、Enterキーを押す
    driver.find_element(By.ID, "j_id0:KeiyakuNoId").send_keys(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


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

Message: unexpected alert open: {Alert text : 指定されたお客様の情報がございません。
検索条件をご確認のうえ、再度操作してください。(処理結果コード 1:正常完了 業務処理結果コード 2:対象契約なしエラー)}

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

NoId = 0000

while NoId <= 1000:

    # 検索ボックスに「ID番号」を入力して、Enterキーを押す
    driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys(str(NoId) + Keys.ENTER)

    # [検索]ボタンをクリック
    driver.find_element(By.ID, "search").click()

    # 1秒待つ
    time.sleep(1)

    # アラートを消す
    Alert(driver).accept()

    #ページを更新して戻る
    driver.refresh()

    NoId += 1

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

NoId = 0000

#while文
while NoId <= 1000:

    # 検索ボックスに「ID番号」を入力して、Enterキーを押す
    driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys(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


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

Message: no such alert
(Session info: chrome=87.0.4280.141)

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

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

宜しくお願い致します。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • t_obara

    2021/02/04 23:48

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

    キャンセル

  • mugen0905

    2021/02/05 00:20

    ご教示いただき有難うございます。
    わかりづらい質問で申し訳ございません。

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

    キャンセル

回答 2

checkベストアンサー

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/02/06 02:09

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

    キャンセル

  • 2021/02/06 20:33

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

    キャンセル

  • 2021/02/06 22:27

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

    キャンセル

0

NoId = 0000

#while文開始
while NoId <= 1000:

    #ボックスに「ID番号」を入力して、Enterキーを押す
    driver.find_element(By.ID, "j_id0:FORM:KeiyakuNoId").send_keys("x"+str(NoId) + Keys.ENTER)   

    try:
        driver.find_element(By.ID, "search").click()
        body = driver.find_element(By.ID, "keiyaku-itiran")
        links = driver.find_elements(By.TAG_NAME, "dd")

        #エクセル出力
        for (data, col) in zip(links[3:8], ["A","B","C","D","E"]):
            ws[col+str(row_num)].value = data.text

            wb.save("情報.xlsx")

        row_num += 1

        #ページを更新して戻る
        driver.refresh()

    except Exception as ex:

        time.sleep(1)

        #ページを更新して戻る
        driver.refresh()

    NoId += 1
#while文終了

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る