NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 팁 앤 테크
  • 매뉴얼

    팁과 테크니컬 노하우를 확인하세요.

    팁 앤 테크

    팁과 테크니컬 노하우를 확인하세요.

    본 사이트의 컨텐츠는 저작권법의 보호를 받으므로 무단 복사, 게재, 배포 등을 금합니다.

    에디터 웹크롤링 매크로 - KB차차차에서 중고차 매물 정보 가져오기.

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 웹크롤링 연재글의 마지막이 될거 같네요. [ 1부 - 네이버 연관 검색어 가지오기 ]와 [ 2부 - 영어 단어를 입력하면 자동으로 해석해주는 매크로 만들기 ] 예제를 모두 경험 해보시면 이번 예제도 그리 어렵지 않게 해낼 수 있을겁니다. 참고로, 네이버나 구글과 같은 사이트들은 공식 인터페이스 형식(Format)인 Json을 사용하여 데이타를 주고 받습니다. 그런데, KB차차차는 이상하게도 비표준 형태로 서버와 데이타를 주고 받더라구요. 그래서, 이런 경우에는 어떻게 데이타를 파싱해서 추출해야 하는지도 알아볼께요. 자~ 이 테스트를 위해 [ 엔지엠 RPA 매크로 에디터 ]를 실행하고, 새로운 스크립트를 추가하세요.

    cnOuw3h.gif

     

     

    Json이란?

    JavaScript Object Notation의 줄임말로 데이타를 구조적으로 표현하는 일종의 포멧을 말합니다. 원래는 Xml을 주로 사용했었는데요. Xml은 불필요한 정보들이 너무 많아서 서버와 클라이언트간 통신에 많은 네트워크 트레픽을 발생시킨다는 단점이 있었습니다. 그래서, 등장한게 Json입니다. Json 형식은 JavaScript 객체의 형식을 기반으로 만들었기 때문에 누구나 쉽게 코드를 이해할 수 있습니다. 또한, 거의 모든 프로그래밍 언어들이 Json 포멧을 핸들링할 수 있게 지원하고 있습니다. Json은 특정 언어에 종속되지 않아서 자유롭게 사용이 가능하고, Xml보다 작은 용량으로 데이타 전송이 가능합니다. 필요한 정보만 전달하기 때문에 가독성이 좋습니다.

     

    앞서 설명했던 예제들과 동일하게 구글 크롬을 실행하고, [ KB차차차 중고차 검색하고 비교하기 ] 페이지로 이동해줍니다. 그리고, F12를 눌러서 구글 크롬 개발자 도구를 실행해주세요. 아래 동영상과 같이 중고차를 검색하면 서버로부터 데이타를 받아올 수 있습니다. 검색어에 "bmw"를 입력하면, 관련 매물들의 목록을 가져올 수 있습니다. 요청(Request)에서 마지막을 클릭한 후 응답(Response) 탭을 클릭 해보세요.

     

     

    일반적으로 사용하는 Json이 아닌 Html 문서가 날라옵니다. 아마도, 매물 정보 관련 Html 코드를 데이타베이스에 그대로 넣어놓은게 아닌가 생각되네요. 데이타베이스에 키워드로 질의(Query)하면 목록을 가공하지 않고 그대로 내려주는거 같습니다. 웹크롤링 1부와 2부를 모두 읽어보시고, 예제를 따라 해보신 분들은 서버로부터 받은 데이타를 어떻게 처리해야 할지 이미 알고 계실겁니다. KB차차차 중고차 매물 정보는 아래와 같이 응답을 보내줬습니다. 내용이 많아서 일부 내용은 삭제 했습니다^^

    <div class="ds-scroll">
        <div>
            <div class="cmm-justify">
                <span class="keyword">5시리즈</span>
                <button type="button" class="link-arrow" onclick="(function() {
    				kbcStorage.recentSearchKeyword.push({
    					'target' : 'result'
    					, 'makerCode' : '107'
    					, 'makerName' : 'BMW'
    					, 'classCode' : '1904'
    					, 'className' : '5시리즈'
    				}).then(function() {
    					location.href = '/public/search/main.kbc#!?makerCode=107&classCode=1904';
    					$('#ks-mask').click();
    					$('#ks-input').val('5시리즈');
    					window.scrollTo(0,0);
    				});
    			})();">
                    전체보기
                </button>
            </div>
            <ul class="list">
                <li>
                    <a href="javascript:;" onclick="(function() {
    					kbcStorage.recentSearchKeyword.push({
    						'target' : 'result'
    						, 'makerCode' : '107'
    						, 'makerName' : 'BMW'
    						, 'classCode' : '1904'
    						, 'className' : '5시리즈'
    						, 'carCode'   : '2865'
    						, 'carName'   : '올뉴5시리즈 (G30) (2017~현재)'
    					}).then(function() {
    						location.href = '/public/search/main.kbc#!?makerCode=107&classCode=1904&carCode=2865';
    						$('#ks-mask').click();
    						$('#ks-input').val('BMW올뉴5시리즈 (G30)');
    						window.scrollTo(0,0);
    					});
    				})();"><b>B</b><b>M</b><b>W</b>올뉴5시리즈 (G30) (2017~현재)</a>
                </li>
                <li>
                    <a href="javascript:;" onclick="(function() {
    					kbcStorage.recentSearchKeyword.push({
    						'target' : 'result'
    						, 'makerCode' : '107'
    						, 'makerName' : 'BMW'
    						, 'classCode' : '1904'
    						, 'className' : '5시리즈'
    						, 'carCode'   : '1509'
    						, 'carName'   : '뉴5시리즈 (2003~2017)'
    					}).then(function() {
    						location.href = '/public/search/main.kbc#!?makerCode=107&classCode=1904&carCode=1509';
    						$('#ks-mask').click();
    						$('#ks-input').val('BMW뉴5시리즈');
    						window.scrollTo(0,0);
    					});
    				})();"><b>B</b><b>M</b><b>W</b>뉴5시리즈 (2003~2017)</a>
                </li>
                <li>
                    <a href="javascript:;" onclick="(function() {
    					kbcStorage.recentSearchKeyword.push({
    						'target' : 'result'
    						, 'makerCode' : '107'
    						, 'makerName' : 'BMW'
    						, 'classCode' : '1904'
    						, 'className' : '5시리즈'
    						, 'carCode'   : '1504'
    						, 'carName'   : '5시리즈 (1972~2004)'
    					}).then(function() {
    						location.href = '/public/search/main.kbc#!?makerCode=107&classCode=1904&carCode=1504';
    						$('#ks-mask').click();
    						$('#ks-input').val('BMW5시리즈');
    						window.scrollTo(0,0);
    					});
    				})();"><b>B</b><b>M</b><b>W</b>5시리즈 (1972~2004)</a>
                </li>
            </ul>
        </div>
        ...
        ...
        ...
        <div class="num-name-search">
            <a href="javascript:;" class="link-arrow _search-carno-a-name" onclick="(function() {
               var k='bmw' , kInt=parseInt(k);
               if (isNaN(kInt)) { // 문자
               if (k.length < 2) {
    				alert('판매자명은 2글자 이상 입력바랍니다.');
    				return;
    			}
    		} else { // 숫자
    			if (k.length  < 4) {
    				alert('차량번호 4자리 이상 입력바랍니다.');
    				return;
    			}
    		}
    
    		kbcStorage.recentSearchKeyword.push({
    			'target' : 'list-by-carnoandphone'
    			, 'keyword' : k
    		}).then(function() {
    			location.href = '/public/search/main.kbc#!?carNoMemberName=' + k;
    		});
    	})();">차량번호, 판매자명으로 찾기</a>
        </div>
    

     

    다시 엔지엠 RPA 매크로에 돌아와서 함수의 [ 정규 표현식 ] 액션을 추가 해주세요. 그리고, 위의 Html을 원본 문자열 속성에 넣어줍니다.

    aRh4VhB.png

     

     

    이전에 데이타를 자동으로 가져올려면 [ 웹서비스 ] 액션을 사용해야 합니다. 사용자에게 검색어 또는 데이타를 받아올 키워드를 입력받으려면 1부 내용을 참고하셔야 합니다. 1부 내용에는 사용자로부터 검색어를 입력 받고 이 검색어에 대한 매물 정보를 가져와서 엑셀에 정리하거나 데이타베이스에 넣을 수 있습니다.

     

     

    이제 KB차차차 중고차 매물 정보 가져오기 페이지에서 받은 Html을 분석해야 합니다. Json 형식이 아니기 때문에 다른 방법을 사용해야 하는데요. 아래 내용을 보면, makerCode, makerName, classCode, className, carCode, carName 정보만 가져오면 될거 같습니다. 그래서 정규식을 이용하는거거든요^^;

    <li>
    	<a href="javascript:;" onclick="(function() {
    		kbcStorage.recentSearchKeyword.push({
    			'target' : 'result'
    			, 'makerCode' : '107'
    			, 'makerName' : 'BMW'
    			, 'classCode' : '1904'
    			, 'className' : '5시리즈'
    			, 'carCode'   : '2865'
    			, 'carName'   : '올뉴5시리즈 (G30) (2017~현재)'
    		}).then(function() {
    			location.href = '/public/search/main.kbc#!?makerCode=107&classCode=1904&carCode=2865';
    			$('#ks-mask').click();
    			$('#ks-input').val('BMW올뉴5시리즈 (G30)');
    			window.scrollTo(0,0);
    		});
    	})();"><b>B</b><b>M</b><b>W</b>올뉴5시리즈 (G30) (2017~현재)</a>
    </li>

     

     

    정규식이란?

    정규식은 정규표현식이라고 불립니다. 사전적으로는 특정한 규칙을 가진 문자열의 집합을 단순화된 표현으로 변화시키는 방법을 정리한 형식 언어입니다. 정규표현식을 사용하면 주어진 문자열 또는 텍스트에서 조건에 만족하는 문자열들만 추출할 수 있습니다. 정규표현식을 사용하는 이유는 간단합니다. 매칭 시켜야할 문자열을 프로그래밍 언어의 조건식으로 만들면 매우 복잡해지기 때문입니다. 정규표현식을 사용하면 매우 간결하면서도 쉽게 문자열들을 추출할 수 있습니다.

     

    내가 만든 정규표현식을 평가하고 테스트하는 유용한 사이트가 있습니다. 저도 여기를 이용하는데요. 여러분들도 정규표현식을 만들 때 여기를 이용하시면 될거 같습니다.

    [ 정규표현식 테스트 사이트 ]

     

    추출할 문자열을 보면 ", 'makerName' : 'BMW'" 이와 같이 생긴 부분을 찾을 수 있을겁니다. 여기서 "'makerName' : 'BMW'"와 같은 데이타들만 추출할겁니다. 정규표현식에서 여러 문자열을 매치할 때는 괄호를 사용합니다. 그래서, 괄호 안에 추출할 정보들의 키만 정리 해줍니다. "makerCode|makerName|classCode|className|carCode|carName"와 같은 정보면 될거 같습니다. 그리고, 좀 더 타이트하게 원하는 정보만 뽑아올 수 있도록 하려면 추가적인 제약을 더 걸어줘야 합니다. 콜론과 싱글쿼테이션도 정규표현식에 추가해주면 좋을거 같네요.

    '(makerCode|makerName|classCode|className|carCode|carName)' : '.*'

     

    어라~ 원하는 모든 정보가 매치되지 않았습니다. 자세히 다시 살펴보니 caCode와 carName은 공백이 1개가 아니라 3개였습니다. 아마도, 보기 좋게 간격을 맞추기 위해서 공백(&nbsp;)을 추가한거 같습니다. 이 부분도 수정해야 모두 매치시킬 수 있을거 같군요.

    9wBWA0Y.png

     

     

    매치되는 문자(공백, &nbsp;)뒤에 여러개가 나오는 경우 모두 매치하려면 +를 사용해야 합니다. 지금은 *를 사용해도 문제 없이 동작할겁니다. 하지만, 제약이 큰 +를 사용하는게 좋겠죠? +는 무조건 하나 이상 존재해야 하므로 모든 문자열 매치에 오류가 없을겁니다. 이번에는 찾고자 하는 모든 데이타를 가져올 수 있게 되었습니다.

    '(makerCode|makerName|classCode|className|carCode|carName)' +: '.*'

    Ny2obZ5.png

     

     

    스크립트를 실행하면 원하는 데이타가 결과 목록에 배열로 잘 들어갔습니다.

    lX6nnBX.png

     

     

    여기서 콜론을 기준으로 키(makerCode...)와 값(현대...)을 분리하려면 배열 목록을 [ 변수 ]에 추가하고, [ Foreach 반복 ] 액션으로 모든 항목을 반복하면서 [ 문자열 분리 ] 액션으로 키와 값을 각각 변수에 넣어줘야 합니다. 간단해 보이지만, 처음 접하시는 분들은 다소 혼란스러울 수 있습니다. 1부와 2부에 동일한 내용이 설명되어 있으니 꼭! 1부와 2부 내용을 학습하시고 이 글을 보세요^^

     

    개발자에게 후원하기

    MGtdv7r.png

     

    추천, 구독, 홍보 꼭~ 부탁드립니다.

    여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~

    감사합니다~

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.