Webスクレイピング勉強④~ランキングサイト掲載情報の自動取得~
引き続きWEBスクレイピングの勉強
目的
下記ランキングサイトから
・情報を取得して
・一覧化&ファイル出力
1.構造確認
①全体
ランキング全体の作りとして、divタグのclass="u_areaListRankingBox"に1つの観光地が定義されている。
②観光地名
divタグの「class=u_title」で定義されているぽい。
③総合評価
divタグの「class=u_rankBox」で定義されているぽい。
④カテゴリ評価
divタグの「class=u_categoryTipsItem」で定義されているぽい。
2.1つ目の観光地情報を取得
構造を確認出来たら情報を取得する。まずは1つ目だけ取得できることを確認する。
(1)HTML取得
requestsとbeautifulsoupをインストールしてURLからHTML取得
import requests #requestsインポート
from bs4 import BeautifulSoup #beautifulsoupインポート
url = 'https://scraping-for-beginner.herokuapp.com/ranking/' #url指定
res = requests.get(url) #urlのHTML取得
soup = BeautifulSoup(res.text,'html.parser') #取得自他情報をHTMLタグとして格納
(2)観光地情報取得
①ランキング1位の情報全体を取得
divタグの「class=u_areaListRankingBox」の情報を取得
#観光地名
spots = soup.find_all('div', attrs={'class':'u_areaListRankingBox'}) #ランキング全体を取得
これでランキング全体が取得できたため、この1つ目の要素をとれば1位の情報のみを取得できる。
spot = spots[0] #1つ目の情報を取得
確認すると、確かに1つめの観光地情報がとれてる
以降は、この中から必要な情報を抽出していく。
(3)観光地名取得
観光地名は、spotの中のdivタグ&class = u_title
spot_name = spot.find('div', attrs={'class':'u_title'}) #divタブのu_titleクラスのみ取得
確認すると指定したクラスの値で観光地名が取得できている。
ただこれだと不要な値(頭の1)がついているので、spanタグを除外する。(spanタグのclass=badge)
spot_name.find('span', attrs={'class': 'badge'}).extract() #不要な情報を除外
再度確認すると、確かに除外された
spot_nameのtextを確認すると改行コードがついている
こちらはreplace関数で変換
spot_name = spot_name.text.replace('\n','') #不要な文字を置換
綺麗になった。
(4)総評価取得
総評価も同様に取得する。
spot_evalu = spot.find('div', attrs={'class':'u_rankBox'})
こちらも同様に不要な文字を置換し、かつ少数なので型をfloatに変換
spot_evalu = float(spot_evalu.text.replace('\n',''))
総評価も取得完了!
(5) 各カテゴリ評価取得
カテゴリ評価も取得。
category_Items = spot.find('div', attrs={'class':'u_categoryTipsItem'}) #カテゴリ評価の一覧表を取得
中身を確認
その中からさらにdlタグを抽出する
category_Items = category_Items.find_all('dl')
各カテゴリと点数をリスト化できたため、それぞれ抽出していく
category_Item = category_Items[0] #1つ目の要素を取得
category = category_Item.dt.text #dtタグのテキストを取得(楽しさ)
rank = category_Item.span.text #spanタグのテキストを取得(4.6)
それぞれ取得できた
これをリストに格納する。
details = {} #リスト定義
details[category] = rank #カテゴリと点数をセットで格納する
同じ要領でfor文で全てのカテゴリと点数を格納する
details = {} #リスト定義
for category_Item in category_Items: #category_Itemsの値をcategory_Itemに格納
category = category_Item.dt.text #dtタグのテキストを取得(カテゴリ)
rank = category_Item.span.text #spanタグのテキストを取得(点数)
details[category] = rank
全カテゴリと点数の組み合わせを格納完了
(6)その他の情報も追加
同様に、事前に取得した観光地名と総評価もリストに追加する。
datum = details #全体のデータを入れるリストをdatumとする
datum['観光地名'] = spot_name.replace('\n','') #観光地名を入れる
datum['評点'] = spot_evalu #評価を入れる
ここまでで、すべての観光地情報がリスト化された。
3.全観光地情報を取得(リスト全体)
まずは先ほどまでの情報を整理
以下のコードで全体のうち、1つ目の観光地情報が取得可能。
import requests #requestsインポート
from bs4 import BeautifulSoup #beautifulsoupインポート
#(1)HTML取得
url = 'https://scraping-for-beginner.herokuapp.com/ranking/' #url指定
res = requests.get(url) #urlのHTML取得
soup = BeautifulSoup(res.text,'html.parser') #取得自他情報をHTMLタグとして格納
#(2)観光地情報取得
spots = soup.find_all('div', attrs={'class':'u_areaListRankingBox'}) #ランキング全体を取得
spot = spots[0] #1つ目の要素のみ取り出す
#(3)観光地名取得
spot_name = spot.find('div', attrs={'class':'u_title'}) #divタブのu_titleクラスのみ取得
spot_name.find('span', attrs={'class': 'badge'}).extract() #不要な情報を除外
spot_name.text
spot_name = spot_name.text.replace('\n','') #不要な文字を置換
#(4)総評価取得
spot_evalu = spot.find('div', attrs={'class':'u_rankBox'})
spot_evalu = float(spot_evalu.text.replace('\n',''))
#(5) 各カテゴリ評価取得
category_Items = spot.find('div', attrs={'class':'u_categoryTipsItem'})
category_Items = category_Items.find_all('dl')
details = {} #リスト定義
for category_Item in category_Items: #category_Itemsの値をcategory_Itemに格納
category = category_Item.dt.text #dtタグのテキストを取得(カテゴリ)
rank = category_Item.span.text #spanタグのテキストを取得(点数)
details[category] = rank
#(6)その他の情報も追加
datum = details #全体のデータを入れるリストをdatumとする
datum['観光地名'] = spot_name.replace('\n','') #観光地名を入れる
datum['評点'] = spot_evalu #評価を入れる
以下★の行を変更して、全体を取得するように書き換え
import requests #requestsインポート
from bs4 import BeautifulSoup #beautifulsoupインポート
data = [] #★
#(1)HTML取得
url = 'https://scraping-for-beginner.herokuapp.com/ranking/' #url指定
res = requests.get(url) #urlのHTML取得
soup = BeautifulSoup(res.text,'html.parser') #取得自他情報をHTMLタグとして格納
#(2)観光地情報取得
spots = soup.find_all('div', attrs={'class':'u_areaListRankingBox'}) #ランキング全体を取得
#spot = spots[0] #1つ目の要素のみ取り出す
for spot in spots: #★
#(3)観光地名取得
spot_name = spot.find('div', attrs={'class':'u_title'}) #divタブのu_titleクラスのみ取得
spot_name.find('span', attrs={'class': 'badge'}).extract() #不要な情報を除外
spot_name.text
spot_name = spot_name.text.replace('\n','') #不要な文字を置換
#(4)総評価取得
spot_evalu = spot.find('div', attrs={'class':'u_rankBox'})
spot_evalu = float(spot_evalu.text.replace('\n',''))
#(5) 各カテゴリ評価取得
category_Items = spot.find('div', attrs={'class':'u_categoryTipsItem'})
category_Items = category_Items.find_all('dl')
details = {} #リスト定義
for category_Item in category_Items: #category_Itemsの値をcategory_Itemに格納
category = category_Item.dt.text #dtタグのテキストを取得(カテゴリ)
rank = category_Item.span.text #spanタグのテキストを取得(点数)
details[category] = rank
#(6)その他の情報も追加
datum = details #全体のデータを入れるリストをdatumとする
datum['観光地名'] = spot_name.replace('\n','') #観光地名を入れる
datum['評点'] = spot_evalu #評価を入れる
data.append(datum) #★
dataリストに全観光地情報が格納された
4.表形式に変換&ファイル出力
pandasをインポートして、dataframeに読み込む
import pandas as pd
df = pd.DataFrame(data)
入れた結果が以下
表のカラムは以下で取得可能
df.columns
以下の書き方でカラムの並び替えが可能
df = df[['観光地名', '評点', 'アクセス', '楽しさ', '人混みの多さ', '景色']]
確認すると並び替えできている
df.to_csv('観光地.csv', index=False)
データ取得完了。
以上!
この記事が気に入ったらサポートをしてみませんか?