인프런 커뮤니티 질문&답변

최진환님의 프로필 이미지

작성한 질문수

내 업무를 대신 할 파이썬(Python) 웹크롤링 & 자동화 (feat. 주식, 부동산 데이터 / 인스타그램)

17.1 Wrap-up

드디어 강의 정독 2번째 했네요

22.05.25 14:13 작성

·

211

0

안녕하세요 선생님

근 1개월 동안 파이썬 기초 부터 크롤링 까지 공부를 계속하면서 공부했습니다 

 

그래서 우선부동산 데이터 크롤링 하는것부터 하고 있는데요 

 대구 / 경북 지역의 부동산 단지정보를 수집하자 라는 목표로 우선 프로그램을 짜고 있습니다. 

네이버 부동산의경우 해당 지역 대구시 > 남구 > 대명동 일경우 타 동의 정보도 화면에 노출되어 타 동의 단지정보도 같이 나타나게 되는것을 확인하였습니다 .

 

그래서 작업방식은  단지정보 수집을 위한 코드 값은  모바일 m.land.naver.com에서 수집하고  이때 수집된 단지 정보로 상세정보를 수집하기로 하였습니다 

우선 단지정보수집을 위해서 아래와 같이 코드를 작성하였는데요 for문에서  오류가 발생하네요 

기초정보를 출력하는 코드들은 수업에서 배운내용으로 테스트가 끝난 상태입니다 

아래 코드에서 발행하는 문제에 대해서 조언을 부탁드리겠습니다 

%matplotlib inline

from IPython.core.interactiveshell import InteractiveShell

InteractiveShell.ast_node_interactivity = "all"

import pandas as pd

pd.set_option('display.float_format', lambda x: '%.3f' % x)    

pd.set_option('max_columns', None) 

import requests

import bs4

import time

import numpy as np

from datetime import datetime

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("https://m.land.naver.com")

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

headers = {

    "Connection": "keep-alive",

    "Host": "m.land.naver.com",

    "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IlJFQUxFU1RBVEUiLCJpYXQiOjE2MjMyMzkyMzksImV4cCI6MTYyMzI1MDAzOX0.gdgEApo9bDG5IsSsYDWWeHlAN9LtNh6ejEARMS0FGL8",

    "Referer": "Referer: https://m.land.naver.com/",

    "Sec-Fetch-Dest": "empty",

    "Sec-Fetch-Mode": "cors",

    "Sec-Fetch-Site": "same-origin",

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36",

}

comid = 2700000000  #대구광역시 코드 

mycomid = 2700000000

url = "https://m.land.naver.com/map/getRegionList?cortarNo={}&mycortarNo={}".format(comid,mycomid)

res_reg = requests.get(url, headers=headers)

print(res_reg)

data_dict =  res_reg.json()

data_dict  #데이터 확인하기 

region_list_df = pd.Series(data_dict['result']).to_frame().T

region_list_df #내부에 파일이 묶여져 있어서 리스트만 뽑아올 필요가 있다

region_list_df['list']

nested_df1 = pd.DataFrame(region_list_df['list'].iloc[0]) 

nested_df1 #내부에 있는 데이터만 뽑아서 확인하기 

cartNuns = nested_df1['CortarNo']

nested_list = list(cartNuns) #아파트코드만 뽑아오기


----------------------

for i in nested_list:

    comid_st = i

    url = "https://m.land.naver.com/map/getRegionList?cortarNo={}".format(comid_st)

    res_reg = requests.get(url, headers=headers)

    data_dict = res_reg.json()

    region_list_df = pd.Series(data_dict['result']).to_frame().T

    nested_df1 = pd.DataFrame(region_list_df['list'].iloc[0])

    nested_df1

요부분이 에러가 나옵니다 

답변 1

0

DeepingSauce님의 프로필 이미지
DeepingSauce
지식공유자

2022. 05. 27. 08:32

안녕하세요!

혹시 에러내용도 첨부가능하실까요?

최진환님의 프로필 이미지
최진환
질문자

2022. 06. 04. 17:40

안녕하세요

고민고민하다 질문드려요 

