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

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

ただいまの
回答率

90.61%

  • Python

    7516questions

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

  • Python 3.x

    5926questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • スクレイピング

    309questions

Pythonのスクレイピング処理にて、"HTTPError: 503"の場合は動作停止、"HTTPError: 404"の時は動作続行、とHTTPErrorの処理を分けたい

解決済

回答 2

投稿

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

etherwind

score 4

 前提

Pythonにて、あるサイト上の検索結果をスクレイピングしています。
URLのパラメータの一部をテキストファイルから読み込んで、規則に沿って完成URLを生成し、順々にアクセスして結果を取得することができています。

 本題

安全の為に、"res.raise_for_status()"を組み込んでいるのですが、一部のパラメータで生成されたURLは、サイト内では存在しないページである為、そこにあたると"HTTPError: 404"となり、スクレイピング動作が停止してしまいます。

"res.raise_for_status()"を消せば404が発生しても、無視して次のURLへのアクセスをしてくれるのですが、これだともし"HTTPError: 503"が出てサイトへのアクセス自体を弾かれてもスクレイピング動作が停止しない為、このままではいけないなと思っています。

 実現したいこと

タイトルの通り、アクセスの結果が
・"HTTPError: 503"の場合は動作停止
・"HTTPError: 404"の時は動作続行
と、HTTPErrorの処理を分けたいです。

下記ソースコードに組み込みたいと思っています。

 該当のソースコード

import requests, bs4
import csv
import time
import random

def scrape(url, page_id_for_scrape, csv_writer):
    res = requests.get(url)
    res.raise_for_status()
    soup = bs4.BeautifulSoup(res.text, "html.parser")
    elems = soup.select ('CSSセレクタ')
    for elem in elems:
        print(elem.getText())
        csv_writer.writerow([page_id_for_scrape])
        csv_writer.writerows(elems)

    time.sleep(random.randrange(10, 20))

def main(f):
     writer = csv.writer(f)
     with open('IDリスト.txt') as f:
          page_id_list = [int(row) for row in f]
     for page_id in page_id_list:
          print(page_id)
          scrape(f'http://狙いのサイト={page_id}', page_id, writer)

if __name__ == '__main__':
    with open('保存.csv', 'w',  newline='', encoding='CP932', errors='ignore') as f:
        main(f)

 試したこと

どうすればいいのか見当もつかないのでググりまくったのですが、半日Googleに問い続けても手掛かりさえつかめませんでした。
そもそも自分の考えている動作が、仕様上できるのかどうかさえ疑っています。
できるのかできないのか、できないのであれば代案などあれば教えてほしいです。

 補足

ソースコード内の、CSSセレクタ、IDリスト、保存などの名称は質問用です。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

check解決した方法

+1

解決しました。
for i in ~ if res.status_code == 404: ~ continue
を組み込むことで、
404の場合は処理が継続され、
503の場合はres.raise_for_status()により処理が停止するという
とても都合の良いコードができました。

全てが自力ではありませんでしたが、これにて解決とさせていただきます。

import requests, bs4 
import csv 
import time
import random
import urllist

with open('保存.csv', 'w', encoding='CP932', errors='ignore') as f:
    print(urllist.url)
    for i in urllist.url:
        res = requests.get(i)
        print(i)
        time.sleep(random.randrange(10, 20))
        if res.status_code == 404:
            continue
        res.raise_for_status()
        soup = bs4.BeautifulSoup(res.text, "html.parser")
        elems = soup.select('CSSセレクタ')
        for elem in elems:
            print(elem)
            writer = csv.writer(f)
            writer.writerows(elems) 

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

http://docs.python-requests.org/en/master/user/quickstart/#response-status-codes

自分でステータスコードを見て、継続or中断を判断したらいいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/24 18:30

    ありがとうございます。やり方はあるようなので、希望が見えました。
    if文とresponseを組み合わせればなんとかなるかな、、、というのが今の自分の頭の中です。

    まずはシンプルに、
    エラーコード404ならOK、
    エラーコード503ならsorryとprintする、
    みたいなコードを組んでみようと思います。

    キャンセル

  • 2018/06/24 19:46

    続報です。
    try~exceptを利用して
    アクセス成功の時はAをプリント、HTTPerrorの時はBをプリント、
    といった簡単なコードは書けましたが、404の時はA、503の時はB、といった、エラーの種類で処理を分けるコードの書き方が未だわかりません。

    「http://docs.python-requests.org/en/master/user/quickstart/#response-status-codes」
    こちらもアクセスして目を通しましたが、
    404と503の結果で処理分ける方法に関する説明ではないと解釈できますが、私の読み間違えでしょうか。

    まだpython初心者ですので、記述例を含めた回答を希望します。

    キャンセル

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

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

関連した質問

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

  • Python

    7516questions

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

  • Python 3.x

    5926questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • スクレイピング

    309questions

  • トップ
  • Pythonに関する質問
  • Pythonのスクレイピング処理にて、"HTTPError: 503"の場合は動作停止、"HTTPError: 404"の時は動作続行、とHTTPErrorの処理を分けたい