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

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

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

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

JupyterLab

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python

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

Q&A

解決済

2回答

684閲覧

URLを取得できなかったときはNoneと出力したい

loulou098

総合スコア15

スクレイピング

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

JupyterLab

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python

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

0グッド

0クリップ

投稿2023/05/15 21:51

実現したいこと

求人サイトから企業名、企業の住所、電話番号を取得するコードを作成しています

前提

その際、もし求人が掲載期間終了によりURLを取得できなかった場合、Noneと出力したいのですが、うまくいきません。

発生している問題・エラーメッセージ

--------------------------------------------------------------------------- HTTPError Traceback (most recent call last) Cell In[37], line 27 21 #job_info_url = cp_page.get('href') 22 23 24 25 #これで住所取得できた(あとは、複数のコードをfor文で回して取得すればOK) 26 page_r = requests.get(cp_page_url) ---> 27 page_r.raise_for_status() 28 page_soup = BeautifulSoup(page_r.content, 'lxml') 31 addresses = page_soup.select('div.bl_card2_table.bl_card2_table__wide th:-soup-contains("住所")') File ~/anaconda3/lib/python3.10/site-packages/requests/models.py:1021, in Response.raise_for_status(self) 1016 http_error_msg = ( 1017 f"{self.status_code} Server Error: {reason} for url: {self.url}" 1018 ) 1020 if http_error_msg: -> 1021 raise HTTPError(http_error_msg, response=self) HTTPError: 404 Client Error: Not Found for url: https://atsumaru.jp/area/detail?kno=X109214&said=7&shn=980&vol=00001

該当のソースコード

#HTMLを読み込む with open('company_list.html', 'r') as f: html = f.read() #HTMLを解析する soup = BeautifulSoup(html, 'lxml') #style="visibility:hidden"を除いた所以降のaタグの数を出力したい cp_pages = soup.select('div#jobLists div#jobList.jobList > div h2 a') print(len(cp_pages)) for cp_page in cp_pages: print(cp_page.text)#get cp_name #詳細ページにアクセス job_info_url = cp_page.get('href') if cp_pages else None cp_page_url = 'https://atsumaru.jp' + job_info_url#求人詳細ページのurl取得 #job_info_url = cp_page.get('href') page_r = requests.get(cp_page_url) page_r.raise_for_status() page_soup = BeautifulSoup(page_r.content, 'lxml') addresses = page_soup.select('div.bl_card2_table.bl_card2_table__wide th:-soup-contains("住所")') addresses = page_soup.select('tr:has(th:-soup-contains("住所")) td p:first-child') for address in addresses: print(address.text)

試したこと

・job_info_url = cp_page.get('href') if cp_pages else Noneをjob_info_url = cp_page.get('href') if cp_pages else print('None')とした:同じエラー

・job_info_url = cp_page.get('href') if cp_pages else Noneを

python

1if cp_pages: 2 cp_page.get('href') 3 4else: 5 print('None')

としたところ、同じエラー。

補足情報(FW/ツールのバージョンなど)

Pythonのバージョン:3.10.9

使用PC:Intel MacBook

バージョン:macOS Monterey Version 12.4

実装環境:Jupyter Lab

Chromeのバージョン:112.0.5615.137

ChromeDriverのバージョン:112.0.5615.49

selenium 4.9.0

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

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

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

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

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

guest

回答2

0

job_info_url = cp_page.get('href') if cp_pages else Noneであろうが、
job_info_url = cp_page.get('href') if cp_pages else print('None')であろうが、
if cp_pagesが偽であればjob_info_urlにはNoneが代入されるので、次の行の文字列との+で、
TypeError: can only concatenate str (not "NoneType") to strというエラーになります。

が、cp_pagessoup.select('div#jobLists div#jobList.jobList > div h2 a')の結果のリストの一要素なので、偽値であることはなく、上記は常に
job_info_url = cp_page.get('href')
と同じです。

もし求人が掲載期間終了によりURLを取得できなかった場合

という事ですが、「掲載期間終了」時にHTMLが具体的にどういう状態になっているのかを把握した上でそれへの対処を考える必要があります。

「期間終了後もaタグがあり、href属性にもURLが書いてあるが、そのURLがリンク切れ」という状態であれば、リンク切れかどうかはアクセスしてみないとわからないので、m8aFm77kKU9JuIDさんの回答のように、実際にアクセスしてみて例外を捕捉するしか無いです。

「実際にアクセスしてみなくても、期間終了かどうかはHTMLを見ただけで~~という違いがあるので、それで判断できる」という場合は、その違いをプログラムで調べれば良いです。

