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

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

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

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

XPath(XML Path)

XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

Python

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

Q&A

解決済

2回答

2652閲覧

Python スクレイピング 取得項目の取得エラーと、ポップアップ発生時によるエラーの対応方法

NSugita

総合スコア6

スクレイピング

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

XPath(XML Path)

XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

Python

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

0グッド

1クリップ

投稿2019/11/17 03:28

Python初心者です。
いま、Pythonの学習用にサイトをスクレイピングしようとしているのですが、以下の事象で詰まってしまっています。
質問内容について、大変恐縮ですがご教示いただけますと幸いです。
よろしくお願いいたします。

事象:

  • xpathで取得設定した項目が、掲載元サイトに掲載がなかった場合、エラーで処理が止まってしまう。

  • 掲載元サイトで、ポップアップが突然表示されてしまった場合、後続の処理にいかずエラーで処理が止まってしまう。


質問内容:

  • xpathで取得設定した項目が、掲載元サイトに掲載がなかった場合、取得エラーのテキストをリストに返し、後続の処理に進む方法

  • 掲載元サイトで、ポップアップが突然表示されてしまった場合、以下の処理で、ポップアップを閉じたあと、後続の処理に進む方法。ポップアップは毎回出るものではありません。詳細ページでの表示はなく、一覧ページで表示されます。

※表示されたポップアップを閉じる方法は分かっています。
以下のコードで閉じることができます。

Python

1 elem_close_btn = browser.find_element_by_id('popover-link-x') 2 elem_close_btn.click()

コードの説明:

  • ブラウザ    :Chrome
  • 使用ライブラリ :selenium (beautifulsoupは使用していません)
  • 設定のページングURLにある一覧ページを起点にクロールをしていきます。
  • 詳細ページにもぐり、xpathで指定したスクレイピング箇所(5か所)を取得します。
  • 一覧ページでページングをして、さらに詳細ページをクロール
  • 一覧ページ1~10ページまで繰り返し...

  ※コード部分
index_page = 0
for pages in range(10,100):


Python

1from selenium import webdriver 2from time import sleep 3import pandas as pd 4browser = webdriver.Chrome('chromedriver.exe') 5 6#============================================================================================================================= 7# 設定 8#============================================================================================================================= 9 10## 起点URL 11#url = 'https://jp.indeed.com/%E6%B1%82%E4%BA%BA?q=%C2%A56%2C000%2C000%E3%80%80%E3%83%87%E3%83%BC%E3%82%BF&l=%E6%9D%B1%E4%BA%AC%E9%83%BD' 12 13## ページングURL 14page = 'https://jp.indeed.com/jobs?q=%C2%A56%2C000%2C000%E3%80%80%E3%83%87%E3%83%BC%E3%82%BF&l=%E6%9D%B1%E4%BA%AC%E9%83%BD&start={}' 15 16## スクレイピング箇所 17 18### タイトル 19results_01 =[] 20r01_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/h3' 21### 会社名 22results_02 =[] 23r02_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[1]/div/div/div[1]' 24### 勤務地 25results_03 =[] 26r03_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[1]/div/div/div[3]' 27### 年収 28results_04 =[] 29r04_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[2]/span[1]' 30### 詳細 31results_05 =[] 32r05_xpath = '//*[@id="jobDescriptionText"]' 33 34 35#============================================================================================================================= 36# クロール&スクレイピング 37#============================================================================================================================= 38 39index_page = 0 40for pages in range(10,100): 41 browser.get(page.format(index_page)) 42 43 44 45 ## 詳細ページのURLのクラスを指定 46 elem_detail_btn = browser.find_elements_by_class_name('title') 47 48 index_detail = 0 49 for elem_detail_btns in range(len(elem_detail_btn)): 50 elem_detail_btn[index_detail].click() 51 52 ## 詳細ページに移動 53 browser.switch_to.window(browser.window_handles[-1]) 54 55 ## スクレイピング 56 r01 = browser.find_element_by_xpath(r01_xpath).text 57 results_01.append(r01) 58 r02 = browser.find_element_by_xpath(r02_xpath).text 59 results_02.append(r02) 60 r03 = browser.find_element_by_xpath(r03_xpath).text 61 results_03.append(r03) 62 r04 = browser.find_element_by_xpath(r04_xpath).text 63 results_04.append(r04) 64 r05 = browser.find_element_by_xpath(r05_xpath).text 65 results_05.append(r05) 66 67 68 ## 一覧ページに移動 69 browser.switch_to.window(browser.window_handles[0]) 70 71 72 index_detail +=1 73 74 index_page +=10 75 76

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

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

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

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

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

