東京都の高校の情報を入手する

前回,東京都の高等学校一覧から,各校のWikipediaの記事へのリンクを収集したので,各校の記事から情報を取得していきます。
analyst-in-rekisen.hatenablog.com

引き続きRのrvestパッケージと,dplyrパッケージを使います。
Wikipediaの学校の記事にはテンプレートがあり,国公私立の別,住所などはひとつのテーブルにまとまっているので簡単です。

1. 検索するためのXPathの用意

各校の記事から,国公私立の別,共学か別学か,課程(全日制・通信制…),住所,の情報を検索するためのXPathを準備しておきます。
XPathをRの文字型でもつので,XPaht内の引用符''のエスケープが必要です。また,文字コードも変換しておきます。
記事をいくつかみてみると,住所のところは2段組になっていて1段目が住所,2段目が経緯度のようなので,1段目だけとります。

###################
##XPathで検索するときのパス
###################
info_label <- c("国公私立の別", "共学・別学", "課程")
names(info_label) <- c("sector", "gender", "course")
path_list <- list(NULL)
for( i in 1:length(info_label)){
	path_list[[i]] <- (
		paste('//table[@class=\'infobox\']/tr/td[../th/text()=\''
			, info_label[i]
			, '\']'
			, sep=""
			)
		)
	names(path_list)[i] <- names(info_label)[i]
}
##住所情報のパスだけは別立て
path_list[[ length(path_list) + 1 ]] <- (
	'//node()[preceding-sibling::tr/th/text()=\'所在地\']/td/div[1]'
)
names(path_list)[length(path_list)] <- "address"
##文字コードを直す
for(i in 1:length(path_list)){
	path_list[[i]] <- (
		path_list[[i]] 
		%>% iconv(from = "", to = "UTF-8")
	)
}

できあがったのは以下のようなものです。

> path_list
$sector
[1] "//table[@class='infobox']/tr/td[../th/text()='国公私立の別']"

$gender
[1] "//table[@class='infobox']/tr/td[../th/text()='共学・別学']"

$course
[1] "//table[@class='infobox']/tr/td[../th/text()='課程']"

$address
[1] "//node()[preceding-sibling::tr/th/text()='所在地']/td/div[1]"

2. 各校の記事の情報を取得する。

前回取得した学校の一覧は,Rのmatrixで, school_info_unique にもっていて,text列に学校名,href列にリンク先が入っています。

#####################
##各校の記事を取得してリストにする。
#####################
school_kiji_list <- list(NULL)

for(i in 1:nrow(school_info_unique)){
	url_kiji <- paste("https://ja.wikipedia.org"
				,school_info_unique[i,"href"]
				, sep="")
	school_kiji_list[[i]] <- read_html(url_kiji)
}

##大きさの確認
length(school_kiji_list)
##名前をつけておく
names(school_kiji_list) <- school_info_unique[,"text"]

けっこう時間がかかったので,進行状況とか表示させたらよかったかもしれません。

3. 各校の記事から必要な情報を抜き出す

2で取得した各校の記事から,1で作成しておいたXPathを使って情報を抜き出します。情報が掲載されていない場合があるのと,2段に分かれていたりするとやっかいなので,ノードが1個のときだけ抜き出すようにしました。

####################
##各校の記事から情報を抜き出す
###################

##結果の入れ物を作る
each_school_info <- matrix(  ""
					, nrow= length(school_kiji_list)
					, ncol=(length(path_list)+1)
				)
colnames(each_school_info) <- c("name", names(path_list))
for( i in 1:length(school_kiji_list)){
	each_school_info[i,"name"] <- names(school_kiji_list)[i]
	for( infoname in names(path_list)){
		#特定の情報のノードを取得してテキストを取り出す
		#その情報が含まれていない(ノードが見つからない)場合,複数ある場合は""のまま
		node_tmp <-(school_kiji_list[[i]] %>% html_nodes(xpath=path_list[[infoname]]))
		each_school_info[i,infoname] <- (
			ifelse(length(node_tmp) == 1 
					,html_text( node_tmp )
					,""
				)
		)
	}
	#時間かかりそうだから終わったら表示する
	msg <- paste("Finish: ", i, " : ", names(school_kiji_list)[i], sep="") 
	print(msg)
	rm(msg)
}

4. いちおう確認する

まず,各列にどんな値が起きているか確認しておきます。
国公私立の別は…

unique(each_school_info[,"sector"])

結果はこちら

[1] "国立学校"
[2] "私立学校"
[3] "公立学校(区立)"
[4] ""
[5] "\n私立学校\n設置者=学校法人昭和女子大学"
[6] "公立学校"
[7] "公立学校(都立)"

これは,国立,公立,私立にコーディングしなおす必要がありそうです。また,設置者がとれていないところもあるので別途調査が必要です。

