46 【Python Scrapyの学び】 不動産の物件情報を抽出してExcelに出力する方法2 ~カラムDetail解説編~
こんにちは!TechCommitメンバーの友季子です♬今回は、WebサイトのSUUMOさまから物件情報を抽出してExcelに出力する【Detailカラム】についてまとめてみます。特にPython、Scrapyを学んでいる方に役立つ情報をお届けしますので、ぜひ参考にしてくださいね♪
0. 前提
この記事では、PythonのライブラリScrapyを使って、ウェブサイトから物件情報をスクレイピングし、整理してExcelファイルに保存する方法を紹介します。以下のことについて理解しておくと、よりスムーズに進めることができます:
PythonとScrapyの基礎: PythonのプログラミングとScrapyライブラリの使い方。
HTMLの基本構造: HTML内のデータがどのように構造化されているか。
データ整形の重要性: データを整形することで分析やレポート作成が簡単になります。
1. 全体の完成コード(サンプル)
import scrapy
from scrapy.http.response.html import HtmlResponse
from urllib.parse import urljoin
from parsel import SelectorList
import pandas as pd
from datetime import datetime
class SuumoSpider(scrapy.Spider):
name = "suumo"
origin = "https://suumo.jp"
allowed_domains = ["suumo.jp"]
start_urls = [
"https://suumo.jp/jj/chintai/ichiran/FR301FC005/?ar=030&bs=040&ta=13&sc=13113&cb=0.0&ct=8.0&mb=0&mt=9999999&et=20&cn=5&shkr1=03&shkr2=03&shkr3=03&shkr4=03&sngz=&po1=25&po2=99&pc=50"
]
properties = [] # データを保存するリスト
async def parse(self, response: HtmlResponse):
await self.handle_response(response)
# ページネーション処理
paginators: SelectorList = response.css(".pagination-parts")
last_paginator = paginators[-1]
if last_paginator.css("::text").get() == "次へ":
next_url = last_paginator.css("a").attrib.get("href")
if next_url:
yield scrapy.Request(url=urljoin(self.origin, next_url))
async def handle_response(self, response: HtmlResponse):
for row in response.css("div.property"):
title = row.css("h2.property_inner-title a::text").get()
rent_price = row.css("div.detailbox-property-point::text").get()
property_table = row.css("div.detailbox > div.detailbox-property > table")
plan_of_house = property_table.css("td.detailbox-property--col3 div::text").get()
exclusive_area = property_table.css("td.detailbox-property--col3 div::text")[1].get()
detail_texts = row.css("div.detailbox-note div.detailnote-box div::text").getall()
detail_texts = [t.strip() for t in detail_texts if t.strip() != ""]
detail = "\n".join(detail_texts).strip()
# 住所の取得
address = self.extract_address(row)
# スクレイピング結果を一時的にリストに保存
self.properties.append({
"Title": title,
"Rent Price": rent_price,
"Plan of House": plan_of_house,
"Exclusive Area": exclusive_area,
"Detail": detail,
"Address": address, # 住所を追加
})
def extract_address(self, row):
# 住所の取得
address_elem = row.css("td.detailbox-property-col::text").get()
if address_elem and any(prefecture in address_elem for prefecture in PREFECTURES):
return address_elem.strip()
return "住所が見つかりません"
def close(self, reason):
"""
スパイダーが全ての処理を完了した際に呼び出される
"""
self.save_to_excel()
def save_to_excel(self):
# pandasを使ってデータをExcelに変換
df = pd.DataFrame(self.properties)
# 現在の日付と時間をファイル名に組み込む
current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
file_name = f"suumo_data_{current_time}.xlsx"
# ファイルをダウンロードフォルダ直下に保存
file_path = f"C:/Users/yukik/Downloads/{file_name}"
df.to_excel(file_path, index=False)
self.log(f"Excel file saved: {file_path}")
2. コードのクラスとメソッドの説明
class SuumoSpider(scrapy.Spider):
Scrapyのスパイダーを定義するクラスで、ウェブサイトからデータを抽出します。
name = "suumo"
スパイダーの名前。Scrapyでスパイダーを識別するために使用します。
origin = "https://suumo.jp"
スクレイピング対象の基本URLです。
allowed_domains = ["suumo.jp"]
スクレイピングを許可するドメインのリストです。
start_urls
スクレイピングを開始する最初のURLリストです。
async def parse(self, response: HtmlResponse):
メインのパースメソッド。ウェブサイトからHTMLを取得し、handle_response メソッドに渡します。
await self.handle_response(response)
handle_response メソッドを呼び出して、データ処理を行います。
paginators: SelectorList = response.css(".pagination-parts")
ページネーションのリンクを取得します。
async def handle_response(self, response: HtmlResponse):
物件情報の各要素を抽出し、リストに保存します。
self.extract_address(row)
住所を抽出する補助メソッドです。
def extract_address(self, row):
住所を抽出するためのメソッド。PREFECTURES リストを使用して、住所が正しいかを確認します。
def close(self, reason):
スパイダーが終了したときに呼び出されるメソッド。収集したデータをExcelファイルとして保存します。ダウンロード直下に保存します。
def save_to_excel(self):
pandasを使って収集したデータをExcelファイルに保存するメソッドです。
3. コードの流れ
データの取得: parse メソッドでウェブサイトからHTMLを取得し、handle_response メソッドに渡します。
データの抽出: handle_response メソッドで、物件情報や詳細な説明を抽出します。住所の取得には extract_address メソッドを使用します。
データの保存: スクレイピングが終了すると、close メソッドが呼ばれ、収集したデータがExcelファイルとして保存されます。※抽出時間などが表記されます。
4. Detailカラムの解説
4-1データ抽出と整形
detail_texts = row.css("div.detailbox-note div.detailnote-box div::text").getall()
row.css("div.detailbox-note div.detailnote-box div::text").getall():
ここで、HTMLの特定の部分からすべてのテキストを取り出し
※css() メソッドで、指定したクラスの要素を探したり、その中のテキストを取り出しをします。
4-2データクリーニング
detail_texts = [t.strip() for t in detail_texts if t.strip() != ""]
detail_texts = [t.strip() for t in detail_texts if t.strip() != ""]
各テキストの前後の空白を削除し、空のテキスト(スペースだけのテキスト)を除外します。これにより、意味のある情報だけが残ります。
4-3テキストの整形
detail = "\n".join(detail_texts).strip()
detail = "\n".join(detail_texts).strip()
"\n".join(detail_texts) で、リスト内のテキストを改行で区切って1つの大きな文字列に結合します。
.strip() で最終的な前後の空白を取り除きます。
例:もしHTMLが次のようだとすると・・・
<div class="detailnote-box">
<div>駅徒歩5分</div>
<div>近くにスーパーあり</div>
<div>日当たり良好</div>
</div>
この処理をすると、次のようなテキストになります:
駅徒歩5分
近くにスーパーあり
日当たり良好
5. おわりに
ここまでお読みいただき、ありがとうございました!今回の記事では、私がScrapyを使ってWebページから物件情報を抽出し、整形するために学んでいることを説明しました。もし、ちょっとでもお役に立てばイイネ💗お願いします。Happy Coding!