Python/2.7 for fun.

크롤링시 데이터 찾는 방법 노하우.

qkqhxla1 2017. 8. 30. 14:25

어떤 사이트에서 크롤링을 할 경우에 다음과 같은 단계를 거친다.

1. 해당 페이지를 구성하는 데이터들을 어디서 받을수 있는지 찾는다.

2. 해당 페이지에 요청을 보내는 코드를 짠다.

3. 페이지 정보 등을 가져온 후 (파이썬의 경우) beautifulsoup나 정규식을 이용하여 필요한 부분을 크롤링하여 자동화한다.


일정 횟수 이상 크롤링을 해본 사람들이 보기에 가장 어려운 부분은 1번 파트이다.(처음 시작하는 사람은 구현부인 2,3번이 가장 어렵다)

2번이야 항상 똑같으니 됐고, 3번이야 프로그래밍 지식이나 센스만 있으면 간단하다. 하지만 1번은 우리가 데이터를 찾아야 하기에 힘들다. 그리고 api처럼 공식문서도 당연히 없다. 아래에 다양한 사례와 1번의 데이터를 조금 더 쉽게 찾을 수 있는, 또는 크롤링하는 노하우등을 적었다.



1. '가장 간단한' 소스를 뒤져보면 바로 나오는 경우. (가장 쉬움.)

크롤링을 시작하는 사람들이 가장 먼저 짜보려는 프로그램중 하나는 웹툰 목록을 파싱해오는 크롤러다.

