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

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

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

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

Q&A

1回答

2063閲覧

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

Taka787

総合スコア23

Python 3.x

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

0グッド

0クリップ

投稿2019/11/18 04:01

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

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

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

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

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

python

1import requests 2#Requestsを使用するとWebサイトの情報取得や画像の収集などを簡単に行うことが出来る 3from bs4 import BeautifulSoup 4#BeautifulSoupはスクレイピングに特化したモジュール 5#htmlファイルをタグ情報から解析し、抽出データを格納したインスタンスを返す。 6import os 7#osモジュール 8import time 9#時刻に関する様々な関数を提供 10#通勤時間20分、40分、60分場合分け 11for folder in 20, 40, 60: 12 # ディレクトリの場合分け 13 dirname = "htmlbox{}".format(folder) 14 #20分以内と40分以内、60分以内の3つのページをそれぞれ別々のフォルダに保存 15 if not os.path.exists(dirname): 16 #pythonでフォルダの存在確認 17 # ディレクトリ作成 18 os.mkdir(dirname) 19 # それぞれの1ページ目をhtml化 20 if folder == 20: 21 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" 22 if folder == 40: 23 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" 24 if folder == 60: 25 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" 26 response = requests.get(base_url) 27 #get()の第一引数にURLを指定するとresponseオブジェクトが取得できる。 28 time.sleep(1) 29 #サーバーに負荷をかけないように間をあける 30 #ファイルに保存 31 with open('htmlbox{}/page1.html'.format(folder), 'w', encoding='utf-8') as file: 32 #with構文は、ファイルの読み込みが必要なコードでよく使われます。 33 #with構文を使うとファイルの読み込みで必要なclose処理を省略することが出来る。 34 file.write(response.text) 35 36 # urlの引き出し 37 soup = BeautifulSoup(response.content, "lxml") 38 39 # 2ページ以降のurlを定義 40 pages = soup.find_all("div", class_="pagination pagination_set-nav") 41 #find_allでdivタグを全て取得 42 pages_text = str(pages) 43 pages_split = pages_text.split('</a></li>\n</ol>') 44 #splitで</a></li>\n</ol>のタグで切り分け 45 num_pages = int(pages_split[0].split('>')[-1]) 46 #2ページ目以降のurlをhtml化 47 for i in range(2, num_pages + 1): 48 next_url = base_url + "&page=" + str(i) 49 #次のページのurlを作成 50 response2 = requests.get(next_url) 51 time.sleep(1) 52 #ファイルに保存 53 with open('htmlbox{}/page{}.html'.format(folder, i), 'w', encoding='utf-8') as file: 54 file.write(response2.text) 55 #検収条件 56 print("{}分圏内の総ページ数".format(folder)) 57 print(num_pages) 58 #実際取れたhtml数と比較 59

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

python

