Haru57636433
@Haru57636433 (haru .)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

pythonでのスクレイピングで、time.sleepを入れるべき場所

解決したいこと

pythonでのスクレイピングで、time.sleepを入れるべき場所をご確認させて頂きたいです。
基本的にはサイトに対してリクエストするときに入れればよいかと思いますが、
例えば

一覧ページ → 詳細ページのURL取得

といった時にも入れる必要があるのかが分かりません。

該当するソースコード①

       if test_mode:
            list_url = base_url + str(page_num)
            self.scrape_list(list_url, mode=test_mode)
        else:
            while True:
                list_url = base_url + str(page_num)
                if self.scrape_list(list_url, mode=test_mode) != True:
                    break

                # INパラメータまでのページ数データを取得する
                if page_num >= end_page:
                    break
                page_num += 1
        return

まずこちらは一覧ページの何ページ目までスクレイピングするかを決めている状態で
現在何ページ目か、まだ継続するかの確認処理です。
ここは特にページ数を取ってくるだけで、処理が一巡するまでは1秒以上時間がかかるはずなので、
入れる必要はないかと考えました。

該当するソースコード②

    def scrape_list(self, list_url, mode):
        """
        一覧ページのパーシング
        """
        r = requests.get(list_url)
        if r.status_code != requests.codes.ok:
            return False

        soup = BeautifulSoup(r.content, 'html.parser')
        soup_a_list = soup.find_all('a', class_='list-rst__rst-name-target') # 名前一覧

        if len(soup_a_list) == 0:
            return False

        if mode:
            for soup_a in soup_a_list[:2]:
                item_url = soup_a.get('href') # 個別ページURLを取得
                self.store_id_num += 1
                self.scrape_item(item_url, mode)
                time.sleep(2)
        else:
            for soup_a in soup_a_list:
                item_url = soup_a.get('href') # 個別ページURLを取得
                self.store_id_num += 1
                self.scrape_item(item_url, mode)
                time.sleep(2)

        return True

こちらでは、一覧から各詳細ページのURLを取得しに行っています。
soup_a.get('href')
この箇所でリクエストを飛ばしているので、
for文の最終行に
time.sleep(2)
を入れています。
(本当は1秒でいいと思うのですが恐る恐るで念のため2秒にしています

該当するソースコード③

ここでは一覧ページ → 詳細ページのURLをリクエストして
HTMLパースを行っているので、ここでは

r = requests.get(item_url)

の前にsleepを入れています

そして、これは要らないかなと考えているのですが、
HTMLパース後にsoup.findで実際に情報を収集しているのですが、
パースが住んでいる時点でリクエストを改めて投げることは無いので
入れる必要はないでしょうか?

    time.sleep(2)
    store_name_tag = soup.find('h2', class_='display-name')
    store_name = store_name_tag.span.string

以下の中のこの部分です。


    def scrape_item(self, item_url, mode):
        """
        個別情報ページのパーシング
        """
        start = time.time()
        time.sleep(2)

        r = requests.get(item_url)
        if r.status_code != requests.codes.ok:
            print(f'error:not found{ item_url }')
            return

        soup = BeautifulSoup(r.content, 'html.parser')

        time.sleep(2)
        store_name_tag = soup.find('h2', class_='display-name')
        store_name = store_name_tag.span.string
        print('{}→個別ページの名前:{}'.format(self.store_id_num, store_name.strip()), end='')
        self.store_name = store_name.strip()

        try:
          elems = soup.find_all('table', class_='c-table c-table--form rstinfo-table__table')
          trs = elems[0].find_all('tr')
          tds = trs[1].td
          genre = tds.span.string
          print('{}→種類:{}'.format(self.store_id_num, genre.strip()), end='')
          self.genre = genre.strip()
        except AttributeError:
          genre = "無し"
        except IndexError:
          opening = "無し"

        # データフレームの生成
        self.make_df()
        return

宜しくお願い致します。

2

2Answer

そもそもスクレイピングを許可されているのかといった議論はあるかと思いますが、そこはクリアしているとして、sleepを入れる目的は、相手サーバーに負荷をかけないためなので、サーバーにアクセスする頻度を下げるのが目的になります。
したがってrequests.getが確実に連続で出ないようになっていればいいのではないでしょうか。どこに入れるかは自由と思います。

0Like

sleeprequest.getの間に適切な時間を空ける目的で入れればいいかと。
soupですが、これはrequestでとってきた情報(status code、本文などなど)を分析しているだけで、改めてwebサイトにアクセスしているわけではないので、sleepは考えなくていいと思います。

0Like

Your answer might help someone💌