우선은  자동화까지는 아니지만 지역코드를 뽑아서 아파트 코드는 뽑아 내었습니다. 그리고 엑셀로  정리는 했습니다.   그러나 조금 아쉬운건 이것도 데이터를 뽑아올 떄 자동화 할수 있으면 좋을꺼 같아서  질의 드리구요 

그리고 뽑아온 아파트 단지 코드가 4000여개 정도 되는데요. 이 데이터를 뽑아서 출력할떄  KEY 에러가 발생합니다 . 

해당 키 에러가 발생하는경우를 분석을 해보 았을떄  landPriceMaxByPtp   의 값이 있는데 첫번쨰 값이 없을경우 혹은 complex_detail_list_df['landPriceMaxByPtp'].values.tolist() 명령어를 제대로 수행하지 못했을경우에 에러가 나오는 것을 확인하였습니다

이럴때 대처방안이 있을지 궁금합니다.

 

첫번쨰 질문인 지역코드 뽑아오기자동화 방법 소스

%matplotlib inline from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity = "all" import pandas as pd pd.set_option('display.float_format', lambda x: '%.3f' % x) pd.set_option('max_columns', None) import requests import bs4 import time import numpy as np from datetime import datetime from selenium import webdriver driver = webdriver.Chrome() driver.get("https://m.land.naver.com") from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import csv import pymysql

headers = { "Connection": "keep-alive", "Host": "m.land.naver.com", "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IlJFQUxFU1RBVEUiLCJpYXQiOjE2MjMyMzkyMzksImV4cCI6MTYyMzI1MDAzOX0.gdgEApo9bDG5IsSsYDWWeHlAN9LtNh6ejEARMS0FGL8", "Referer": "Referer: https://m.land.naver.com/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", }

for comid in [4700000000, 2700000000]: url = "https://m.land.naver.com/map/getRegionList?cortarNo={}".format(comid) res_reg = requests.get(url, headers=headers) data_dict = res_reg.json() region_list_df = pd.Series(data_dict['result']).to_frame().T nested_df1 = pd.DataFrame(region_list_df['list'].iloc[0]) nested_df1 cartNuns = nested_df1['CortarNo'] nestedlst = list(cartNuns) last_nestlist = len(nestedlst) nestedlst time.sleep(2) for sicomid in nestedlst: urls = "https://m.land.naver.com/map/getRegionList?cortarNo={}".format(sicomid) res_regs = requests.get(urls, headers=headers) data_dicts = res_regs.json() region_lists_df = pd.Series(data_dicts['result']).to_frame().T nested_dfs = pd.DataFrame(region_lists_df['list'].iloc[0]) nested_dfs time.sleep(5)

대구 / 경북 지역에 대한 시 구 읍면동 지역 코드 뽑아오기 여기서 아래과 같이 한번에 아파트코드값을 한번에 뽑아오고 정렬을 하려 햇으나 오류가 나서 실패, 우선은 지역코드값을을 수기로 넣고 for문으로 데이터를 뽑아온후 화면 드래그 해서 엑셀로 정리 했습니다 .

그러나 한번에 데이터를 뽑아오고 엑셀 export 혹은 db insert 하는 방법이 궁긍합니다

 

아래는 실패한 코드 입니다

data_dict = res_reg.json() region_list_df = pd.Series(data_dict['result']).to_frame().T region_list_df['list'] nested_df1 = pd.DataFrame(region_list_df['list'].iloc[0]) cartNuns = nested_df1['CortarNo'] nestedlst = list(cartNuns) last_nestlist = len(nestedlst) for i in nestedlst: comid_st = i url = "https://m.land.naver.com/map/getRegionList?cortarNo={}".format(comid_st) res_reg = requests.get(url, headers=headers) data_dict = res_reg.json() region_list_df = pd.Series(data_dict['result']).to_frame().T region_list_df nested_dfi = pd.DataFrame(region_list_df['list'].iloc[0]) nested_dfi nested_cartNuns = nested_dfi['CortarNo'] aptlst = nested_cartNuns for k in aptlst: url_apt = "https://m.land.naver.com/complex/ajax/complexListByCortarNo?cortarNo={}".format(aptlst) res_apt = requests.get(url_apt, headers=headers) data_dict = res_apt.json() data_dict apt_list_df = pd.DataFrame(data_dict['result']) apt_list_df

 

