pythonでスクレイピング(beautifulsoup 応用編)
pythonでスクレイピング(beautifulsoup)について、独学を進めます。
前回の pythonでスクレイピング(beautifulsoup 基礎編)の続きです。
PC作業環境
OS: windows 8.1
pythonインストールできた状態なら
この記事の .pyファイルとバッチファイルをコピペして、バッチファイルをダブルクリックすれば動作確認できますので、ぜひ試してみて下さい!
理解する必要はありません。
①pythonを自分のPCにインストール
②.pyファイル(pythonコード)を自分のPCの作業フォルダにコピペ
③バッチファイルを自分のPCの作業フォルダにコピペ
④バッチファイルをダブルクリックで、パイソンコードが実行されて出力結果をゲット!
これだけでパイソンの概要が習得できます。①~④で分からないところがあれば、以前の記事を確認してみて下さい。それでも分からないときは以下のツイッター(独学推奨ツイート)のリプ欄で質問して下さいね。なるべく回答できるようにします。
ツイッター + ブログ =「無料で最強の学びツール」
— 南びわ湖エリア情報🛳️ (@minamibiwako) March 16, 2021
「どくがく」を補助してくれるアウトプット
無料ブログを収益という数字で
学びの進み方を「見える化」
ツイッターで援護射撃して
ブーストしながら高得点(高収益)をねらうゲーム#nobukue #ノブクエ #独学 #毒学 #無料https://t.co/GZHF0T3Xc4 pic.twitter.com/UN0qX606lL
pythonコードのインデント(tab)が、うまく表示できていません。
forループの下に、インデントを付けているtab情報が消えていますので注意願います !
改善できるように、はてなブログの「 \t 表示」について確認中です。
改善ができるまでは、、、
pythonコードをコピペするだけでは動きません。(tabある場合)
for文など、tabのインデントを追加するだけで動きます!
目次
引き続き、この動画シリーズで独学を進めていきます。
不動産情報の取得 PART1
ページ1~ 増やしていくときの書き方
bsでパース
パース(解析)結果の使い方
pythonコード parse_html_005.py
# coding: shift_jis
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')my_url = "https://suumo.jp/chintai/shiga/sc_kusatsu/?page={}"
target_url = my_url.format(1)
print("@@@@@@@@@@_1")
print("htmlを取得するurl")
print(target_url)import requests
my_html = requests.get(target_url)print("@@@@@@@@@@_2")
print("htmlを取得したurl")
print(my_html.url)print("@@@@@@@@@@_3")
#print("取得したhtml(長いので先頭の12行のみ表示)")
my_file = open("./output.txt", "w", encoding="utf-8")
print(my_html.text, file=my_file)
my_file.close()'''
複数行にわたるコメントアウトはトリプルクォーテーションで!
「read_table」は行頭にタブがあるとエラー出る(pandas.errors.ParserError: Error tokenizing data. C error: Expected 1 fields in line 20, saw 2)
data = pd.read_table("output3.txt")
よって「read_html」を試したが、lxmlがインポートされていないとエラー出る(ImportError: lxml not found, please install it)
「read_html」はリストでheadが使えるテキスト属性じゃないよとエラー出る(AttributeError: 'list' object has no attribute 'head')
よって「read_table」を使うことに戻し、タブを空白に置換してエラーを回避(目視確認のためだけなので暫定対策)
'''print("@@@@@@@@@@_4")
# ファイルを開く
my_file = open("./output1.txt", "w", encoding="utf-8")
with open("./output.txt", "r", encoding="utf-8") as f:
# 一行ずつ読み込む
for my_data1 in f:
# TAB を 空白へ置換(strip で white space を除去)
print(my_data1.strip().replace("\t"," "), file=my_file)
my_file.close()print("@@@@@@@@@@_5")
import pandas as pd
my_data2 = pd.read_table("output1.txt")
print(my_data2.head(12))print("@@@@@@@@@@_6")
print(my_data2)print("@@@@@@@@@@_7")
print("取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)")
html_type = type(my_html.text)
print(html_type)print("@@@@@@@@@@_8")
from bs4 import BeautifulSoup
soup = BeautifulSoup(my_html.text)
print(soup.find("title").text)print("@@@@@@@@@@_9")
print("スーモページの表示建物数20が取れているか")
contents = soup.find_all("div",class_="cassetteitem")
print(len(contents))
read_htmlを試すために、lxml をインポート
バッチファイル(pip_list.bat)
出力結果(0)
Package Version
--------------- ----------
beautifulsoup4 4.8.1
certifi 2019.11.28
chardet 3.0.4
idna 2.8
lxml 4.6.3
numpy 1.20.1
pandas 1.2.3
pip 21.0.1
python-dateutil 2.8.1
pytz 2021.1
requests 2.22.0
setuptools 41.2.0
six 1.15.0
soupsieve 1.9.5
urllib3 1.25.7
lxml がインストールされました。
バッチファイル(pythonコードを実行) do_py011.bat
rem do_py011.bat
@echo off
set year=%date:~0,4%
set month=%date:~5,2%
set day=%date:~8,2%
set time2=%time: =0%
set hour=%time2:~0,2%
set minute=%time2:~3,2%
set second=%time2:~6,2%
set logname=%year%-%month%-%day%_%hour%_%minute%_%second%python parse_html_005.py >> %logname%_parse_html_005.txt
rem pause
出力結果(1)
@@@@@@@@@@_1
htmlを取得するurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_2
htmlを取得したurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_3
@@@@@@@@@@_4
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
4942 };
4943 </script>
4944 </body>
4945 <!-- FR301FC0012 END -->
4946 </html>[4947 rows x 1 columns]
@@@@@@@@@@_7
取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)
<class 'str'>
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報
@@@@@@@@@@_9
スーモページの表示建物数20が取れているか
20
表示建物数20のデータが取れていることが確認できました。
物件・部屋情報を取得します。
物件情報(物件名、住所、アクセス、築年数)
部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)
物件情報(物件名、住所、アクセス、築年数)
部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)
【演習】部屋情報の取得
pythonコード parse_html_006.py
# coding: shift_jis
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')my_url = "https://suumo.jp/chintai/shiga/sc_kusatsu/?page={}"
target_url = my_url.format(1)
print("@@@@@@@@@@_1")
print("htmlを取得するurl")
print(target_url)import requests
my_html = requests.get(target_url)print("@@@@@@@@@@_2")
print("htmlを取得したurl")
print(my_html.url)print("@@@@@@@@@@_3")
#print("取得したhtml(長いので先頭の12行のみ表示)")
my_file = open("./output.txt", "w", encoding="utf-8")
print(my_html.text, file=my_file)
my_file.close()'''
複数行にわたるコメントアウトはトリプルクォーテーションで!
「read_table」は行頭にタブがあるとエラー出る(pandas.errors.ParserError: Error tokenizing data. C error: Expected 1 fields in line 20, saw 2)
data = pd.read_table("output3.txt")
よって「read_html」を試したが、lxmlがインポートされていないとエラー出る(ImportError: lxml not found, please install it)
「read_html」はリストでheadが使えるテキスト属性じゃないよとエラー出る(AttributeError: 'list' object has no attribute 'head')
よって「read_table」を使うことに戻し、タブを空白に置換してエラーを回避(目視確認のためだけなので暫定対策)
'''print("@@@@@@@@@@_4")
# ファイルを開く
my_file = open("./output1.txt", "w", encoding="utf-8")
with open("./output.txt", "r", encoding="utf-8") as f:
# 一行ずつ読み込む
for my_data1 in f:
# TAB を 空白へ置換(strip で white space を除去)
print(my_data1.strip().replace("\t"," "), file=my_file)
my_file.close()print("@@@@@@@@@@_5")
import pandas as pd
my_data2 = pd.read_table("output1.txt")
print(my_data2.head(12))print("@@@@@@@@@@_6")
print(my_data2)print("@@@@@@@@@@_7")
print("取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)")
html_type = type(my_html.text)
print(html_type)print("@@@@@@@@@@_8")
from bs4 import BeautifulSoup
soup = BeautifulSoup(my_html.text)
print(soup.find("title").text)print("@@@@@@@@@@_9")
print("スーモページの表示建物数20が取れているか")
contents = soup.find_all("div", class_="cassetteitem")
print(len(contents))print("@@@@@@@@@@_10")
print("物件情報(物件名、住所、アクセス、築年数)")
content = contents[0]
detail = content.find("div", class_="cassetteitem-detail")
title = detail.find("div", class_="cassetteitem_content-title").text
address = detail.find("li", class_="cassetteitem_detail-col1").text
access = detail.find("li", class_="cassetteitem_detail-col2").text
age = detail.find("li", class_="cassetteitem_detail-col3").text
print(title)
print(address)
print(access)
print(age)print("@@@@@@@@@@_11")
# print(content)
table = content.find("table", class_="cassetteitem_other")
# print(table)print("@@@@@@@@@@_12")
tr_tags = table.find_all("tr", class_="js-cassette_link")
print(len(tr_tags))print("@@@@@@@@@@_13")
tr_tag = tr_tags[0]
# print(tr_tag)print("@@@@@@@@@@_14")
print("部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)")
td_tags = tr_tag.find_all("td")# td_tag = td_tags[0]
# print(td_tag)# td_tag = td_tags[1]
# print(td_tag)td_tag = td_tags[2]
print(td_tag.text)td_tag = td_tags[3]
print(td_tag.text)td_tag = td_tags[4]
print(td_tag.text)td_tag = td_tags[5]
print(td_tag.text)
バッチファイル(pythonコードを実行) do_py012.bat
rem do_py012.bat
@echo off
set year=%date:~0,4%
set month=%date:~5,2%
set day=%date:~8,2%
set time2=%time: =0%
set hour=%time2:~0,2%
set minute=%time2:~3,2%
set second=%time2:~6,2%
set logname=%year%-%month%-%day%_%hour%_%minute%_%second%python parse_html_006.py >> %logname%_parse_html_006.txt
rem pause
出力結果(2)
@@@@@@@@@@_1
htmlを取得するurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_2
htmlを取得したurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_3
@@@@@@@@@@_4
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
5563 };
5564 </script>
5565 </body>
5566 <!-- FR301FC0012 END -->
5567 </html>[5568 rows x 1 columns]
@@@@@@@@@@_7
取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)
<class 'str'>
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報
@@@@@@@@@@_9
スーモページの表示建物数20が取れているか
20
@@@@@@@@@@_10
物件情報(物件名、住所、アクセス、築年数)
トップペアー福甚No.2
滋賀県草津市野路東4JR東海道本線/南草津駅 歩16分
JR東海道本線/瀬田駅 歩49分
JR東海道本線/草津駅 歩47分
築27年
3階建@@@@@@@@@@_11
@@@@@@@@@@_12
2
@@@@@@@@@@_13
@@@@@@@@@@_14
部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)
3階
6万円
5000円
-
5万円
2LDK
52.8m2
演習問題である「部屋情報の取得」ができていることが確認できました。
不動産情報の取得 PART2
unpack
floor, price, first_fee, capacity
データの仕分け
floor, price, first_fee, capacity
fee, management_fee, deposit, gratuity, madori, menseki
データの格納
forループ
pythonコード parse_html_007.py
# coding: shift_jis
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')my_url = "https://suumo.jp/chintai/shiga/sc_kusatsu/?page={}"
target_url = my_url.format(1)
print("@@@@@@@@@@_1")
print("htmlを取得するurl")
print(target_url)import requests
my_html = requests.get(target_url)print("@@@@@@@@@@_2")
print("htmlを取得したurl")
print(my_html.url)print("@@@@@@@@@@_3")
#print("取得したhtml(長いので先頭の12行のみ表示)")
my_file = open("./output.txt", "w", encoding="utf-8")
print(my_html.text, file=my_file)
my_file.close()'''
複数行にわたるコメントアウトはトリプルクォーテーションで!
「read_table」は行頭にタブがあるとエラー出る(pandas.errors.ParserError: Error tokenizing data. C error: Expected 1 fields in line 20, saw 2)
data = pd.read_table("output3.txt")
よって「read_html」を試したが、lxmlがインポートされていないとエラー出る(ImportError: lxml not found, please install it)
「read_html」はリストでheadが使えるテキスト属性じゃないよとエラー出る(AttributeError: 'list' object has no attribute 'head')
よって「read_table」を使うことに戻し、タブを空白に置換してエラーを回避(目視確認のためだけなので暫定対策)
'''print("@@@@@@@@@@_4")
# ファイルを開く
my_file = open("./output1.txt", "w", encoding="utf-8")
with open("./output.txt", "r", encoding="utf-8") as f:
# 一行ずつ読み込む
for my_data1 in f:
# TAB を 空白へ置換(strip で white space を除去)
print(my_data1.strip().replace("\t"," "), file=my_file)
my_file.close()print("@@@@@@@@@@_5")
import pandas as pd
my_data2 = pd.read_table("output1.txt")
print(my_data2.head(12))print("@@@@@@@@@@_6")
print(my_data2)print("@@@@@@@@@@_7")
print("取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)")
html_type = type(my_html.text)
print(html_type)print("@@@@@@@@@@_8")
from bs4 import BeautifulSoup
soup = BeautifulSoup(my_html.text)
print(soup.find("title").text)print("@@@@@@@@@@_9")
print("スーモページの表示建物数20が取れているか")
contents = soup.find_all("div", class_="cassetteitem")
print(len(contents))print("@@@@@@@@@@_10")
print("物件情報(物件名、住所、アクセス、築年数)")
content = contents[0]
detail = content.find("div", class_="cassetteitem-detail")
title = detail.find("div", class_="cassetteitem_content-title").text
address = detail.find("li", class_="cassetteitem_detail-col1").text
access = detail.find("li", class_="cassetteitem_detail-col2").text
age = detail.find("li", class_="cassetteitem_detail-col3").text
print(title)
print(address)
print(access)
print(age)print("@@@@@@@@@@_11")
# print(content)
table = content.find("table", class_="cassetteitem_other")
# print(table)print("@@@@@@@@@@_12")
tr_tags = table.find_all("tr", class_="js-cassette_link")
print(len(tr_tags))print("@@@@@@@@@@_13")
tr_tag = tr_tags[0]
# print(tr_tag)print("@@@@@@@@@@_14")
print("部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)")
td_tags = tr_tag.find_all("td")# td_tag = td_tags[0]
# print(td_tag)# td_tag = td_tags[1]
# print(td_tag)td_tag = td_tags[2]
print(td_tag.text)td_tag = td_tags[3]
print(td_tag.text)td_tag = td_tags[4]
print(td_tag.text)td_tag = td_tags[5]
print(td_tag.text)print("@@@@@@@@@@_14")
print("データの仕分け")
floor, price, first_fee, capacity = tr_tag.find_all("td")[2:6]fee, management_fee = price.find_all("li")
deposit, gratuity = first_fee.find_all("li")
madori, menseki = capacity.find_all("li")
print(floor.text)
print(fee.text)
print(management_fee.text)
print(deposit.text)
print(gratuity.text)
print(madori.text)
print(menseki.text)print("@@@@@@@@@@_15")
print("データの格納")
d = {
"title": title,
"address": address,
"access": access,
"age": age,
"floor": floor.text,
"fee": fee.text,
"management_fee": management_fee.text,
"deposit": deposit.text,
"gratuity": gratuity.text,
"madori": madori.text,
"menseki": menseki.text
}
print(d)print("@@@@@@@@@@_16")
print("小さく情報取得がokだったので、forループ")
# from pprint import pprint
d_list =
contents = soup.find_all("div", class_="cassetteitem")
# content = contents[0]
for content in contents:
detail = content.find("div", class_="cassetteitem-detail")
title = detail.find("div", class_="cassetteitem_content-title").text
address = detail.find("li", class_="cassetteitem_detail-col1").text
access = detail.find("li", class_="cassetteitem_detail-col2").text
age = detail.find("li", class_="cassetteitem_detail-col3").texttable = content.find("table", class_="cassetteitem_other")
tr_tags = table.find_all("tr", class_="js-cassette_link")# tr_tag = tr_tags[0]
for tr_tag in tr_tags:
floor, price, first_fee, capacity = tr_tag.find_all("td")[2:6]
fee, management_fee = price.find_all("li")
deposit, gratuity = first_fee.find_all("li")
madori, menseki = capacity.find_all("li")
d = {
"title": title,
"address": address,
"access": access,
"age": age,
"floor": floor.text,
"fee": fee.text,
"management_fee": management_fee.text,
"deposit": deposit.text,
"gratuity": gratuity.text,
"madori": madori.text,
"menseki": menseki.text
}
# リストd_listの末尾に要素(取得した辞書d)を追加格納する
d_list.append(d)
# pprint(d, depth=2, width=70)
print(d)
バッチファイル(pythonコードを実行) do_py013.bat
rem do_py013.bat
@echo off
set year=%date:~0,4%
set month=%date:~5,2%
set day=%date:~8,2%
set time2=%time: =0%
set hour=%time2:~0,2%
set minute=%time2:~3,2%
set second=%time2:~6,2%
set logname=%year%-%month%-%day%_%hour%_%minute%_%second%python parse_html_007.py >> %logname%_parse_html_007.txt
rem pause
出力結果(3)
@@@@@@@@@@_1
htmlを取得するurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_2
htmlを取得したurl
https://suumo.jp/chintai/shiga/sc_kusatsu/?page=1
@@@@@@@@@@_3
@@@@@@@@@@_4
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
4883 };
4884 </script>
4885 </body>
4886 <!-- FR301FC0012 END -->
4887 </html>[4888 rows x 1 columns]
@@@@@@@@@@_7
取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)
<class 'str'>
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報
@@@@@@@@@@_9
スーモページの表示建物数20が取れているか
20
@@@@@@@@@@_10
物件情報(物件名、住所、アクセス、築年数)
ユニヴァリィ グランヴィア8
滋賀県草津市草津町JR東海道本線/草津駅 歩19分
JR東海道本線/南草津駅 歩25分
JR東海道本線/栗東駅 歩54分
築1年
3階建@@@@@@@@@@_11
@@@@@@@@@@_12
1
@@@@@@@@@@_13
@@@@@@@@@@_14
部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)
3階
8.1万円
5000円
8.1万円
8.1万円
2LDK
51m2
@@@@@@@@@@_14
データの仕分け
3階
8.1万円
5000円
8.1万円
8.1万円
2LDK
51m2
@@@@@@@@@@_15
データの格納
{'title': 'ユニヴァリィ\u3000グランヴィア8', 'address': '滋賀県草津市草津町', 'access': '\nJR東海道本線/草津駅 歩19分\nJR東海道本線/南草津駅 歩25分\nJR東海道本線/栗東駅 歩54分\n', 'age': '\n築1年\n3階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t3階', 'fee': '8.1万円', 'management_fee': '5000円', 'deposit': '8.1万円', 'gratuity': '8.1万円', 'madori': '2LDK', 'menseki': '51m2'}
@@@@@@@@@@_16
小さく情報取得がokだったので、forループ
{'title': 'ユニヴァリィ\u3000グランヴィア8', 'address': '滋賀県草津市草津町', 'access': '\nJR東海道本線/草津駅 歩19分\nJR東海道本線/南草津駅 歩25分\nJR東海道本線/栗東駅 歩54分\n', 'age': '\n築1年\n3階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t3階', 'fee': '8.1万円', 'management_fee': '5000円', 'deposit': '8.1万円', 'gratuity': '8.1万円', 'madori': '2LDK', 'menseki': '51m2'}
{'title': 'メゾン・アイリス', 'address': '滋賀県草津市追分3', 'access': '\nJR東海道本線/南草津駅 歩22分\nJR東海道本線/草津駅 歩23分\nJR東海道本線/栗東駅 歩47分\n', 'age': '\n築11年\n2階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t1階', 'fee': '6.9万円', 'management_fee': '3000円', 'deposit': '6.9万円', 'gratuity': '-', 'madori': '2LDK', 'menseki': '57.85m2'}以下、省略
ここまでの内容で、
javascriptが使われていないwebページであれば、自由自在に情報抽出できます!
不動産情報の取得 複数ページから
sleep
forループ(1~3ページまで)
pythonコード parse_html_008.py
# coding: shift_jis
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')from time import sleep
from bs4 import BeautifulSoup
import requests
import pandas as pd
import sys
my_url = "https://suumo.jp/chintai/shiga/sc_kusatsu/?page={}"
d_list =
sys.stderr.write("requests.get ")for i in range(1,4):
# target_url = my_url.format(1)
target_url = my_url.format(i)# print("@@@@@@@@@@_1")
# print("htmlを取得するurl")
# print(target_url)
my_html = requests.get(target_url)
sys.stderr.write(".")
sleep(1)
sys.stderr.write(".")
sleep(1)
sys.stderr.write(".")
sleep(1)
# print("@@@@@@@@@@_2")
# print("htmlを取得したurl")
# print(my_html.url)# print("@@@@@@@@@@_3")
# print("取得したhtml(長いので先頭の12行のみ表示)")
my_file = open("./output.txt", "w", encoding="utf-8")
print(my_html.text, file=my_file)
my_file.close()'''
複数行にわたるコメントアウトはトリプルクォーテーションで!
「read_table」は行頭にタブがあるとエラー出る(pandas.errors.ParserError: Error tokenizing data. C error: Expected 1 fields in line 20, saw 2)
data = pd.read_table("output3.txt")
よって「read_html」を試したが、lxmlがインポートされていないとエラー出る(ImportError: lxml not found, please install it)
「read_html」はリストでheadが使えるテキスト属性じゃないよとエラー出る(AttributeError: 'list' object has no attribute 'head')
よって「read_table」を使うことに戻し、タブを空白に置換してエラーを回避(目視確認のためだけなので暫定対策)
'''# print("@@@@@@@@@@_4")
# ファイルを開く
my_file = open("./output1.txt", "w", encoding="utf-8")
with open("./output.txt", "r", encoding="utf-8") as f:
# 一行ずつ読み込む
for my_data1 in f:
# TAB を 空白へ置換(strip で white space を除去)
print(my_data1.strip().replace("\t"," "), file=my_file)
my_file.close()print("@@@@@@@@@@_5")
my_data2 = pd.read_table("output1.txt")
print(my_data2.head(12))print("@@@@@@@@@@_6")
print(my_data2)# print("@@@@@@@@@@_7")
# print("取得したhtmlのtype判定(str型ならbeautifulsoupでのパース解析可能)")
# html_type = type(my_html.text)
# print(html_type)print("@@@@@@@@@@_8")
soup = BeautifulSoup(my_html.text)
print(soup.find("title").text)print("@@@@@@@@@@_9")
# print("スーモページの表示建物数20が取れているか")
contents = soup.find_all("div", class_="cassetteitem")
print(len(contents))# print("@@@@@@@@@@_10")
'''
print("物件情報(物件名、住所、アクセス、築年数)")
content = contents[0]
detail = content.find("div", class_="cassetteitem-detail")
title = detail.find("div", class_="cassetteitem_content-title").text
address = detail.find("li", class_="cassetteitem_detail-col1").text
access = detail.find("li", class_="cassetteitem_detail-col2").text
age = detail.find("li", class_="cassetteitem_detail-col3").text
print(title)
print(address)
print(access)
print(age)
'''# print("@@@@@@@@@@_11")
# print(content)
'''
table = content.find("table", class_="cassetteitem_other")
'''
# print(table)# print("@@@@@@@@@@_12")
'''
tr_tags = table.find_all("tr", class_="js-cassette_link")
print(len(tr_tags))
'''# print("@@@@@@@@@@_13")
'''
tr_tag = tr_tags[0]
'''
# print(tr_tag)# print("@@@@@@@@@@_14")
'''
print("部屋情報(物件の階数、賃料/管理費、敷金・礼金、間取り・面積)")
td_tags = tr_tag.find_all("td")
'''
# td_tag = td_tags[0]
# print(td_tag)# td_tag = td_tags[1]
# print(td_tag)
'''
td_tag = td_tags[2]
print(td_tag.text)td_tag = td_tags[3]
print(td_tag.text)td_tag = td_tags[4]
print(td_tag.text)td_tag = td_tags[5]
print(td_tag.text)
'''# print("@@@@@@@@@@_14")
'''
print("データの仕分け")
floor, price, first_fee, capacity = tr_tag.find_all("td")[2:6]fee, management_fee = price.find_all("li")
deposit, gratuity = first_fee.find_all("li")
madori, menseki = capacity.find_all("li")
print(floor.text)
print(fee.text)
print(management_fee.text)
print(deposit.text)
print(gratuity.text)
print(madori.text)
print(menseki.text)
'''# print("@@@@@@@@@@_15")
'''
print("データの格納")
d = {
"title": title,
"address": address,
"access": access,
"age": age,
"floor": floor.text,
"fee": fee.text,
"management_fee": management_fee.text,
"deposit": deposit.text,
"gratuity": gratuity.text,
"madori": madori.text,
"menseki": menseki.text
}
print(d)
'''print("@@@@@@@@@@_16")
# print("小さく情報取得がokだったので、forループ")
# from pprint import pprint
# d_list = []
contents = soup.find_all("div", class_="cassetteitem")
# content = contents[0]
for content in contents:
detail = content.find("div", class_="cassetteitem-detail")
title = detail.find("div", class_="cassetteitem_content-title").text
address = detail.find("li", class_="cassetteitem_detail-col1").text
access = detail.find("li", class_="cassetteitem_detail-col2").text
age = detail.find("li", class_="cassetteitem_detail-col3").texttable = content.find("table", class_="cassetteitem_other")
tr_tags = table.find_all("tr", class_="js-cassette_link")# tr_tag = tr_tags[0]
for tr_tag in tr_tags:
floor, price, first_fee, capacity = tr_tag.find_all("td")[2:6]
fee, management_fee = price.find_all("li")
deposit, gratuity = first_fee.find_all("li")
madori, menseki = capacity.find_all("li")
d = {
"title": title,
"address": address,
"access": access,
"age": age,
"floor": floor.text,
"fee": fee.text,
"management_fee": management_fee.text,
"deposit": deposit.text,
"gratuity": gratuity.text,
"madori": madori.text,
"menseki": menseki.text
}
# リストd_listの末尾に要素(取得した辞書d)を追加格納する
d_list.append(d)
# pprint(d, depth=2, width=70)
print(d)
forループのインデント情報が消えてしまっています!申し訳ありません。
(はてなブログにpyソースを貼り付けると \t 情報が消えてしまう現象、なぜ?)
forループ内にインデント(字下げ)を追加しないとコピペだけでは動きません!
対策方法が分かり次第、修正します。
内容について
標準出力(print)は、バッチファイルでリダイレクトしてテキストファイルに落としています。エラー出力として、データ取得の進捗状況が把握したいと思いstderrで試してみましたが、全処理が終わったあとでの表示になってしまい、リアルタイムでの進捗状況確認はできませんでした。できなかった記録として、ソースを残しておきます!
バッチファイル(pythonコードを実行) do_py014.bat
rem do_py014.bat
@echo off
set year=%date:~0,4%
set month=%date:~5,2%
set day=%date:~8,2%
set time2=%time: =0%
set hour=%time2:~0,2%
set minute=%time2:~3,2%
set second=%time2:~6,2%
set logname=%year%-%month%-%day%_%hour%_%minute%_%second%python parse_html_008.py >> %logname%_parse_html_008.txt
rem pause
出力結果(4)
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
4496 };
4497 </script>
4498 </body>
4499 <!-- FR301FC0012 END -->
4500 </html>[4501 rows x 1 columns]
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報
@@@@@@@@@@_9
20
@@@@@@@@@@_16
{'title': 'ヴィラコーポ清水', 'address': '滋賀県草津市南笠東1', 'access': '\nJR東海道本線/南草津駅 歩16分\nJR東海道本線/瀬田駅 歩35分\nJR東海道本線/草津駅 歩64分\n', 'age': '\n築34年\n4階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t2階', 'fee': '6万円', 'management_fee': '3000円', 'deposit': '12万円', 'gratuity': '-', 'madori': '3LDK', 'menseki': '63m2'}以下省略
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
5010 };
5011 </script>
5012 </body>
5013 <!-- FR301FC0012 END -->
5014 </html>[5015 rows x 1 columns]
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報(2ページ)
@@@@@@@@@@_9
20
@@@@@@@@@@_16
{'title': 'JR東海道本線 南草津駅 4階建 築13年', 'address': '滋賀県草津市南草津1', 'access': '\nJR東海道本線/南草津駅 歩4分\nJR東海道本線/草津駅 歩54分\nJR東海道本線/瀬田駅 歩39分\n', 'age': '\n築13年\n4階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t2階', 'fee': '6.9万円', 'management_fee': '2500円', 'deposit': '-', 'gratuity': '6.9万円', 'madori': '1K', 'menseki': '30.96m2'}以下省略
@@@@@@@@@@_5
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
5 <head>
6 <meta charset="utf-8" />
7 <!-- seo.headerTag Start -->
8 <title>【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報...
9 <meta name="keywords" content='草津市,滋賀県,賃貸,賃貸マン...
10 <meta name="description" content='【SUUMO(スーモ)賃...
11 <link rel="shortcut icon" href="/front/img/fav...
@@@@@@@@@@_6
<!DOCTYPE html>
0 <!--[if lt IE 7]><html lang="ja" class="ie"><!...
1 <!--[if IE 7]><html lang="ja" class="ie"><![en...
2 <!--[if IE 8]><html lang="ja" class="ie"><![en...
3 <!--[if gt IE 8]><!--><html lang="ja"><!--<![e...
4 <!-- FR301FC0012 START -->
... ...
4491 };
4492 </script>
4493 </body>
4494 <!-- FR301FC0012 END -->
4495 </html>[4496 rows x 1 columns]
@@@@@@@@@@_8
【SUUMO】草津市の賃貸(賃貸マンション・アパート)住宅のお部屋探し物件情報(3ページ)
@@@@@@@@@@_9
20
@@@@@@@@@@_16
{'title': 'JR東海道本線 南草津駅 6階建 築30年', 'address': '滋賀県草津市南笠東2', 'access': '\nJR東海道本線/南草津駅 歩20分\nJR東海道本線/瀬田駅 歩26分\nJR東海道本線/草津駅 歩59分\n', 'age': '\n築30年\n6階建\n', 'floor': '\r\n\t\t\t\t\t\t\t\t\t\t\t2階', 'fee': '5.5万円', 'management_fee': '5000円', 'deposit': '-', 'gratuity': '-', 'madori': '2LDK', 'menseki': '53.9m2'}
以下省略
3ページ分のデータが取得できたことが確認できました。
スクレイピング結果をCSVに保存
この動画までで、pythonのスクレイピングの一連の流れが習得
記述中
( pythonでスクレイピング(beautifulsoup 基礎編) からお読み下さい)
滋賀を盛り上げていく旅は続く
■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■
以下、ネット上の反応