개인(팀) 프로젝트/해상물류 통합 데이터 플랫폼 프로젝트

09. Selenium - 동적 사이트 테이블 Crawling : 오류 해결

한소희DE 2021. 7. 13. 21:54

 

 

 

 

 

목차

Selenium으로 인식되지 않는 text를 print 하는 방법

동적 테이블 값을 Selenium + BeautifulSoup4 로 출력하는 방법


 

 

01. Selenium으로 인식되지 않는 text를 print 하는 방법

나는 이전동안, Selenium을 이용한 동적 사이트 테이블을 크롤링하는 작업을 수행했다.

수행 기록은 아래와 같다.

 

https://eng-sohee.tistory.com/78

 

07. Selenium - 동적 사이트 테이블 Crawling

목차 크롤링 사용 목적 Selenium 구현 과정 01. 크롤링 사용 목적 우리는 동적 페이지 내 데이터를 실시간 수집을 해와야 한다. 대시보드에 실시간으로 데이터를 띄워주어야 하기 때문이다. 따라서

eng-sohee.tistory.com

 

 

그런데 이걸 하면서, 위 포스팅에 작성되어있듯 문제가 발생했다.

바로, Selenium에서 특정 id 내 text 값이 불러와지지 않는다는 것이다...

 

 

노랗게 색칠한 부분을 보면, 똑같이 'find_element_by_id'로 데이터를 가져왔는데도 특정 id는 인식이 안되어 데이터를 못 불러오는 것을 알 수 있다....

 

class와 구조가 동일한데 왜 12번째 id부터는 인식이 안 되는 걸까...? 답답했다. 😵💦

 

 

 

이 문제를 해결하기 위해 이것저것 시도해봤다. 실패한 기록은 다음과 같다.

 

    1. find_element_by_id('아이디명').text
    2. find_element_by_id('아이디명')
    3. find_element_by_class_name('클래스명')
    4. find_elements_by_class_name('클래스명') + list 반환 위해 for loop
    5. find_element_by_xpath('정적 xpath 경로')
    6. find_element_by_xpath('동적 xpath 경로')
    7. table, tbody, tr 경로를 별도로 설정하고 경로 내 모든 td를 출력하도록 for loop
    8. 등등 많은 잡(?)시도.....

 

실패 결과는 모두 어떻게 나왔는가?

(1) 공백
(2) None 출력
(3) [<selenium.webdriver.remote.webelement.Web85915d49d36b6db4d7f54d01fe", element="aa107841-78d")>]

 

 

그래서 계속 실패를 반복하다가, (여기가 이제 포스팅의 결론) 해결방법을 찾았다!

바로 BeautifulSoup4 + Selenium 을 함께 사용하는 것.

 

원래도 이 방법을 처음에 썼었지만, 코드가 복잡해지는 것 같아 Selenium으로 모두 하려고 했는데, 실패했다.

따라서 밑져봤자 본전이라고, Selenium을 통해 동적 페이지를 불러 와서, BeautifulSoup4로 특정 값을 뽑아 오는 것을 재시도해봤다.

 

 

 

코드 시도 결과는 아래와 같다.

 

와 실화인가!!!!! 진짜 실화인가!!!!!! 데이터가 들어온다!!!! 몇 일을 시도했는데.. 이렇게 가까이에 해결 방법이 있었다니 허탈했지만, 이것 저것 삽질한 끝에 해결할 수 있어서 너무 기뻤다 !!! (사실 지금도 기쁘다.)

 

 

🔥 오늘의 배운 점
Selenium 으로 데이터값이 정상적으로 print 되지 않으면, BeautifulSoup4를 이용해 값을 출력하도록 하자.

 

 

이제, 동적 테이블을 반복적으로 스크롤 다운해가며, BeautifulSoup4로 데이터를 print할 수 있도록 수정해보겠다.


 

 

02. 동적 테이블 값을 Selenium + BeautifulSoup4 로 출력하는 방법

 

중복이 되어도 딕셔너리는 단일키만 들어가기 때문에 괜찮다. 즉 멱등하게 처리할 수 있다. 따라서 딕셔너리형태로 바꿔주었다. 

 

# 마지막 페이지 테이블 데이터 집계 
def tail_value():
        for i in range(0,22):
            save_value = {}
            try:
                for k in range(0,1):
                    value = soup.select_one('#mf_tacMain_contents_M1554_body_grpSrchList_cell_{}_{} > nobr'.format(i, k)).text
                    save_value.setdefault('key_{}'.format(k), value)
                # print(save_value)
                save_dict['n_{}_{}'.format(datetime.datetime.now().strftime("%Y%m%d"), save_value['key_0'])] = save_value
            except AttributeError:
                break



# 데이터 수집
for _ in range(0,10000):
    btn.send_keys(Keys.DOWN)
    save_value = {}
    for k in range(0,22):
        # 해당 페이지의 전체 html 소스를 string 형태로 답기 위해 html 저장 + 스크롤 다운한 화면을 동적화
        html = driver.page_source
        soup = BeautifulSoup(html, 'html.parser')
        value = soup.select_one('#mf_tacMain_contents_M1554_body_grpSrchList_cell_{}_{} > nobr'.format(0, k)).text
        # 키값이 없으면 키값에 0을 넣고 만약 있으면 키값을 반환
        save_value.setdefault('key_{}'.format(k), value)
        # print(value)
    print(save_dict)
    
    if 'n_{}_{}'.format(datetime.datetime.now().strftime("%Y%m%d"), save_value['key_0']) in save_dict:
        cnt += 1
    if cnt > 15:
        tail_value()
        break

    save_dict['n_{}_{}'.format(datetime.datetime.now().strftime("%Y%m%d"), save_value['key_0'])] = save_value