네이버 웹툰(http://comic.naver.com/webtoon/weekday.nhn) 같은 경우는 페이지 소스를 보면 해당 웹툰의 링크가 어디인지 다 나와있다. 

해당 페이지에서 페이지 소스를 본 후 웹툰 이름을 텍스트로 검색해보면 해당 부분이 나온다. 근처의 위 아래로 링크를 이것저것 클릭하다보면 웹툰 페이지가 나오게 되고, 규칙을 파악하게 된다. 이게 가장 간단한 경우인 소스 보면 바로 나오는 경우이다.


2. 살짝 숨겨져 있는 경우.(그래도 쉬움.) 내 네이버 블로그다 : http://blog.naver.com/qkqhxla1/220089516315 여기서 크롤링으로 '이사했습니다.' 라는 제목글을 가져와 보자. 소스를 봐도 안나온다. 하지만 자세히 보면 본 페이지 소스를 찾을수 있고, 그 페이지에서 다시 소스 보기를 하면 나온다. 소스 중앙에 "/PostList.nhn?blogId=qkqhxla1&widgetTypeCall=true" 링크가 있는데 여길 클릭해서 들어간 후 다시 소스 보기를 해서 가져올 수 있다.

이 경우도 아주 간단한 경우이다.


3. 소스 뒤져도 안 나오는 경우. 

소스 뒤져도 안 나오는 경우 슬슬 어려워진다. 다음 웹툰을 크롤링한다고 가정해보자. 월요일 웹툰 탭이 켜진 상태이다. http://webtoon.daum.net/#day=mon&tab=day 여기서 월요일 웹툰의 링크 등등을 가져오고 싶은데 어떻게 해야 할지 모르겠다. 소스를 봐도 아무것도 안 나온다. 

이 경우는 페이지에 들어오는 데이터들을 살펴봐야 한다. 페이지를 검사하기 위해 페이지 검사?창을 연다. 윈도우는 모르겠는데 맥에서의 단축키는 옵션+커맨드+i 이다.


아래와 같은 창이 열리고 추측을 해본다. 소스를 봤는데도 웹툰에 관한 정보가 없는 이상 페이지에서는 어디 다른 곳에서 웹툰에 관한 정보를 매번 받아올 거라고 가정한다. 그러면 그 정보가 네트워크 탭(아래 사진에 현재 선택되어 있는 탭)에 기록될것이고, 네트워크 탭을 뒤지다보면 어딘가 정보가 있을것 같다. 

네트워크 탭을 뒤져보자. Filter란에 찾을 키워드를 넣어서 필터를 걸 수 있다. 왔다갔다하는 데이터가 많으므로 게싱을 잘 해야 한다. 일단 나같은 경우 필터에 가장 처음으로 넣어보는건 ajax라는 단어이다. 대부분 사이트에서 데이터를 가져올 경우, 자바스크립트에서 ajax를 사용해 비동기로 데이터를 가져오는 경우가 많기 때문이다. 


하지만 다음 웹툰 같은 경우에는 ajax를 검색해도 아무것도 나오질 않는다. 이 경우에는 로딩되는 소스를 처음부터 살펴보자. 이미지 파일은 그냥 지나가고 .js로 끝나는 파일이나 json등과 나머지의 파일만 살펴봐도 된다. 

js개발을 많이 해봤거나, 많은 사이트를 살펴보면 위의 캡쳐된 js중에 두번째 라인의 jquery-2.1.1.min.js같은 경우 기본 라이브러리로 그냥 지나가도 된다는걸 알수 있다. 뭔가 있을만한 것들만 살펴보자.


하나하나 살펴보다 보면 Name에 mon?timeStamp=150406~ 이런게 있다. 월요일을 선택해서 저 리스트들을 가져온것도 있고, 현재 timestamp가 찍혀있는게 뭔가 있는것같다. 값을 가져오면 json형태라는걸 알 수 있다.

해당 주소를 더블클릭해 들어가 볼수도 있다. : http://webtoon.daum.net/data/pc/webtoon/list_serialized/mon?timeStamp=1504069902135


{"result":{"status":"200","message":""},"data":[{"id":1378,"nickname":"CatQueen","webtoonType":"series","title":"고양이 마마님","finishYn":"N","thumbnailImage2":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/a2f86ed531940714434e3f32eac9153f1d772191","width":0,"height":0,"serviceStatus":"service"},"appThumbnailImage":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/426119bd43d32eda583bfdd1976f2a4aa3f2f991","width":0,"height":0,"serviceStatus":"service"},"pcThumbnailImage":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/d91682c78485c52d99df12e234f864b9dc8b3ffb","width":0,"height":0,"serviceStatus":"service"},"pcRecommendImage":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/ec96d7a44a1a4c7f87c977228055a8c92853b8a7","width":0,"height":0,"serviceStatus":"service"},"pcHomeImage":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/e5fa530ca23feff5ed233c01b11ce2c69b999ce1","width":0,"height":0,"serviceStatus":"service"},"pcHomeRightImage":{"id":0,"url":"http://t1.daumcdn.net/webtoon/op/e4f998e2f52e70e8d0a574bc3f595ffcf4cad7f8","width":0,"height":0,"serviceStatus":"service"},"pcHomeLeftColor":"dca365","pcHomeRightColor":"dca365","introduction":"지금의 당신에게 소중한 시간은 언제인가요? 300년만에 다시 시작된 인연과 악연의 굴레.","startDate":"20170807000000","serviceStatus":"service","viewerType":"scroll","weekTerm":"weekly","articleId":0,"media":"daum","payYn":"N","payType":"free","price":0,"ageGrade":0,"restYn":"N","monopolize":"N","dateCreated":"20170803112821","webtoonComment":{"id":0,"articleId":1378,"commentUseYn":"N"},"cartoon":{"id":61859,"genres":[{"id":4,"name":"판타지"},{"id":5,"name":"순정"}],"artists":[{"id":6705,"name":"마루","penName":"마루","history":"2010년 겨울하나\u003cbr\u003e\r\n2011년 피노키오","smallPictureImage":{"id":6947001,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/U07CDB1C4CF1AFB31D","width":0,"height":0,"serviceStatus":"service"},"appImage":{"id":44855711,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/5194710A0377CD0001","width":0,"height":0,"serviceStatus":"service"},"nameImage":{"id":6953079,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/U544C0049AA830D047","width":0,"height":0,"serviceStatus":"service"},"birthDay":"00010101000000","debutDay":"20101128000000","email":"ares_star@hanmail.net","blog":"http://blog.naver.com/ares_star","fancafe":"http://cafe.naver.com/pinocchiofan","twitter":"https://twitter.com/arestar1030","teamYn":"N","artistOrder":0,"artistType":"picture"},{"id":6705,"name":"마루","penName":"마루","history":"2010년 겨울하나\u003cbr\u003e\r\n2011년 피노키오","smallPictureImage":{"id":6947001,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/U07CDB1C4CF1AFB31D","width":0,"height":0,"serviceStatus":"service"},"appImage":{"id":44855711,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/5194710A0377CD0001","width":0,"height":0,"serviceStatus":"service"},"nameImage":{"id":6953079,"url":"http://i1.cartoon.daumcdn.net/svc/image/U03/cartoon/U544C0049AA830D047","width":0,"height":0,"serviceStatus":"service"},"birthDay":"00010101000000","debutDay":"20101128000000","email":"ares_star@hanmail.net","blog":"http://blog.naver.com/ares_star","fancafe":"http://cafe.naver.com/pinocchiofan","twitter":"https://twitter.com/arestar1030","teamYn":"N","artistOrder":0,"artistType":"story"}],"categories":[{"id":384,"name":"전생","categoryType":"keyword","priority":1},{"id":58,"name":"고양이","categoryType":"keyword","priority":2},{"id":310,"name":"연애","categoryType":"keyword","priority":2},{"id":492,"name":"학원","categoryType":"keyword","priority":2},{"id":1,"name":"스토리","categoryType":"story","priority":0}]},"webtoonWeeks":[{"id":20035,"weekDay":"mon"}],"latestWebtoonEpisode":{"id":44041,"episode":4,"title":"3화 그때는 그때고 지금은 지금이야!","thumbnailImage":{"id":44041,"url":"http://t1.daumcdn.net/cartoon/598E3CA90253690001","width":0,"height":0,"serviceStatus":"service"},"episodeImage":{"id":0,"url":"http://t1.daumcdn.net/cartoon/598E3CAD02376C0001","width":0,"height":0,"serviceStatus":"service"},"encryptUseYn":"N","serviceStatus":"service","articleId":0,"dateCreated":"20170828000100","price":0,"isTopRecommend":false,"isPaid":false},"webtoonServices":[{"id":34916,"webtoonId":1378,"serviceTarget":"series"},{"id":34917,"webtoonId":1378,"serviceTarget":"padtoon"},{"id":34918,"webtoonId":1378,"serviceTarget":"mobile"},{"id":34919,"webtoonId":1378,"serviceTarget":"app"}],"score":0.0,"isNew":true,"averageScore":9.942413458427692,"ranking":0,"diff":0,"metricsScore":0,"sort":"desc","sortWeight":1},{"id":1372,"nickname":"RTX","webtoonType":"series","title":"집행자여","finishYn":"N","thumbnailImage":{"id":0,"url":"http://t1.daumcdn.net/cartoon/59391FCD013F7E0001","width":0,"height":0,"serviceStatus":"service"},"thumbnailImage2":{"id":0,"url":"http://t1.daumcdn.net/cartoon/5939465C0268500001","width":0,"height":0,"serviceStatus":"service"},"padThumbnailImage":{"id":0,"url":"http://t1.daumcdn.net/cartoon/59391FDA026B690001","width":0,"height":0,"serviceStatus":"service"},"homeThumbnailImage":


~~~ 중략

잘 살펴보면 이 json 데이터가 맞음을 알 수 있다. '고양이 마마님'이라는 웹툰 정보 전체가 위에 들어있는데, 여기서 이 웹툰의 주소를 찾아보자. 어떻게 찾을수 있을까? 해당 웹툰의 주소는 http://webtoon.daum.net/webtoon/view/CatQueen 이다. 

전체 주소는 위의 json에서 찾을수 없지만 마지막의 CatQueen부분은 nickname에서 찾을수 있다. 그러면...? 다른 웹툰을 살펴보면 마지막 부분만 변함을 알 수 있다. ex) 집행자여 라는 웹툰 : http://webtoon.daum.net/webtoon/view/RTX 그렇다면 기본 주소 http://webtoon.daum.net/webtoon/view/ 에 끝부분에 nickname부분만 가져와서 붙이면 url을 얻을 수 있다. 이런 식으로 필요한 정보 대부분은 얻을 수 있다.


연습.

1. 에누리 사이트에서 자동차를 검색했을 경우에 나오는 상품의 리스트를 가지고 오고 싶다.

http://www.enuri.com/search.jsp?nosearchkeyword=&issearchpage=&searchkind=&es=&c=&ismodelno=false&hyphen_2=false&from=&owd=&keyword=%EC%9E%90%EB%8F%99%EC%B0%A8

가 검색했을때의 url이고, 여기서 상품을 가지고와보자. 답은 따로 적지 않는다.

힌트 : ajax


여기에 적은건 간단한 두 케이스이고 이 경우 말고도 다른 여러 케이스가 있다. (예제는 찾기가 힘들어서 안올림.)

1. 페이지 소스 내에서 api주소를 찾을 수 있는데 정보를 api에서 호출해다가 쓰는 경우.

2. 셀렉트 버튼을 누르는 순간 ajax 가 호출되어 하위 정보를 가져오는 경우.

등등


마지막으로.

초보들에게 구분이 되는 자바스크립트 소스는 두가지 종류가 있다.

1. 페이지 소스보기로 나오는 자바스크립트와

2. '페이지 검사'후 마우스로 찍었을때 나오는 자바스크립트. (동적으로 페이지를 만드는 경우)

이 경우 '단순하게' 스크립트로 페이지 소스를 가져올때 사용할 수 있는 경우는 1번뿐이다. 2번 소스를 이용해 크롤링을 하고 싶으면 selenium이나 ajax나 api페이지를 찾아서 직접 요청하면 된다.