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

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

ただいまの
回答率

87.61%

サイト内から特定データをWEBスクレイピングしたい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,009

score 17

前提・実現したいこと

dmm.ぱちタウンから全パチンコホールをWEBスクレイピングしたいと考えています。
昨日投稿しましたが、丸投げのような内容になったため出来る範囲内で修正をしました。
しかしながらエラーが発生し解決できておりません。
初心者のためご教授いただきく存じます。

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

・「NameError: name 'hall_info' is not defined」とエラーが発生しています。
・エラーが解消すれば問題なくスクレイピングできるか確認したい。

コード

import requests
import logging
from bs4 import BeautifulSoup

if __name__ == "__main__":

    # フォーマットを定義
    formatter = '%(asctime)s : %(levelname)s : %(message)s'
    # ログレベルを DEBUG に変更
    logging.basicConfig(format=formatter, filename='logger.log', level=logging.INFO)

    base_url = 'https://p-town.dmm.com'
    target_url = '/'
    r = requests.get(base_url + target_url)         #requestsを使って、webから取得
    soup = BeautifulSoup(r.text, 'lxml') #要素を抽出

    selector = 'body > div.o-layout > div > div.o-container > main > section.default-box.-shop > div > div li'
    # 都道府県ループ
    for elem1 in soup.select(selector):
        string_ = elem1.text
        target_url = elem1.next_element.attrs.get('href')
        area_name = target_url.rsplit('/', 1)[1]
        #print(area_name)
        logging.info('%s %s', 'test:', string_ + ':' + base_url + target_url)
        r = requests.get(base_url + target_url)
        soup= BeautifulSoup(r.text, 'lxml')
        selector = 'body > div.o-layout > div > div > main > section:nth-child(3) li'
        num = 0
        # 市区町村ループ
        for elem2 in soup.select(selector):
            target_url = elem2.next_element.attrs.get('href')
            city_id = target_url.rsplit('/', 1)[1]
            print(elem2.text + ':' + base_url + target_url)
            logging.info('%s %s', 'test:', elem2.text + ':' + base_url + target_url)
            r = requests.get(base_url + target_url)
            soup = BeautifulSoup(r.text, 'lxml')
            selector = 'body > div.o-layout > div > div.o-container > main > section li'
            nextpage = True
            while nextpage:
                # 次ページ有無チェック
                for elem3 in soup.select(selector):
                    if elem3.attrs.get('class')[0] == 'item':
                        if elem3.text == '>':
                            if elem3.next.attrs.get('href') is not None:
                                nextpage = True
                                break
                        else:
                            nextpage = False
                # 登録ホールループ
                for elem3 in soup.select(selector):
                    if elem3.attrs.get('class')[0] == 'unit':
                        # ホール情報収集
                        num += 1
                        target_url = elem3.next_element.attrs.get('href')
                        hall_id = target_url.rsplit('/', 1)[1]
                        r2 = requests.get(base_url + target_url)
                        soup2 = BeautifulSoup(r2.text, 'lxml')
                        # 店舗名取得
                        selector2 = 'body > div.o-layout > div > div.o-container > main > div:nth-child(1) > div > h1'
                        hall_name = soup2.select(selector2)[0].text
                        # 店舗基本情報取得
                        for tr in soup.select('table[class="default-table"] tr'):
                            name = tr.th.text
                            if name == '住所':
                                # 前後の空白文字を削除 strip=true
                                value = tr.p.get_text(strip=True)
                            elif name == '新台':
                                # 空白文字を削除 replace(置換する文字列, 置換される文字列)
                                items = [a.text.replace(' ', '') for a in tr.find_all('p')]
                                value = ''.join(items)
                            else:
                                value = tr.get_text(strip=True)
                                # 不要な文字削除 re.sub(正規表現, 置換する文字列, 置換される文字列)
                                value = re.sub('[\u3000\n]', '', value)    
                                hall_info = value                 
                        print(str(num) + '[' + hall_id + ']:' + hall_name + ':' + hall_info )
                        logging.info('%s %s', str(num) + '[' + hall_id + ']:' + hall_name + ':' + hall_info + ':', base_url + target_url)

                    # 次ページ読込、なければループ終了
                    elif elem3.attrs.get('class')[0] == 'item':
                        if elem3.text == '>':
                            #print(elem3.next.attrs.get('href'))
                            if elem3.next.attrs.get('href') is not None:
                                target_url = elem3.next.attrs.get('href')
                                r = requests.get(target_url)
                                soup = BeautifulSoup(r.text, 'lxml')
                            else:
                                nextpage = False
                            break

試したこと

Name errorのため該当箇所の名前を確認しましたが、特に問題ありませんでした。

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

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • 退会済みユーザー

    2019/04/10 15:07

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

checkベストアンサー

+1

hall_infoに代入されないままprintなりに到達するケースがあると提示エラー発生します。

# hall_info = '' # とりあえず定義しておけばエラーは出ない。
for i in range(2):
    print(i)
    if i % 2 == 0:
        pass
    else:
        hall_info = i

    print(hall_info) # NameError: name 'hall_info' is not defined

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/11 17:45

    hall_info = value に代入しているのですが、それでもエラーが出ているためどう修正すればよいでしょうか。可能であれば、該当箇所をどう修正すればいいかご教授いただけると助かります。

    キャンセル

  • 2019/04/11 19:25

    一般的にはprintなりの参照前に変数を定義すればよいです。
    回答コードで云えば、1行目のコメントアウトを外せばよいです。
    質問コードにおいて具体的にどこをどのように修正すべきかは、処理内容によるのでご自身で判断下さい。

    キャンセル

  • 2019/04/12 09:04

    上記の件、承知いたしました。こちらで判断し対応いたします。
    ご返信いただきありがとうございました。

    キャンセル

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

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

関連した質問

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