guest

回答2

0

自己解決

解決しましたので、以下にコードを載せておきます。
課題に対する具体的な解決方法は以下です。

xpathで取得設定した項目が、掲載元サイトに掲載がなかった場合、取得エラーのテキストをリストに返し、後続の処理に進む方法

追加した処理は2点です。

・先にすべての取得項目を'Non'で定義します。
その後、値が正常に取得できた場合は、正しい値で上書きしリストに格納、取得できなかった場合は'Non'をリストに格納するという処理です。

・例外処理(try, except)のコードを追記しました。
try以降で取得項目を取得使しようと試みた際、エラーで取得ができなかった、例外が発生した場合、
except以降でエラー理由を表示してエラーをスルーします。
finally以降で例外が発生したしないにかかわらずリストに値を格納するという処理を行っています。

python

1 try: 2 r02 = 'Non' 3 r02 = browser.find_element_by_xpath(r02_xpath).text 4 except Exception as e: 5 print(e) 6 finally: 7 results_02.append(r02)

掲載元サイトで、ポップアップが突然表示されてしまった場合、

例外処理(try, except, finally)のコードを追記しました。
詳細ページのURLをクリックしたときに、ポップアップの例外が発生した場合は閉じるボタンをクリックした後に詳細ページのURLをもう一度クリックします。
さらに例外が発生するしないにかかわらず、詳細ページのウィンドウをアクティブにする処理をfinally以降で行いました。

python

1 try: 2 elem_detail_btn[index_detail].click() 3 except: 4 elem_close_btn = browser.find_element_by_id('popover-link-x') 5 elem_close_btn.click() 6 elem_detail_btn[index_detail].click() 7 finally: 8 ## 詳細ページに移動 9 browser.switch_to.window(browser.window_handles[-1])

以下、すべてのコードです。
同じところで躓いている方の参考になれば幸いです。

python

