プロジェクトの背景
新築マンションのデータは、不動産購入者にとっては購入判断の重要な参考資料となり、開発者にとっては競合プロジェクト分析のツールとしても役立ちます。また、不動産エージェントにとっては物件調査前の準備情報としても重要です。
今回は惠民之家を例に、Pythonを用いて惠州の新築マンションデータを一括収集する方法をご紹介します。収集したデータは、物件名、販売価格、主力間取り、発売日、容積率、緑化率を含む41の項目あります。
収集したデータは以下の形式で確認できます。
記事の最後に収集に使用したソースコードをダウンロード可能です。
プロジェクトの目的
惠民之家のホームページURL:
http://www.fz0752.com/
新築マンション一覧URL:
http://www.fz0752.com/project/list.shtml
一覧から任意の物件をクリックし詳細情報を確認できます。
プロジェクトの準備
- ソフトウェア: PyCharm
- 外部ライブラリ: requests, fake_useragent, lxml
- サイトURL: http://www.fz0752.com/
Webページ分析
一覧ページの分析
新築マンション一覧ページを開くと、次へをクリックするとURLが以下のように変化します。
http://www.fz0752.com/project/list.shtml?state=&key=&qy=&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO=2
URLのパラメータpageNOがページ番号を表し、qyがエリアIDを表しています。エリアIDとページ番号を組み合わせることで、全ての物件のURLを収集可能です。
詳細ページの分析
物件の詳細ページURL例:
http://newhouse.fz0752.com/fontHtml/html/project/00020170060.html
URL内の00020170060が物件IDです。詳細ページのURLは以下のように生成されます。
http://newhouse.fz0752.com/project/detail.shtml?num=20170060
このIDは元のURLから抽出可能であることが確認できます。
反スクラッチ対策
同一IPアドレスからの繰り返しリクエストはサイトのIPブロックのリスクがあります。本記事ではfake_useragentを使用し、ランダムなUser-Agentヘッダーを生成することでリスクを軽減します。
コードの実装
スクラッチに必要なライブラリをインポートし、エリアIDとページ番号を組み合わせてURLを生成します。エリアIDを指定し、ページ番号を1から50までループさせます。
# -*- coding: utf-8 -*-
import csv
import time
import random
import requests
import traceback
from lxml import etree
from fake_useragent import UserAgent
def main():
# 46:惠城区,47:仲恺区,171:惠阳区,172:大亚湾,173:博罗县,174:惠东县,175:龙门县
region_ids = [46,47,171,172,173,174,175]
for region in region_ids:
for page in range(1,50):
url = f'http://www.fz0752.com/project/list.shtml?state=&key=&qy={region}&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO={page}'
response = requests.request("GET", url, headers=headers, timeout=5)
print(response.status_code)
if response.status_code == 200:
content = response.content.decode('utf-8')
print(f"正在解析エリアID {region} のページ {page}")
print("-" * 80)
parser = etree.HTML(content)
extract_detailed_urls(parser, region)
# 終了条件のチェック
num = ''.join(parser.xpath('//*[@id="parent-content"]/div/div[6]/div/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/a/@href'))
if len(num) == 0:
break
if __name__ == '__main__':
ua = UserAgent(verify_ssl=False)
headers = {"User-Agent": ua.random}
time.sleep(random.uniform(1, 2))
main()
詳細URLを取得し、各物件の詳細データを収集します。
def extract_detailed_urls(parser, region):
items = parser.xpath('//*[@id="parent-content"]/div/div[6]/div/div[1]/div[2]/div')
try:
for item in items:
initial_url = ''.join(item.xpath('./div[2]/div[1]/div[1]/a/@href')).strip()
print(f"初期URL: {initial_url}")
if len(initial_url) > 25:
detail_url = f'http://newhouse.fz0752.com/project/detail.shtml?num={initial_url[52:].replace(".html","")}'
else:
detail_url = f'http://newhouse.fz0752.com/project/detail.shtml?num={initial_url[15:]}'
print(f"詳細URL: {detail_url}")
try:
fetch_detailed_data(detail_url, region)
except:
pass
except Exception:
print(traceback.print_exc())
詳細ページのデータ収集を行います。
def fetch_detailed_data(detail_url, region):
time.sleep(random.uniform(1, 2))
response = requests.get(detail_url, headers=headers, timeout=5)
if response.status_code == 200:
content = response.text
parser = etree.HTML(content)
# 各項目のデータ収集(一部例示)
try:
status = parser.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/div[1]/text()')[0].strip()
except:
status = None
try:
name = parser.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/h1/text()')[0].strip()
except:
name = None
try:
summary = parser.xpath('//*[@id="parent-content"]/div/div[3]/div[5]/div[2]/div/p[1]/text()')[0].strip()
except:
summary = None
# 他の項目の収集
data = {
'status': status,
'name': name,
'summary': summary,
'region': region
}
print(data)
収集したデータをCSVファイルに保存します。
def save_to_csv(data):
try:
with open('hz_newhouse.csv', 'a', encoding='utf_8_sig', newline='') as file:
fieldnames = ['status','name','summary','region']
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writerow(data)
except Exception:
print(traceback.print_exc())
収集結果の加工
CSVファイルを読み込んで重複を削除し、Excel形式に変換します。
import pandas as pd
df = pd.read_csv("hz_newhouse.csv")
df = df.drop_duplicates()
df.to_excel("hz_newhouse.xlsx", index=False)
プロジェクトの総括
- Pythonのスクラッチ技術を用いて、新築マンションデータの収集を効率的に行いました。
- 収集量を適度に抑え、サイトの負荷を軽減します。