共学・別学のほうは…

unique(each_school_info[,"gender"])

結果はこちら

[1] "男女別学(女子校)"
[2] "女子校→男女共学→男女別学"
[3] "男女共学"
[4] "女子校"
[5] "男女別学(男子校)"
[6] "男女別学\n(男子校)"
[7] "男女共学\n健康・スポーツ進学コースに限り男子のみ"
[8] "女子校(全日制)男女共学(通信制)"
[9] "男女別学(女子校)"
[10] "男女別学"
[11] "男子校"
[12] "共学校"
[13] "共学部は男女共学\n女子部は男女別学"
[14] ""
[15] "高等学校は一部男女共学\n中学校は男女共学"
[16] "男女共学※中学校男女別学(女子校)※高校"
[17] "男女共学(男女ほぼ同数)"
[18] "女子校\n音楽科は男女共学"
[19] "男女別学定時制(男子校)\n通信制は男女共学"
[20] "男女共学(男女比1:1)"
[21] "男女別学(女子のみ)"
[22] "男女別学・男子校"

こちらもバリエーションがあります。全日制と定時制でちがうとか,学科で違うというのは何か方針を決めてコーディングしなおす必要がありそうです。また情報が取れていないところは別途確認です。

課程のところは…

unique(each_school_info[,"course"])

結果はこちら

[1] "全日制課程"
[2] ""
[3] "全日制課程\n通信制課程"
[4] "昼間定時制課程"
[5] "通信制課程"
[6] "全日制課程定時制課程通信制課程"
[7] "全日制"
[8] "定時制課程通信制課程"
[9] "定時制(3部制)課程"
[10] "全日制課程定時制課程"
[11] "全日制課程\n定時制課程"
[12] "全日制課程、定時制課程"
[13] "全日制課程(全18学級)\n定時制課程(全10学級)"
[14] "全日制課程(6学級)\n定時制課程(2学級)"
[15] "定時制課程"
[16] "全日制課程(全24学級)\n定時制課程(全7学級)"
[17] "通信制課程全日制課程(最終募集は2015年3月)"
[18] "昼間定時制課程\n通信制通学課程\n通信制技能連携課程"
[19] "全日制課程(平日コース)通信制課程(土曜コース)"
[20] "全日制課程、通信制

これも,共学・別学と同様にコーディング方針を考える必要があります。

最後に,住所のところに東京以外のものがあるようなので確認します。
grepでname列に"東京都"を含む行を検索して,それにマイナスをつけて反転します。

each_school_info[
	 -grep(pattern="東京都", x=each_school_info[,"address"])
	,]

該当するのは,以下の12件でした。

name sector gender course address
[1,] "ウィッツ青山学園高等学校" "私立学校" "男女共学" "全日制課程\n通信制課程" "三重県伊賀市北山1373番地"
[2,] "クラーク記念国際高等学校" "私立学校" "男女共学" "全日制課程\n通信制課程" "北海道深川市納内町三丁目2番40号\n(北海道本校)"
[3,] "八洲学園高等学校" "私立学校" "男女共学" "通信制課程" "大阪府堺市西区鳳中町7丁225-3北緯34度32分13.2秒東経135度27分22秒"
[4,] "大智学園高等学校" "私立学校" "男女共学" "通信制課程" "福島県双葉郡川内村大字上川内字町分143"
[5,] "学芸館高等学校" "私立学校" "男女共学" "通信制課程" "群馬県高崎市高松町14番2"
[6,] "屋久島おおぞら高等学校" "私立学校" "男女共学" "通信制課程" "鹿児島県熊毛郡屋久島町平内34-2"
[7,] "文教大学付属高等学校" "" "" "" ""
[8,] "日本ウェルネス高等学校" "私立学校" "男女共学" "通信制課程" "愛媛県今治市大三島口総4010番地"
[9,] "星槎国際高等学校" "私立学校" "男女共学" "通信制課程" "北海道芦別市緑泉町5-12"
[10,] "青森山田高等学校" "私立学校" "男女共学" "全日制課程、通信制課程" "青森県青森市青葉三丁目13番40号北緯40度48分14.0秒東経140度44分57.5秒"
[11,] "飛鳥未来高等学校" "私立学校" "男女共学" "通信制課程" "奈良県天理市櫟本町1514-3"
[12,] "鹿島学園高等学校" "私立学校" "男女共学" "全日制課程\n通信制課程" "茨城県鹿嶋市田野辺141-9

これをみるに,通信制などの東京校等が一覧に出ていて,リンク先が本校の記事になっているようです。ちょっと考える必要がありそうです。また,経緯度は外したはずだったのが,くっついているのもあるので,これはうまく削る必要があります。

ということで,次回はコーディングの統一や抜けている情報の収集といった泥くさい作業が中心になりそうです。