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

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

ただいまの
回答率

88.10%

ハザードマップと物件情報を重ね合わせ、危険なエリア以外の物件を可視化する

受付中

回答 1

投稿

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

score 23

物件検索サイト「スーモ」からスクレイピングした物件情報の中から、ハザードマップの危険エリア外の物件だけをGooglemap上などにプロットし可視化するサービスを考えています。

現在の状況ですが、スーモから物件情報はクローリング&スクレイピングできました。
この情報から危険エリア外の物件だけを可視化したいと思っています。

ネット上で調べてみましたが、ハザードマップの危険エリアの位置情報はどうも落とせそうにありませんでした。

ご存じの方がいらっしゃいましたら、ご教授お願い致します。

ちなみにクローリングコードは以下です。

import requests
#Requestsを使用するとWebサイトの情報取得や画像の収集などを簡単に行うことが出来る
from bs4 import BeautifulSoup
#BeautifulSoupはスクレイピングに特化したモジュール
#htmlファイルをタグ情報から解析し、抽出データを格納したインスタンスを返す。
import os
#osモジュール
import time
#時刻に関する様々な関数を提供
#通勤時間20分、40分、60分場合分け
for folder in 20, 40, 60:
    # ディレクトリの場合分け
    dirname = "htmlbox{}".format(folder)
    #20分以内と40分以内、60分以内の3つのページをそれぞれ別々のフォルダに保存
    if not os.path.exists(dirname):
        #pythonでフォルダの存在確認
        # ディレクトリ作成
        os.mkdir(dirname)
        # それぞれの1ページ目をhtml化
        if folder == 20:
            base_url = "https://suumo.jp/jj/chintai/ichiran/FR301FC001/?ar=030&ta=13&bs=040&ekInput=00320&tj=20&nk=-1&ct=9999999&cb=0.0&et=9999999&mt=9999999&mb=0&cn=9999999&shkr1=03&shkr2=03&shkr3=03&shkr4=03&fw2=&pc=30"
        if folder == 40:
            base_url = "https://suumo.jp/jj/chintai/ichiran/FR301FC001/?ar=030&ta=13&bs=040&ekInput=00320&tj=40&nk=-1&ct=9999999&cb=0.0&et=9999999&mt=9999999&mb=0&cn=9999999&shkr1=03&shkr2=03&shkr3=03&shkr4=03&fw2=&pc=30"
        if folder == 60:
            base_url = "https://suumo.jp/jj/chintai/ichiran/FR301FC001/?ar=030&ta=13&bs=040&ekInput=00320&tj=60&nk=-1&ct=9999999&cb=0.0&et=9999999&mt=9999999&mb=0&cn=9999999&shkr1=03&shkr2=03&shkr3=03&shkr4=03&fw2=&pc=30"
        response = requests.get(base_url)
        #get()の第一引数にURLを指定するとresponseオブジェクトが取得できる。
        time.sleep(1)
        #サーバーに負荷をかけないように間をあける
        #ファイルに保存
        with open('htmlbox{}/page1.html'.format(folder), 'w', encoding='utf-8') as file:
        #with構文は、ファイルの読み込みが必要なコードでよく使われます。
        #with構文を使うとファイルの読み込みで必要なclose処理を省略することが出来る。
            file.write(response.text)

        # urlの引き出し
        soup = BeautifulSoup(response.content, "lxml")

        # 2ページ以降のurlを定義
        pages = soup.find_all("div", class_="pagination pagination_set-nav")
        #find_allでdivタグを全て取得
        pages_text = str(pages)
        pages_split = pages_text.split('</a></li>\n</ol>')
        #splitで</a></li>\n</ol>のタグで切り分け
        num_pages = int(pages_split[0].split('>')[-1])
        #2ページ目以降のurlをhtml化
        for i in range(2, num_pages + 1):
            next_url = base_url + "&page=" + str(i)
            #次のページのurlを作成
            response2 = requests.get(next_url)
            time.sleep(1)
            #ファイルに保存
            with open('htmlbox{}/page{}.html'.format(folder, i), 'w', encoding='utf-8') as file:
                file.write(response2.text)
        #検収条件
        print("{}分圏内の総ページ数".format(folder))
        print(num_pages)
        #実際取れたhtml数と比較

スクレイピングコードです。

import requests
from bs4 import BeautifulSoup
import os
import csv
import pandas as pd

