728x90
반응형

목표 물건

  우선 본인이 원하는 물건을 기준으로 프로그램 구현 목표했다. (다 먹고 살자고 하는...) 큰 범위에서 인서울, 역세권, 300세대 이상을 기준으로 삼았다.본 게시글을 참고하나 다른 조건을 원하는 사람은 일부 조건만 수정하면 가능하다.

  추가로 이전 게시글에서 설명한 코드 블럭은 설명을 덧붙이지 않을 예정이다. 블럭 단위로 방법을 설명하고자 하며 import 는 따로 추가하지 않을 예정이다. Bot 차단 방지 위해 time.sleep을 중간 중간 추가 필요하나, 코드 블럭에는 추가해두지 않았다.

Chorme 실행

driverCourt = webdriver.Chrome()
driverCourt.get('법원 경매 SITE URL')

main = driverCourt.window_handles
for i, x in enumerate(main):
    if i != 0:
        driverCourt.switch_to.window(x)
        driverCourt.close() 
driverCourt.switch_to.window(main[0])

  이전 게시글에서 설명한 사이트 접속 및 팝업 종료 블럭이다.법원 경매 사이트에 접속한다. 정상적으로 접속하면 크롬 상단에 "Chorme이 자동화된 테스트 소프트웨어에 의해 제어되고 있습니다." 라고 알람이 떠있다.

법원 캡처 화면

물건 조건 설정

# 물건상세검색 버튼 클릭
driverCourt.find_element(By.XPATH, '버튼 XPATH 붙혀넣기').click()

# 법원 지정
setCourt = Select(driverCourt.find_element(By.ID, 'idJiwonNm'))
setCourt.select_by_value('서울중앙지방법원')
# 아파트 지정
setAPT = Select(driverCourt.find_element(By.NAME, 'lclsUtilCd'))
setAPT.select_by_value("0000802")
setAPT = Select(driverCourt.find_element(By.NAME, 'mclsUtilCd'))
setAPT.select_by_value("000080201")
setAPT = Select(driverCourt.find_element(By.NAME, 'sclsUtilCd'))
setAPT.select_by_value("00008020104")
# 날짜 지정
time_textbox = driverCourt.find_element(By.NAME, 'termStartDt')
time_textbox.clear()
time_textbox.send_keys("value", '2024.05.21')
time_textbox = driverCourt.find_element(By.NAME, 'termEndDt')
time_textbox.clear()
time_textbox.send_keys("value", '2024.05.28')
# 검색 후 페이지 이동 대기
driverCourt.find_element(By.XPATH, '검색 XPATH 붙혀넣기').click()

  법원 메인 사이트에서 "물건 상세 검색"으로 이동 후, 원하는 조건 입력 후 검색 클릭한다.

  • 버튼 클릭은 webelement의 click으로 가능하다. 종종 화면에 보이지 않아 클릭되지 않는 경우가 있는데, 이후 게시물에서 해결방법 추가 예정이다.
  • Select을 통해 Dropdown 제어한다.
  • 날짜 지정 가능한 textbox는 clear하지 않으면 기존 text + 입력 text로 text가 설정된다. clear 후 send_keys를 해야한다.

  아래 이미지와 같은 순으로 진행된다.

법원 경매 - 물건 상세 검색 이동 방법

 

728x90
반응형

물건 리스트 화면 설정

if driverCourt.find_elements(By.ID, 'ipage'): # 페이지 당 10개씩 변경
    setPage = Select(driverCourt.find_element(By.ID, 'ipage'))
    setPage.select_by_value("default10")
else: # 이전 page 돌아가기 클릭
    driverCourt.find_element(By.XPATH, '이전 button XPATH 입력').click()
    continue

  한번에 너무 많은 물건이 있는 경우 전부 안불러와지는 경우가 존재한다. 따라서 최소 개수로 페이지당 물건 수 설정한다.이 과정에서 검색 조건에 만약 물건이 한 개도 없다면 페이지 당 물건 수 Dropdown 메뉴가 없다. 이를 이용하여, 물건이 없으면 바로 이전 page로 돌아가고, 존재하면 물건 수를 설정하게 한다. 각 case 별 예시 화면은 아래 이미지와 같다.

법원 물건 예시
(좌) 검색 조건에 물건이 존재하는 경우 / (우) 물건이 존재하지 않는 경우

Table 저장

soup = BeautifulSoup(driverCourt.page_source,'html.parser')
table = soup.find('table', attrs={'class':'Ltbl_list'})
table_rows = table.find_all('tr')
row_list = []
for tr in table_rows:
    td = tr.find_all('td')
    row = [tr.text for tr in td]
    row_list.append(row)
aution_item = pd.DataFrame(row_list).iloc[1:] # 첫번째는 name row로 불필요한 정보로 제외

  Selenium은 페이지를 동적으로 제어하는 패키지다. (페이지 이동, 텍스트 입력, 스크롤 이동 등등...)Data를 가져오는 경우 정적인 BeautifulSoup4를 사용한다. 경매 물건이 존재하는 경우 bs4로 html을 파싱한 후 한 row씩 + row에서도 한 col 씩 list에 저장 후 이를 df로 저장한다. 아래는 예시 df. html 언어는 마지막에 일괄 처리 예정이다.