投稿2023/05/16 11:51

otn

総合スコア84553

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

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

0

ベストアンサー

対策としては、HTTPエラーを適切に捕捉し、その場合にはNoneを出力するようにコードを修正することが考えられます。具体的には、try-exceptブロックを使用してHTTPエラーを捕捉します。以下に修正案を示します。

python

1for cp_page in cp_pages: 2 print(cp_page.text) # get cp_name 3 4 # 詳細ページにアクセス 5 job_info_url = cp_page.get('href') if cp_pages else None 6 cp_page_url = 'https://atsumaru.jp' + job_info_url # 求人詳細ページのurl取得 7 8 try: 9 page_r = requests.get(cp_page_url) 10 page_r.raise_for_status() 11 page_soup = BeautifulSoup(page_r.content, 'lxml') 12 13 addresses = page_soup.select('div.bl_card2_table.bl_card2_table__wide th:-soup-contains("住所")') 14 addresses = page_soup.select('tr:has(th:-soup-contains("住所")) td p:first-child') 15 for address in addresses: 16 print(address.text) 17 except requests.exceptions.HTTPError as err: 18 print(f'HTTP error occurred: {err}') # Not Found, etc. 19 print('None')

この修正により、HTTPエラーが発生した場合にエラーメッセージを表示し、その後に'None'を出力します。これによりプログラムはエラーで停止せず、次の求人ページの処理を続けることができます。

投稿2023/05/15 22:32

m8aFm77kKU9JuID

総合スコア78

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

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

loulou098

2023/05/15 23:55

ご回答ありがとうございます!しっかりと出力されました!ちなみにですが、 except HTTPError as err: print(f'HTTP error occurred: {err}') # Not Found, etc. print('None') のように「requests.exceptions.」を用いない記述法もネット上で散見されます(https://www.google.com/url?client=internal-element-cse&cx=0903a1a109a46b6e5&q=https://www.sejuku.net/blog/23044&sa=U&ved=2ahUKEwj4-PGCwPj-AhWst1YBHXgJBWAQFnoECAYQAg&usg=AOvVaw0XHm1SViVvbu5JZSu76daq&arm=e)が、これで実行するとNameError: name 'HTTPError' is not definedのエラーが出ます。 これは今はexcept HTTPError as err:の書き方がPythonのバージョン変更か何かで、適用されなくなったということでしょうか?Python3系ではasキーワードが必須になったとの情報は見つかりましたが、それ以降の書き方の変更に関する記事が見当たらず、気になったので質問させていただきました。 何かご存じでしたら、ご教授いただけると幸いです。
m8aFm77kKU9JuID

2023/05/16 00:10

Pythonのエラーハンドリングに関する部分で、requests.exceptions.HTTPErrorとHTTPErrorの違いについて説明します。 requests.exceptions.HTTPErrorはrequestsライブラリで定義されているHTTPErrorクラスを指します。したがって、requests.exceptions.HTTPErrorを使用する場合は、requestsライブラリをインポートしている必要があります。 一方で、HTTPErrorだけの場合は、その名前空間が明示的には定義されていません。そのため、requests.exceptions.HTTPErrorの代わりにHTTPErrorを使用しようとすると、「HTTPErrorが定義されていない(NameError)」というエラーが発生します。 これを解決するには、最初にfrom requests.exceptions import HTTPErrorという形でHTTPErrorをインポートすることが必要です。その後は、HTTPErrorだけを使用してエラーをハンドリングできます。以下に示すように、コードを修正することができます。 from requests.exceptions import HTTPError # ... try: page_r = requests.get(cp_page_url) page_r.raise_for_status() page_soup = BeautifulSoup(page_r.content, 'lxml') addresses = page_soup.select('div.bl_card2_table.bl_card2_table__wide th:-soup-contains("住所")') addresses = page_soup.select('tr:has(th:-soup-contains("住所")) td p:first-child') for address in addresses: print(address.text) except HTTPError as err: print(f'HTTP error occurred: {err}') # Not Found, etc. print('None') したがって、この問題はPythonのバージョン変更によるものではなく、単にHTTPErrorクラスがどのライブラリからインポートされているかによる違いです。
loulou098

2023/05/16 21:12

そうだったのですね!ありがとうございます!
yeahtubby

2023/05/29 08:36

このテーマに関して非常に興味深い記事を書いていただき、ありがとうございます。 本当に考えさせられる内容だったので、もっと読みたいです。 [happy wheels](https://happy-wheels.co)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問