[파이썬 크롤링/부동산 데이터] scrapy를 이용한 부동산 공공 데이터 저장하기(csv/excel)

2021. 3. 28. 02:51 Python/파이썬 웹 크롤링

| 들어가기 전에

 

GIT 저장소

 

지금 포스팅은 국토교통부에서 제공하는 부동산 공공데이터 API를 사용합니다. 아래 포스팅을 보시고 먼저 부동산 공공데이터 API를 신청해주시길 바래요!

 

[기타 정보/ETC] - 국토교통부 공공데이터 부동산 실거래가 API 신청 방법

 

 

이전 포스팅

 

[Python/파이썬 웹 크롤링] - [파이썬 크롤링/부동산 데이터] 스크래피(scrapy) startproject로 초기 프로젝트 구성하기

[Python/파이썬 웹 크롤링] - [파이썬 크롤링/부동산 데이터] scrapy를 이용한 부동산 공공 데이터 간단하게 받아오기

[Python/파이썬 웹 크롤링] - [파이썬 크롤링/부동산 데이터] scrapy를 이용한 부동산 공공 데이터 파싱 및 추출하기

 

포스팅에 있는 내용을 따라하기 위해서는 pandas 패키지를 설치해야합니다. pandas는 파이썬에서 사용하는 데이터분석 라이브러리로, 행과 열로 이루어진 데이터 객체를 만들어 다룰 수 있게 되며 보다 안정적으로 대용량의 데이터들을 처리하는데 매우 편리한 도구 입니다. 

 

 pandas의 DataFrame 자료구조를 이용해서 파이썬의 객체들을 csv파일 혹은 excel 파일로 쉽게 저장할 수 있습니다. 또한 DataFrame을 통해 excel 파일로 데이터를 저장하기 위한 엔진이 필요한데, 이를 위해서 xlsxwriter 패키지도 같이 설치해줘야 합니다.

 

pip install pandas xlsxwriter

 

 

|  Pandas를 이용해서 공공데이터를 csv, excel 형태로 저장하기

 

 

프로젝트 구조

|   scrapy.cfg
\---invest_crawler
    |   consts.py
    |   settings.py
    |   __init__.py
    |
    +---items
    |   |   apt_trade.py
    |   |   __init__.py
    |
    +---spiders
    |   |   apt_trade_spiders.py
    |   |   __init__.py

 

소스 코드

 

consts.py

# 샘플 더미 데이터 입니다. 어떻게 세팅하는 지 보여드리기 위해 넣은 데이터이기 때문에 그대로 사용하시면 에러가 납니다.

# 샘플 더미 데이터 입니다. 어떻게 세팅하는 지 보여드리기 위해 넣은 데이터이기 때문에 그대로 사용하시면 에러가 납니다.
APT_DETAIL_ENDPOINT = "http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade?serviceKey=asdsdfsdfWiZGAJkCsr3wM0YkDO%2BssYpNXZ%2FEWZfuIW5k%2FcHFtD5k1zcCVasdfEtBQID5rIcjXsg%3D%3D&"

 

apt_trade.py

import scrapy


class AptTradeScrapy(scrapy.Item):

    apt_name = scrapy.Field()
    address_1 = scrapy.Field()
    address_2 = scrapy.Field()
    address_3 = scrapy.Field()
    address_4 = scrapy.Field()
    address = scrapy.Field()
    age = scrapy.Field()
    level = scrapy.Field()
    available_space = scrapy.Field()
    trade_date = scrapy.Field()
    trade_amount = scrapy.Field()

    def to_dict(self):
        return {
            '아파트': self['apt_name'],
            '시/도': self['address_1'],
            '군/구': self['address_2'],
            '동/읍/면': self['address_3'],
            '번지': self['address_4'],
            '전체주소': self['address'],
            '연식': self['age'],
            '층': self['level'],
            '면적': self['available_space'],
            '거래일자': self['trade_date'],
            '매매가격': self['trade_amount']
        }
  • to_dict 메서드를 AptTradeScrapy item에 추가하였습니다. 이 메서드를 작성한 목적은 pandas에서 지원하는 DataFrame 자료구조로 item을 쉽게 변환하기 위해 추가한 것입니다. 
  • 여기서 조금 헷갈리실 수 있는 부분은 to_dict에서 self 키워드일 것입니다. 이 self 키워드는 객체 자기자신을 나타냅니다. scrapy에서 item의 속성값은 [ ] 같이 대괄호를 통해 접근할 수 있습니다. 따라서 자기자신을 나타내는 키워드인 self에 [ ] 안에 속성명을 집어넣어 데이터를 구성하는 것입니다.  

 

 

