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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Python 3.x

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

selenium

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

Q&A

解決済

1回答

7471閲覧

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

taichin3264

総合スコア9

Python 3.x

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

selenium

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

0グッド

0クリップ

投稿2018/07/18 15:53

編集2018/07/19 05:51

前提・実現したいこと

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

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

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

   日付, 時間, レッスン, インストラクター 予約フラグ
1 7/21(土), 10:0010: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を使いました。
(その判断があっているのかわかりません。)
実現したいもののうち、日付と予約フラグを除いて配列化できました。

該当のソースコード

Python

1from selenium import webdriver 2from selenium.webdriver.support import expected_conditions as EC 3from selenium.webdriver.support.ui import Select 4from bs4 import BeautifulSoup 5import pandas as pd 6 7driver = webdriver.Chrome('C:\driver\chromedriver.exe') 8 9driver.get("https://www.feelcycle.com/feelcycle_reserve/reserve.php")#店舗ページを開く 10driver.find_element_by_xpath('//*[@id="schedule"]/form/div/li[1]/a/img').click()#六本木を選択 11 12 13r = driver.page_source.encode('utf-8') 14html = BeautifulSoup(r, 'lxml') 15elems = html.find_all('div', class_=['unit','unit_past','unit_reserved']) 16 17lesson_data = []#空のリストを作成 18 19for elem in elems: 20 text=elem.get_text() 21 text = text.split('\n')#改行(\n)で分割する 22 lesson_data.append(text)#分割したデータをリストに挿入 23 24df = pd.DataFrame(lesson_data) 25print(df) 26

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

が、以下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

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

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

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

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

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

y_waiwai

2018/07/18 23:32

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

2018/07/19 01:15 編集

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

回答1

0

ベストアンサー

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

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

python

1import re 2import requests 3import pandas as pd 4from bs4 import BeautifulSoup 5 6# HTMLを取得 7r = requests.get('https://www.feelcycle.com/feelcycle_reserve/reserve.php') 8r.encoding = r.apparent_encoding 9 10# 店舗IDスクレイピング 11soup = BeautifulSoup(r.text) 12shops = soup.find_all('li', class_='tenpo_bann') 13pattern = r'([0-9]*)' 14 15shop_ids = [] 16for shop in shops: 17 try: 18 shop_id = shop.a.get('onclick') 19 shop_id = re.findall(pattern, shop_id) 20 shop_id = [i for i in shop_id if i != ''] 21 shop_name = shop.find('img').get('alt') 22 print(shop_name + ":" + shop_id[0]) 23 except: 24 pass 25 26# ユーザーのショップID入力 27# example: 11 28shop_id = input() 29 30# ユーザーの日付入力 31# example: 2018/07/22 32setdate = input() 33 34# リクエストデータ 35payloads = { 36 'tenpo': shop_id, 37 'setdate': setdate 38} 39 40# 店舗IDでHTMLをリクエスト 41r = requests.post('https://www.feelcycle.com/feelcycle_reserve/reserve.php', data=payloads) 42r.encoding = r.apparent_encoding 43 44# スクレイピング 45soup = BeautifulSoup(r.text) 46days = soup.find_all('div', id=re.compile("^day_")) 47 48data = [] 49for day in days: 50 date = day.find('div', id=re.compile("^title_week")).text 51 times = day.find_all('div', class_=re.compile("^unit")) 52 for time in times: 53 if time.get('class')[0] == 'unit_blanc': 54 continue 55 56 print(time) 57 start = time.find('p', class_='start').text 58 lesson = time.find_all('p')[1].text 59 instructor = time.find('p', class_='time').text 60 is_reserved = 1 if time.get('class')[0] == 'unit_reserved' > 0 else 0 61 62 data.append([date, start, lesson, instructor, is_reserved]) 63 64df = pd.DataFrame(data) 65print(df)

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

投稿2018/07/24 10:13

0hag1

総合スコア100

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

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

taichin3264

2018/07/25 07:50

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問