はじめに
続編:
注意書き:
※ 本ページ記載内容には、Suumoに対するスクレイピング処理が含まれます。商用利用は禁止されておりますので、個人利用の範囲で参考にしていただければと思います。
背景
- 最近引越し予定で家探しをすることになったものの、お気に入り物件をざっと眺められる場所が欲しい
- スプレッドシートにまとめていきたい
- 物件探しはSuumoでやっていく予定
課題
課題①: 必要な情報すべてを手で入力すると、めんどくさい
- URLだけ貼っていても、いちいち覗きにいかなければいけないため、だるい
- かといって、URLに加えて、家賃・築年数・面積... などなどをSuumoから手で転記するのは、もっとだるい
課題②: 通勤時間は、毎回Google Mapで検索しないと不明であり、めんどくさい
- 「通勤にどれくらい移動時間がかかるか?」は、家探しで結構重要なパラメータ
- しかし、物件情報として取得できるのは以下であり、家⇔オフィスの合計通勤時間は物件情報から取得不可能
- 物件から最寄り駅までの移動時間 (←しかも、ガバガバで信用ならない!!!)
- 最寄り駅からオフィス最寄り駅までの電車移動時間
- 重要な情報であるにもかかわらず、毎回Google Mapで検索するのは、めちゃくちゃだるい
目的
Suumo URLを入力すると、物件を比較するために必要な家賃・通勤時間などの情報を、自動で取得・計算するスプレッドシートを作ろう!
進め方
Quick and Dirty!
ちゃんと考えるのはだるいので、とっとと動くものを作る。課題に対しては適宜アップデートをかけてつぶしていく。
実装
実装のイメージ
- 入力する値はSuumoのURLのみ
- Suumoの機能のお気に入り登録をしたSuumo URLをいれる前提
- Suumo URLを使って、以下の値をスクレイピングする
- 物件名
- 家賃 (管理費・共益費込)
- 築年数
- 最寄り駅と最寄り駅からのアクセス
- 住所
- ②で取得した住所とオフィス住所を利用し、Google Maps APIで通勤時間を計算する
使い方イメージ
A1にSuumoのURLが入っているとしたら、以下をスプレッドシートのセルに書けば、家賃が取得できる、といったイメージ
=getRent(A1)
通勤時間に関しては、以下の計算式で計算するイメージ
=getCommuteTime(<物件住所>, <オフィス住所>)
※後ほど、この実装はまずかったことが判明。改善すべきポイントになります。
実装
スプレッドシート > 拡張機能 > App Script でエディタを開き、以下を実装。
function getCommuteTime(src, dest) {
const target_date = '2024/YY/MM HH:mm:ss' // 想定する通勤日時で到着したい時刻を入力
const datetime = new Date(target_date);
const arrival = new Date(datetime.getTime());
let finder = Maps.newDirectionFinder()
.setOrigin(src)
.setDestination(dest)
.setLanguage("ja")
.setArrive(arrival)
.setMode(Maps.DirectionFinder.Mode.TRANSIT); // 公共交通機関
let route = finder.getDirections().routes[0];
let value = route.legs[0].duration.value/60; //minutes
return value;
}
function checkError(return_value){
let exceptional_strings = '<'
if (return_value.includes(exceptional_strings)){
return_value = 'WARNING: 掲載終了の可能性、URLを参照してください。'
}
return return_value
}
function getSuumoInfo(url, start, end) {
let response = UrlFetchApp.fetch(url);
let content = response.getContentText("utf-8");
let info = Parser.data(content).from(start).to(end).iterate();
return info
}
function getName(url) {
const start = '<h1 class="section_h1-header-title">';
const end = '</h1>';
let info = getSuumoInfo(url, start, end);
let name_tmp = info.pop().trim();
if (name_tmp.includes('-')){
name = name_tmp.slice(0, name_tmp.indexOf("-"))
}else{
name = name_tmp
}
name = checkError(name)
return name
}
function getAge(url) {
const start = '<div class="property_data-body">';
const end = '</div>';
let info = getSuumoInfo(url, start, end);
let age = info[8].trim();
return age
}
function getArea(url) {
const start = '<div class="property_data-body">';
const end = '</div>';
let info = getSuumoInfo(url, start, end);
let area_tmp = info[5].trim();
let area = Number(area_tmp.slice(0, area_tmp.indexOf("m")));
return area
}
function getRent(url) {
const start_rent = '<div class="property_view_main-emphasis">';
const start_management_fee = '<div class="property_data-body">';
const end = '</div>';
let info_rent = getSuumoInfo(url, start_rent, end);
let rent_str = info_rent[0].trim().replace('万円', '');
let rent = Number(rent_str) * 10000;
let info_management_fee = getSuumoInfo(url, start_management_fee, end);
let management_fee_str = info_management_fee[0].trim().replace('円', '');
if (management_fee_str=="-"){ // 管理費・共益費が0の場合
management_fee_str="0"
};
let management_fee = Number(management_fee_str);
let total_fee = (rent + management_fee)/10000;
return total_fee
}
function getAddress(url) {
const start = '<div class="property_view_detail-text">';
const end = '</div>';
let info = getSuumoInfo(url, start, end);
let address = info.pop().trim();
address = checkError(address)
return address
}
function getAccessInfo(url) {
const start = '<div class="property_view_detail-text">';
const end = '</div>';
let info = getSuumoInfo(url, start, end);
let access = info.shift().trim();
access = checkError(access)
return access
}
結果
よかったポイント
- 「これが欲しかったんや!」という良いPoCになった
- URLを貼るだけでズバズバ情報が入力されるのは、やっぱり気持ちいい!快適!!!
- 通勤時間は結構重要な情報だった、物件一覧と通勤時間を横並びに見れるのは大変便利。
改善すべきポイント
- セル上で実施する計算式として実装しているため、スプレッドシートのリロードや、行の挿入・削除等で毎回計算が走ってしまう (優先度: Urgent)
- Suumoでお気に入りしていない状態のURLを入力すると、エラーになる (優先度: Medium)
課題については、しっかり記載していきます。
①毎回計算が走る問題 (Urgent)
セルに直書きしている実装となっているため、以下の状況で毎回計算が走ります。
- シートを開く、リロードする場合
- 行の挿入や削除を行った場合
計算が走ることで、以下の問題が発生します。結構クリティカル。
- Google Maps APIの「短時間にAPI叩きすぎじゃボケ」エラー
- 毎回計算が走るので、処理が遅い
-> 以下によって解決可能そう
- スプレッドシート上でトリガーを設定し、トリガーによって計算を実行する
- URL入力断面の情報をスプレッドシート上の別シートに保持・蓄積し、比較するシートは参照のみを行う
次の記事で対応予定
②お気に入りじゃないURL、エラーになる問題 (Medium)
Suumoの物件ページは、以下のようにお気に入り系のページと非お気に入りのページでURLが異なるそうです。
- お気に入り:
https://suumo.jp/chintai/bc_xxxxxxxxx/
- 非お気に入り:
https://suumo.jp/chintai/jnc_xxxxxxxxxx/
※細かく言えば他にもあるけど、上記2つで大別できる、程度の認識
URLが異なる上、ページ構造も完全に一致するわけではないので、単一のスクレイピングロジックだとエラーになってしまう、という状態。
想定している通常の使い方だと問題ないのですが、「お気に入り登録しないと、物件URLを入力できない」はダサいので、そのうち対応しようかなと。
終わりに
- JavaScript系の言語触るの初めてなので、手こずる部分もあったけど、ドキュメントとか見れば別に普通に書けた。うれしい。
- 動くものを作って、「すげえw」って一緒に喜べる体験自体がとても楽しかった。
- せっかくなので、もう少し便利な仕様にアップデートしたい。
参考情報
通勤時間計算周り
スクレイピング周り