1import requests 2from bs4 import BeautifulSoup 3import os 4import csv 5import pandas as pd 6 7#通学時間20分、40分、60分場合分け 8for folder in 20, 40, 60: 9 if folder == 20: 10 num_html = 1702 #通勤時間が20分以内の取れたhtml数 11 if folder == 40: 12 num_html = 3937 #通勤時間が40分以内の取れたhtml数 13 if folder == 60: 14 num_html = 4580 #通勤時間が60分以内の取れたhtml数 15 for i in range(num_html + 1): 16 #取れたhtml数だけループ 17 if i == 0: 18 #0番目、つまり一番最初はcsvに項目だけ書きこむ 19 with open('sumodata{}.csv'.format(folder), 'w', encoding='CP932',newline="") as file: 20 writer = csv.writer(file) 21 writer.writerow(["subtitle", "location", "station", "times", "years", "heights", 22 "floor", "rent", "admin", "deposit", "gratuity", "madori", "menseki"]) 23 else: 24 with open('htmlbox{}/page{}.html'.format(folder, i), 'r', encoding='utf-8') as file: 25 read = file.read() 26 soup = BeautifulSoup(read, "lxml") 27 cassetteitems = soup.find_all("div", class_="cassetteitem") 28 #soupに入っているlxmlデータからクラスがcassetteitemのdivタグ要素を返す 29 # 建物自体からスクレイピング 30 for cas in range(len(cassetteitems)):#配列cassetteitemsの配列数までループ 31 tbodies = cassetteitems[cas].find_all('tbody')#階・賃料・管理費・敷金・礼金・間取り・専有面積のひとまとまりの情報 32 times1 = cassetteitems[cas].find("ul", class_="cassetteitem_transfer-list")#乗り換え回数・所要時間 33 yearsheights = cassetteitems[cas].find("li", class_="cassetteitem_detail-col3") #築年数 高さ 34 subtitle = cassetteitems[cas].find("div", class_="cassetteitem_content-title").string#物件名 35 location = cassetteitems[cas].find("li", class_="cassetteitem_detail-col1").string#住所 36 station = cassetteitems[cas].find("div", class_="cassetteitem_detail-text").string#最寄り駅 37 times = times1.find("li").string#乗り換え回数・所要時間 38 years = yearsheights.find_all('div')[0].string#築年数 39 heights = yearsheights.find_all('div')[1].string#階数 40 # 一つの建物のうちの部屋数をスクレイピング 41 for tbody in tbodies:#tbodyにtbodiesのデータをひとつづつ取り出す 42 cols = tbody.find_all("td") 43 #colsにtbodyの中のtdタグを全て代入 44 for col, floor1 in enumerate(cols):#インデックス番号, 要素の順に取得できる。 45 if col == 2:#インデックス番号が2の場合 46 floor = floor1.string#floorに物件の階数を代入 47 rent = tbody.find(class_="cassetteitem_price cassetteitem_price--rent").string 48 #リストrentには、物件の家賃を代入 49 admin = tbody.find(class_="cassetteitem_price cassetteitem_price--administration").string 50 #リストadminには、管理費を代入 51 deposit = tbody.find(class_="cassetteitem_price cassetteitem_price--deposit").string 52 #リストdepositには、敷金を代入 53 gratuity = tbody.find(class_="cassetteitem_price cassetteitem_price--gratuity").string 54 #リストgratuityには、礼金を代入 55 madori = tbody.find(class_="cassetteitem_madori").string 56 #リストmadoriには、間取りを代入 57 menseki = tbody.find(class_="cassetteitem_menseki").text 58 #リストmensekiには、専有面積を代入 59 with open('sumodata{}.csv'.format(folder), 'a', encoding='CP932',newline="") as file :#sumodata{}.csvに追記 60 writer = csv.writer(file) 61 writer.writerow([subtitle, location, station, times, years, heights,floor, rent, admin, deposit, gratuity, madori, menseki]) 62 # リストの中身を格納していく 63 #検収条件 64 df = pd.read_csv("sumodata{}.csv".format(folder), encoding="CP932") 65 with open('htmlbox{}/page1.html'.format(folder), 'r', encoding='utf-8') as file: 66 url = file.read() 67 #掲載物件数をスクレイピング 68 soup = BeautifulSoup(url,"lxml") 69 pages = soup.find("div", class_="paginate_set-hit") 70 #変数pagesにヒットした物件情報の数を代入 71 pages_text = str(pages) 72 #変数pagesを文字列型の変換 73 pages_split = pages_text.split('\n') 74 #リストpages_splitに、改行文字で区切った要素を代入 75 pages = pages_split[1] 76 #変数pagesには、「288669<span>件</span>」を代入 77 num_text = pages.split("<span>") 78 #リストnum_textには、<span>で区切った要素を代入 79 num = num_text[0] 80 #変数numには、ヒットした物件数の数値のみを代入 81 if len(num) == len(df): 82 #スクレイピングしたcsvデータの物件数と実際の検索結果物件数が一致しているか確認 83 print("Clear") 84 #もし、一致していた場合、clearを表示 85 else: 86 print("データが欠損") 87 #データが欠損していた場合、データが欠損と表示 88

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

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

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

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

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

tanat

2019/11/18 04:07

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

2019/11/18 04:10

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

回答1

0

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

投稿2019/11/18 04:42

tanat

総合スコア18709

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

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

Taka787

2019/11/18 05:20

マッピングはGoogleMapなどで、ダウンロードしたXMLファイルをインポートしてという感じでしょうか?
tanat

2019/11/18 05:24

元々のデータ形式が違うので単純にインポートは出来ないでしょうから、以下の様な流れになるかと思います。 1. XMLの仕様を確認する(リンクページ内に仕様書っぽいリンクがあったはず) 2. XMLをパースして、サービスに必要なデータを取得する 3. 取得したデータをGoogleMapに載せられるデータに変換する 4. 物件データと組み合わせて表示する
Taka787

2019/11/18 06:43

3番までやってみたのですが、マップ上に表示されませんでした。インポートに失敗します。
Taka787

2019/11/18 06:46

パースは以下のように行いました。 ``` import xml.etree.ElementTree as ET tree = ET.parse('A31-12_13.xml') root = tree.getroot() print(root) ```
tanat

2019/11/18 07:10

であれば、1-3のうちのどこかでミスか抜けがある or 国土数値情報のデータでは足りないのどちらかです。 異なるソースのデータのマッピングは双方の仕様を把握して、地道に変換していくしか無いのでトライ&エラーを繰り返してみてください。 今回のケースで3を行うには 3-1. googleMapにインポートする為に必要な情報と書式を正確に把握する 3-2. googleMapにインポート出来るファイルを手書き等で自力で生成で出来るようになる 3-3. googleMapにインポート出来るファイルを生成するのに必要なデータを1から抽出する(そもそも存在するかどうかの判断も行う) という流れになります。 この辺の作業をスキップしようとすると、「googleMapにインポートできる形式のハザードマップデータ」を探す必要があります。 どちらが楽かはやってみないとわからないので、これも試してみてください。
Taka787

2019/11/18 07:18

かしこまりました。
tanat

2019/11/18 07:27

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

2019/11/18 07:28

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問