두번째 질문 에러 코드 질의 ( 아파트 단지 정보 가져오기 )

complex_id_list = [114164,4021,108057,139497,148379,4023,14530,130068,25022,124799,140518,111416,104342,15357,110539,13765,15371,121379,108601,143190,107408,121763,128083,133264,4027,109432,116364,116363,4025,16975,109388,112475,102232,119539,4028,4029,10184,115580,115578,127222,4030,140629,110189,118560,107778,102962,128220,128221,137349,4033,18275,121541,16976,144257,132686,132687,111999,4034,115507,115508,119613,119612,116829,116827,1] len(complex_id_list)

#단지정보는 위에서 추출한 아파트 코드를 리스트로 직접입력

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Input In [31], in <cell line: 2>()
     12 if "landPriceMaxByPtp" in complex_detail_list_df.columns:
     13     nested_df1 = pd.DataFrame(complex_detail_list_df['landPriceMaxByPtp'].values.tolist())
---> 14     nested_df2 = pd.DataFrame(nested_df1['landPriceTax'].values.tolist())
     16     nested_df1 = pd.concat(
     17         [
     18             nested_df1.drop("landPriceTax", axis=1),
   (...)
     21         axis=1
     22     )
     23     complex_detail_list_df = pd.concat(
     24         [
     25             complex_detail_list_df.drop(["supplyArea", "landPriceMaxByPtp"], axis=1),
   (...)
     28         axis=1
     29     )

File C:\ProgramData\Anaconda3\envs\nland\lib\site-packages\pandas\core\frame.py:3024, in DataFrame.__getitem__(self, key)
   3022 if self.columns.nlevels > 1:
   3023     return self._getitem_multilevel(key)
-> 3024 indexer = self.columns.get_loc(key)
   3025 if is_integer(indexer):
   3026     indexer = [indexer]

File C:\ProgramData\Anaconda3\envs\nland\lib\site-packages\pandas\core\indexes\range.py:354, in RangeIndex.get_loc(self, key, method, tolerance)
    352         except ValueError as err:
    353             raise KeyError(key) from err
--> 354     raise KeyError(key)
    355 return super().get_loc(key, method=method, tolerance=tolerance)

KeyError: 'landPriceTax'

에러코드

세번째 질문 데이터에 대한 excel export 혹은 데이터 베이스 저장방법

데이터를 추출할경우 엑셀 export로 추출하거나 혹은 db저장할경우 데이터가 한줄찍 insert되는지궁금합니다 

 

위의 테이블정보에 맞게 db스키마는 짜둔상태입니다 

 

 

 

 

 

DeepingSauce님의 프로필 이미지
DeepingSauce
지식공유자

2022. 06. 05. 22:59

안녕하세요!

고민의 흔적이 많이 보이는 질문이네요 : )

하지만 올려주신 코드가 지금 다 한줄로 입력이 되어서 제가 제대로 판단하기 어려운 상태입니다.

혹시 괜찮으시다면 github의 gist나 notion 등으로 따로 작성해서 링크로 전달해주실 수 있으신가요?

그리고 각 코드 snippet은 제가 jupyter에서 그대로 복사해서 붙여넣고 실행했을 때,

1. 동작이 되고

2. error나 결과값 등이 reproduce 가능한 형태

면 좋을 듯합니다.

 

3번째 질문에 대한 답변은 지금 드릴 수 있을 것 같은데요.

데이터 한줄씩 insert도 가능합니다. 다만 db등에서는 효율성을 높이기 위해 bulk insert 기능을 많이 사용하고, excel에 저장하는 경우는 excel의 sheet내에 있는 cell을 조작할 수 있는 라이브러리가 있는데 그걸 사용하시면 될것같아요(근데 한줄씩 입력해야하는 이유가 반드시 필요한게 아니라면 엑셀도 저장하는 시간(hourly, daily 등) 기준으로 주기적으로 저장하는 것을 구너장드립니다.)