저장한 법원 물건 예시

다음 페이지로 넘어가기

page = 1 # 현재 페이지

while True:
    # table 저장 코드
    
    # 다음 페이지로 이동
    page2parent = driverCourt.find_element(By.CLASS_NAME, 'page2')
    children = page2parent.find_elements(By.XPATH, '*') # 모든 child 요소를 가져옴
    if page == 1:# 첫 페이지 에서
        if len(children) == page: break # page가 1개 밖에 없을때 종료
        else: children[page].click() # 다음 page open
    elif page <= 10: # 처음 10 page
        if len(children) - 1 == page: break # 이동 키 포함 마지막 page일 경우 종료
        else: children[page+1].click()
    else: # 나머지
        if len(children) - 2 == (page % 10): break # 이동 키 포함 마지막 page일 경우 종료
        else: children[(page % 10) + 2].click()
    page += 1 # 다음 페이지 이동
    
# 이전 page 돌아가기 클릭
driverCourt.find_element(By.XPATH, '이전 버튼 XPATH 입력').click()

  10개 이상의 물건이 있는 조건이면 여러 페이지를 이동하며 table을 저장해야한다. 페이지 가장 하단에 있는 페이지 이동 요소에서 존재하는 요소 개수로 이동 필요 여부 및 다음 페이지 이동 실행한다. 아래와 같은 규칙으로 판단하며, 모든 페이지 탐색 후 이전 버튼을 통해 조건 설정 페이지로 이동한다.

  1. page = 1
    1. child 개수가 1개면 마지막이므로 이전 페이지 이동 (물건 개수 10개 이하)
    2. 나머지는 다음 페이지로 이동
  2. page <= 10
    1. child 개수가 '현 페이지-1' 이면 마지막이므로 이전 페이지 이동 (가장 왼쪽에 추가되는 '<<' 버튼 포함 계산)
    2. 나머지는 다음 페이지 이동
    3. 나머지는 다음 페이지로 이동
  3. 나머지
    1. page가 10이 넘어가므로 10으로 나눈 나머지로 인덱스 계산. 왼쪽에 버튼이 2개라 - 2로 마지막 페이지 여부 판단.
    2. 나머지는 다음 페이지 이동.
    3. 나머지는 다음 페이지로 이동

페이지 이동 규칙

 

HTML 형식 제거

aution_item = aution_item.iloc[:,1:] # 첫 번째 선택 column은 불필요
col_list = ['사건번호','물건번호','소재지','비고','감정평가액','날짜']
aution_item.columns = col_list # col 지정
for col in col_list: # \t는 전부 제거
    aution_item[col] = aution_item[col].str.replace('\t','')
    
for col in col_list: # 겹치는 \n는 하나로
    aution_item[col] = aution_item[col].apply(lambda x : re.sub(r"\n+", "\n", x))

aution_item['법원'] = aution_item['사건번호'].str.split('\n').str[1]
aution_item['사건번호'] = aution_item['사건번호'].str.split('\n').str[2]
aution_item['용도'] = aution_item['물건번호'].str.split('\n').str[2]
aution_item['물건번호'] = aution_item['물건번호'].str.split('\n').str[1]
aution_item['내역'] = aution_item['소재지'].str.split('\n').str[2:].str.join(' ')
aution_item['소재지'] = aution_item['소재지'].str.split('\n').str[1]
aution_item['비고'] = aution_item['비고'].str.split('\n').str[1]
aution_item['최저가격'] = aution_item['감정평가액'].str.split('\n').str[2]
aution_item['최저비율'] = aution_item['감정평가액'].str.split('\n').str[3].str[1:-1] # 괄호 삭제
aution_item['감정평가액'] = aution_item['감정평가액'].str.split('\n').str[1]
aution_item['유찰횟수'] = aution_item['날짜'].str.split('\n').str[3]
aution_item['유찰횟수'] = aution_item['유찰횟수'].str.strip()
aution_item['유찰횟수'] = np.where(aution_item['유찰횟수'].str.len() == 0, '0회', aution_item['유찰횟수'].str.slice(start=2))
aution_item['날짜'] = aution_item['날짜'].str.split('\n').str[2]
aution_item = aution_item[['날짜','법원','사건번호','물건번호','용도','감정평가액','최저가격','최저비율','유찰횟수','소재지','내역','비고']]
aution_item = aution_item[~aution_item['비고'].str.contains('지분매각')].reset_index(drop=True)

  html 형식으로 저장된 정보들을 전처리 하여 원하는 table 형태로 가공한다. 중간 중간 print(aution_item) 을 직접 추가하여 어떤 방식으로 동작하는지 확인 가능하다. 이후 세부 검색 시 활용을 위해중복되는 사건번호의 경우 가장 빠른 사건 번호로 저장되게 한다.

html 형식 제거
빨간 박스가 개별 column

 

이후 목표

  1. 가장 가까운 지하철 역과 직선 거리 및 도보 이동 거리 정보 추가 예정이다.
  2. 연차, 세대수 등 정보 추가. 원하는 조건의 아파트 필터링한다.
  3. 세부 조건 추가 스크래핑한다.
728x90
반응형

+ Recent posts