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

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

ただいまの
回答率

90.52%

  • Python 3.x

    6350questions

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

  • selenium

    503questions

    Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

pythonでスクレイピングし、配列化したい

解決済

回答 1

投稿 編集

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

taichin3264

score 1

 前提・実現したいこと

pythonでスクレイピングを行いたい

具体的には、[このページ]の任意の店舗をクリックした先にある表を
日別で、予約ボックス内の時間・レッスン・インストラクターのテキストを配列化したい
(ゆくゆくはDB化したい)

出来上がりのイメージは以下の通り(六本木をクリックした前提)

日付,          時間,              レッスン,       インストラクター 予約フラグ
1 7/21(土), 10:00~10:45, BSW Regg 1, Rui,                   1 
2 7/21(土), 11:00~11:45, BB1 Hit 11,   Rui,                   1 
3 7/21(土), 12:00~12:45, BB2 MJ 1,     Hiroto,               0
...  

予約フラグについては、予約のオブジェクトのclass属性値が'unit_reserved'の場合に1としたい

 試したこと

seleniumでブラウザを操作し、Beautifulsoupでテキストを取得
当初seleniumのみでテキストの抽出を行うと思いましたが、前述のclass値に応じたフラグ判定を行いたいと思い、beautifulsoupを使いました。
(その判断があっているのかわかりません。)
実現したいもののうち、日付と予約フラグを除いて配列化できました。

 該当のソースコード

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from bs4 import BeautifulSoup
import pandas as pd

driver = webdriver.Chrome('C:\\driver\\chromedriver.exe')

driver.get("https://www.feelcycle.com/feelcycle_reserve/reserve.php")#店舗ページを開く
driver.find_element_by_xpath('//*[@id="schedule"]/form/div/li[1]/a/img').click()#六本木を選択


r = driver.page_source.encode('utf-8')
html = BeautifulSoup(r, 'lxml')
elems = html.find_all('div', class_=['unit','unit_past','unit_reserved'])

lesson_data = []#空のリストを作成

for elem in elems:
    text=elem.get_text()
    text = text.split('\n')#改行(\n)で分割する
    lesson_data.append(text)#分割したデータをリストに挿入

df = pd.DataFrame(lesson_data)
print(df)

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

が、以下2点をどう実現したらいいかわからず、手詰まり状態です。

・日付の取得
一つ上の階層(?)のdivタグにある日付を各レコードに持たせたい(HTMLの知識が非常に乏しく表現できずすみません。)

・予約フラグの判定
class属性値がunit_reservedの場合1 としたい
予約オブジェクトのclass属性値を確認すると、
unit(選択可能枠),unit_past(選択不可枠),unit_reserved(予約済枠)の3つがあることが確認できました。
しかしながら、各エレメントのclass値の判定や、取得について、classを指定した抽出に関する記事は出てくるのですが、
各エレメントのclassを判定するなどの方法が出てこず手詰まり状態です。

何卒よろしくお願い致します。

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

・python 3.6.5
・beautifulsoup 4.6.0
・selenium 3.13.0

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • y_waiwai

    2018/07/19 08:32

    スクレイピング自体はできているんでしょうか。どこまでできていて、現状どういう結果が得られて、なにがどうできないのか説明してくだされ

    キャンセル

  • taichin3264

    2018/07/19 10:12 編集

    y_waiwaiさん ご質問ありがとうございます。 スクレイピングそのものはできており、 実現したいことに記載した表のうち、日付とフラグを除いたものは上記のコードで実現できております。 それぞれの行に、日付とフラグを持たせる方法が見いだせず苦慮しております・・・。

    キャンセル

回答 1

checkベストアンサー

+1

requests と beautifulSoupをオススメします。学習コストは高めです。
その代わりマスターすれば大抵のページはスクレイピングできるようになります。

質問者様の実現したいサンプルコードです。

import re
import requests
import pandas as pd
from bs4 import BeautifulSoup

# HTMLを取得
r = requests.get('https://www.feelcycle.com/feelcycle_reserve/reserve.php')
r.encoding = r.apparent_encoding

# 店舗IDスクレイピング
soup = BeautifulSoup(r.text)
shops = soup.find_all('li', class_='tenpo_bann')
pattern = r'([0-9]*)'

shop_ids = []
for shop in shops:
    try:
        shop_id = shop.a.get('onclick')
        shop_id = re.findall(pattern, shop_id)
        shop_id = [i for i in shop_id if i != '']
        shop_name = shop.find('img').get('alt')
        print(shop_name + ":" + shop_id[0])
    except:
        pass

# ユーザーのショップID入力
# example: 11
shop_id = input()

# ユーザーの日付入力
# example: 2018/07/22
setdate = input()

# リクエストデータ
payloads = {
    'tenpo': shop_id,
    'setdate': setdate
}

# 店舗IDでHTMLをリクエスト
r = requests.post('https://www.feelcycle.com/feelcycle_reserve/reserve.php', data=payloads)
r.encoding = r.apparent_encoding

# スクレイピング
soup = BeautifulSoup(r.text)
days = soup.find_all('div', id=re.compile("^day_"))

data = []
for day in days:
    date = day.find('div', id=re.compile("^title_week")).text
    times = day.find_all('div', class_=re.compile("^unit"))
    for time in times:
        if time.get('class')[0] == 'unit_blanc':
            continue

        print(time)
        start = time.find('p', class_='start').text
        lesson = time.find_all('p')[1].text
        instructor = time.find('p', class_='time').text
        is_reserved = 1 if time.get('class')[0] == 'unit_reserved' > 0 else 0

        data.append([date, start, lesson, instructor, is_reserved])

df = pd.DataFrame(data)
print(df)

お店IDと日付を入力すると該当するお店の1週間分のデータが取得できます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/25 16:50

    コードを回したところ、まさにほしい情報が抽出されておりました。
    requestも当初見たのですが、httpやjsの知識が全くないため、ほぼ内容を理解できず、あきらめてseleniumのパワープレイに走った次第でした。
    いろいろとお伺いしたいことはたくさんありますが、まずはコードの中身をよく理解して自らに落とし込んでいこうと思います。
    大変ご丁寧なご対応ありがとうございます!

    キャンセル

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

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

関連した質問

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

  • Python 3.x

    6350questions

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

  • selenium

    503questions

    Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。