1 2from selenium import webdriver 3import pandas as pd 4browser = webdriver.Chrome('chromedriver.exe') 5 6#============================================================================================================================= 7# 設定 8#============================================================================================================================= 9 10## 起点URL 11#url = 'https://jp.indeed.com/%E6%B1%82%E4%BA%BA?q=%C2%A56%2C000%2C000%E3%80%80%E3%83%87%E3%83%BC%E3%82%BF&l=%E6%9D%B1%E4%BA%AC%E9%83%BD' 12 13## ページングURL 14page = 'https://jp.indeed.com/jobs?q=%C2%A56%2C000%2C000%E3%80%80%E3%83%87%E3%83%BC%E3%82%BF&l=%E6%9D%B1%E4%BA%AC%E9%83%BD&start={}' 15 16## スクレイピング箇所 17 18### URL 19results_01 =[] 20column_name_01 = 'URL' 21r01_xpath = '/html/body/table[2]/tbody/tr/td/table/tbody/tr/td[2]/div/div[1]/a' 22### タイトル 23results_02 =[] 24column_name_02 = 'title' 25r02_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/h3' 26### 会社名 27results_03 =[] 28column_name_03 = 'name' 29r03_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[1]/div/div/div[1]' 30### 勤務地 31results_04 =[] 32column_name_04 = 'place' 33r04_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[1]/div/div/div[3]' 34### 年収 35results_05 =[] 36column_name_05 = 'income' 37r05_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[2]/span[1]' 38### 雇用形態 39results_06 = [] 40column_name_06 = 'status' 41r06_xpath = '/html/body/div[1]/div[2]/div[3]/div/div/div[1]/div[1]/div[1]/div[2]/span[2]' 42### 詳細 43results_07 =[] 44column_name_07 = 'detail' 45r07_xpath = '//*[@id="jobDescriptionText"]' 46 47 48#============================================================================================================================= 49# クロール&スクレイピング 50#============================================================================================================================= 51 52index_page = 0 53for pages in range(2): 54 browser.get(page.format(index_page)) 55 56 57 ## 詳細ページのURLのクラスを指定 58 elem_detail_btn = browser.find_elements_by_class_name('title') 59 60 index_detail = 0 61 for elem_detail_btns in range(len(elem_detail_btn)): 62 63 try: 64 elem_detail_btn[index_detail].click() 65 except: 66 elem_close_btn = browser.find_element_by_id('popover-link-x') 67 elem_close_btn.click() 68 elem_detail_btn[index_detail].click() 69 finally: 70 ## 詳細ページに移動 71 browser.switch_to.window(browser.window_handles[-1]) 72 73 ## 5秒待機 74 browser.implicitly_wait(15) 75 76 ## スクレイピング _ 各項目取得 77 78 r01 = browser.current_url 79 results_01.append(r01) 80 try: 81 r02 = 'Non' 82 r02 = browser.find_element_by_xpath(r02_xpath).text 83 except Exception as e: 84 print(e) 85 finally: 86 results_02.append(r02) 87 try: 88 r03 = 'Non' 89 r03 = browser.find_element_by_xpath(r03_xpath).text 90 except Exception as e: 91 print(e) 92 finally: 93 results_03.append(r03) 94 try: 95 r04 = 'Non' 96 r04 = browser.find_element_by_xpath(r04_xpath).text 97 except Exception as e: 98 print(e) 99 finally: 100 results_04.append(r04) 101 try: 102 r05 = 'Non' 103 r05 = browser.find_element_by_xpath(r05_xpath).text 104 except Exception as e: 105 print(e) 106 finally: 107 results_05.append(r05) 108 try: 109 r06 = 'Non' 110 r06 = browser.find_element_by_xpath(r06_xpath).text 111 except Exception as e: 112 print(e) 113 finally: 114 results_06.append(r06) 115 try: 116 r07 = 'Non' 117 r07 = browser.find_element_by_xpath(r07_xpath).text 118 except Exception as e: 119 print(e) 120 finally: 121 results_07.append(r07) 122 123 ## インスタンスウインドウのみ閉じる 124 browser.close() 125 126 ## 一覧ページに移動 127 browser.switch_to.window(browser.window_handles[0]) 128 129 index_detail +=1 130 131 index_page +=10 132 133##ブラウザを閉じる 134browser.quit() 135 136#============================================================================================================================= 137# データ整形&出力 138#============================================================================================================================= 139 140## DateFrameを定義 141df = pd.DataFrame() 142df[column_name_01] = results_01 143df[column_name_02] = results_02 144df[column_name_03] = results_03 145df[column_name_04] = results_04 146df[column_name_05] = results_05 147df[column_name_06] = results_06 148df[column_name_07] = results_07 149df 150 151#CSVへ出力 152df.to_csv('results_indeed.csv',index=True) 153

投稿2019/11/22 12:08

NSugita

総合スコア6

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

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

0

xpathで取得設定した項目が、掲載元サイトに掲載がなかった場合、取得エラーのテキストをリストに返し、後続の処理に進む方法

browser.find_element_by_~~だと、要素がないときに例外が発生するので面倒です。
browser.find_elements_by_~~だと、要素がないときに[]が返るので、ifで要素がなかったことを判断できます。

掲載元サイトで、ポップアップが突然表示されてしまった場合、

ポップアップがあるかどうかを上述の方法で調べて、あれば閉じる。

投稿2019/11/17 08:45

otn

総合スコア84499

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

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

NSugita

2019/11/22 12:14

ご回答ありがとうございます。 結果自己解決となったのですが、こちらの回答も大変参考になりましたので、ベストアンサーにさせていただこうと思っていたのですが、サイトの勝手がわからず誤って自分の自己解決の回答をベストアンサーにしてしまいました。 申し訳ございません... ご回答ありがとうございました。
otn

2019/11/22 12:26

例外を受けとる方針で行く場合は、受けとる例外を具体的に列挙したほうがいいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問