#通学時間20分、40分、60分場合分け
for folder in 20, 40, 60:
    if folder == 20:
        num_html = 1702  #通勤時間が20分以内の取れたhtml数
    if folder == 40:
        num_html = 3937  #通勤時間が40分以内の取れたhtml数
    if folder == 60:
        num_html = 4580  #通勤時間が60分以内の取れたhtml数
    for i in range(num_html + 1):
    #取れたhtml数だけループ
        if i == 0:
        #0番目、つまり一番最初はcsvに項目だけ書きこむ
            with open('sumodata{}.csv'.format(folder), 'w', encoding='CP932',newline="") as file:
                writer = csv.writer(file)
                writer.writerow(["subtitle", "location", "station", "times", "years", "heights",
                   "floor", "rent", "admin", "deposit", "gratuity", "madori", "menseki"])
        else:
            with open('htmlbox{}/page{}.html'.format(folder, i), 'r', encoding='utf-8') as file:
                read = file.read()
            soup = BeautifulSoup(read, "lxml")
            cassetteitems = soup.find_all("div", class_="cassetteitem")
            #soupに入っているlxmlデータからクラスがcassetteitemのdivタグ要素を返す
            # 建物自体からスクレイピング
            for cas in range(len(cassetteitems)):#配列cassetteitemsの配列数までループ
                tbodies = cassetteitems[cas].find_all('tbody')#階・賃料・管理費・敷金・礼金・間取り・専有面積のひとまとまりの情報
                times1 = cassetteitems[cas].find("ul", class_="cassetteitem_transfer-list")#乗り換え回数・所要時間
                yearsheights = cassetteitems[cas].find("li", class_="cassetteitem_detail-col3") #築年数 高さ
                subtitle = cassetteitems[cas].find("div", class_="cassetteitem_content-title").string#物件名
                location = cassetteitems[cas].find("li", class_="cassetteitem_detail-col1").string#住所
                station = cassetteitems[cas].find("div", class_="cassetteitem_detail-text").string#最寄り駅
                times = times1.find("li").string#乗り換え回数・所要時間
                years = yearsheights.find_all('div')[0].string#築年数
                heights = yearsheights.find_all('div')[1].string#階数
                # 一つの建物のうちの部屋数をスクレイピング
                for tbody in tbodies:#tbodyにtbodiesのデータをひとつづつ取り出す
                    cols = tbody.find_all("td")
                    #colsにtbodyの中のtdタグを全て代入
                    for col, floor1 in enumerate(cols):#インデックス番号, 要素の順に取得できる。
                        if col == 2:#インデックス番号が2の場合
                            floor = floor1.string#floorに物件の階数を代入
                    rent = tbody.find(class_="cassetteitem_price cassetteitem_price--rent").string
                    #リストrentには、物件の家賃を代入
                    admin = tbody.find(class_="cassetteitem_price cassetteitem_price--administration").string
                    #リストadminには、管理費を代入
                    deposit = tbody.find(class_="cassetteitem_price cassetteitem_price--deposit").string
                    #リストdepositには、敷金を代入
                    gratuity = tbody.find(class_="cassetteitem_price cassetteitem_price--gratuity").string
                    #リストgratuityには、礼金を代入
                    madori = tbody.find(class_="cassetteitem_madori").string
                    #リストmadoriには、間取りを代入
                    menseki = tbody.find(class_="cassetteitem_menseki").text
                    #リストmensekiには、専有面積を代入
                    with open('sumodata{}.csv'.format(folder), 'a', encoding='CP932',newline="") as file :#sumodata{}.csvに追記
                        writer = csv.writer(file)
                        writer.writerow([subtitle, location, station, times, years, heights,floor, rent, admin, deposit, gratuity, madori, menseki])
                        # リストの中身を格納していく
    #検収条件
    df = pd.read_csv("sumodata{}.csv".format(folder), encoding="CP932")
    with open('htmlbox{}/page1.html'.format(folder), 'r', encoding='utf-8') as file:
        url = file.read()
    #掲載物件数をスクレイピング
    soup = BeautifulSoup(url,"lxml")
    pages = soup.find("div", class_="paginate_set-hit")
    #変数pagesにヒットした物件情報の数を代入
    pages_text = str(pages)
    #変数pagesを文字列型の変換
    pages_split = pages_text.split('\n')
    #リストpages_splitに、改行文字で区切った要素を代入
    pages = pages_split[1]
    #変数pagesには、「288669<span>件</span>」を代入
    num_text = pages.split("<span>")
    #リストnum_textには、<span>で区切った要素を代入
    num = num_text[0]
    #変数numには、ヒットした物件数の数値のみを代入
    if len(num) == len(df):
    #スクレイピングしたcsvデータの物件数と実際の検索結果物件数が一致しているか確認
        print("Clear")
        #もし、一致していた場合、clearを表示
    else:
        print("データが欠損")
        #データが欠損していた場合、データが欠損と表示
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • tanat

    2019/11/18 13:07

    スクレイピングしたデータを使ってサービスを提供するのは法律や利用規約に触れる可能性が高いと思われますが、その辺りはクリアされていますか?

    キャンセル

  • Taka787

    2019/11/18 13:10

    tanat様
    取り敢えずは個人的に利用を考えています。
    もし、自由に利用できるサイトがあれば、そのサイトから情報を落として、サービス化も考えております。

    キャンセル

回答 1

0

詳細は確認していませんが
国土数値情報
をうまくマッピングすれば出来そうな気がします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/11/18 16:18

    かしこまりました。

    キャンセル

  • 2019/11/18 16:27

    国土数値情報 googlemap 変換
    あたりで調べてみると、(全く同じでは無いですが)国土数値情報→googleMapで変換しているケースがあるので
    https://shimz.me/blog/google-map-api/2135
    参考になるかもしれません。

    キャンセル

  • 2019/11/18 16:28

    ありがとうございます。

    キャンセル

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

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

関連した質問

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