apt_trade_spiders.py

import datetime as dt
from urllib.parse import urlencode

import scrapy
from scrapy import Selector

import invest_crawler.consts as CONST
from invest_crawler.items.apt_trade import AptTradeScrapy

import pandas as pd


class TradeSpider(scrapy.spiders.XMLFeedSpider):
    name = 'trade'

    def start_requests(self):
        page_num = 1
        date = dt.datetime(2006, 1, 1)
        urls = [
            CONST.APT_DETAIL_ENDPOINT
        ]
        params = {
            "pageNo": str(page_num),
            "numOfRows": "999",
            "LAWD_CD": "44133",
            "DEAL_YMD": date.strftime("%Y%m"),
        }
        for url in urls:
            url += urlencode(params)
            yield scrapy.Request(url=url)

    def parse(self, response):
        selector = Selector(response, type='xml')
        items = selector.xpath('//%s' % self.itertag)  # self.intertag는 기본적으로 item으로 되어 있음

        apt_trades = [self.parse_item(item) for item in items]
        apt_dataframe = pd.DataFrame.from_records([apt_trade.to_dict() for apt_trade in apt_trades])

        writer = pd.ExcelWriter('APT_TRADE.xlsx', engine='xlsxwriter')
        apt_dataframe.to_excel(writer, sheet_name='Cheonan', index=False)
        writer.save()

    def parse_item(self, item):
        state = "천안시"
        district = "서북구"

        try:
            apt_trade_data = AptTradeScrapy(
                apt_name=item.xpath("./아파트/text()").get(),
                address_1=state,
                address_2=district,
                address_3=item.xpath("./법정동/text()").get().strip(),
                address_4=item.xpath("./지번/text()").get(),
                address=state + " " + district + " " + item.xpath("./법정동/text()").get().strip() + " " +
                        item.xpath("./지번/text()").get(),
                age=item.xpath("./건축년도/text()").get(),
                level=item.xpath("./층/text()").get(),
                available_space=item.xpath("./전용면적/text()").get(),
                trade_date=item.xpath("./년/text()").get() + "/" +
                           item.xpath("./월/text()").get() + "/" +
                           item.xpath("./일/text()").get(),
                trade_amount=item.xpath("./거래금액/text()").get().strip().replace(',', ''),
            )

        except Exception as e:
            print(e)
            self.logger.error(item)
            self.logger.error(item.xpath("./아파트/text()").get())

        return apt_trade_data
  • 아래 코드에서는 파이썬의 LC(List Comprehension)을 통해 파이썬의 리스트에 담길 item들을 손쉽게 구성하는 것을 볼 수 있습니다.
apt_trades = [self.parse_item(item) for item in items]
  • 또한 위에서 정의해둔 to_dict 메서드를 통해 파이썬 객체 리스트를 손쉽게 pandas에서 제공하는 DataFrame 자료구조로 변환하는 모습입니다.
apt_dataframe = pd.DataFrame.from_records([apt_trade.to_dict() for apt_trade in apt_trades])
  • DataFrame으로 자료를 구성했다면 DataFrame에서 제공하는 저장기능으로 csv 혹은 excel 파일 형식으로 손쉽게 저장할 수 있습니다. 저장하는 코드는 아래와 같습니다. 파일 이름과 sheet_name을 지정하는 것을 눈여겨 봐주셔야 합니다.
writer = pd.ExcelWriter('APT_TRADE.xlsx', engine='xlsxwriter')
apt_dataframe.to_excel(writer, sheet_name='Cheonan', index=False)
writer.save()

 

 

결과 화면

 

 

 

다음 포스팅에는 scrapy를 통해 공공데이터를 어떻게 연속적으로 쉽게 가져올 수 있을 지를 보겠습니다.



출처: https://engkimbs.tistory.com/964?category=807933 [새로비]