CasperJs로 Pixabay 크롤러 만들기

 Pixabay, UnSplash.com, Flicker... 여러분들 모두 발표자료를 준비하면서 고퀄리티의 이미지를 구하기 위해 한 번쯤은 저 사이트에 들어가보셨을 겁니다. 여러분들은 저 사이트에서 다운받은 이미지들을 어떻게 관리하시나요? 혹시 한번 사용한 후 나중에 다시 그 이미지를 구하러 컴퓨터 이곳저곳을 헤집거나, 다시 다운받지 않으신가요? 혹은 여러 이미지들을 일일이 손으로 누르면서 다운받고는, 발표자료랑 어울리지 않는다는 느낌이 들어서 다시 다른 이미지를 다운받지 않으신가요?
 저 같은 경우에는 그러한 일을 많이 겪었습니다. 그러던 어느 날, 재밌는 생각이 들었습니다. 
'고양이'라는 검색어를 치면 나오는 이미지들을 컴퓨터에 체계적으로 다운받아서 정리해주는 프로그램을 만들면 어떨까? 그러면 처음 한 번 다운받아놓고 나중에는 골라서 쓰면 될텐데 
라는 생각이죠. 생각이 떠오른 순간 Node.js로 크롤러를 만들어서 시험을 해봤습니다. 일이 거기서 끝났으면 정말 편했었을텐데요. 아쉽게도 Pixabay는 일반적인 방식으로 크롤링이 되는 사이트는 아니더군요. 그러나 여기서 포기하기에는 아직 멀었습니다. 우리에게는 웹 크롤링을 편리하게 해주는 CasperJs라는 강력한 툴이 있기 때문이죠.

*여기서 잠깐! CasperJs나 CSS 선택자 속성에 대해서 잘 모르시는 분들은 이전 포스팅인

 먼저 크롤링이 가능한지 확인하기 위해서 저번 시간에 짰던 스크린샷을 찍는 코드를 이용해서 테스트를 해봤습니다. 
 네, 결과는 완벽했습니다. 크롤링이 가능했죠. 그럼 이제부터 본격적으로 코드를 짜기 시작했습니다. 가장 처음에 해야 할 일은 바로 이미지 하나하나의 CSS 선택자 속성을 찾는 것 입니다. 지난 시간에 썼던 방식을 그대로 사용하겠습니다. 크롬 브라우저에서 F12를 누르고 왼쪽 위 화살표(Ctrl + Shift + C)를 누른 후 맨 첫 이미지를 선택합니다. 그 다음 Elements 창에 하이라이트 된 부분에 마우스를 가져다 대고 마우스 우클릭을 하고 Copy > Copy Selector를 눌러서 선택자 속성을 복사합니다. 
 제 결과는 #content > div > div:nth-child(3) > div > div > div:nth-child(1) > a > img가 나왔습니다. 그러나 크롬에서는 <스폰서 이미지>라면서 먼저 뜨는 이미지가 있지만 위의 스크린샷에는 그런 이미지가 없습니다. 
따라서 CSS 선택자 속성을 #content > div > div:nth-child(2) > div > div > div:nth-child(1) > a > img로 바꿔줍니다. 그리고 웹 페이지를 조금 뜯어보시면 알 수 있는 건데 div:nth-child(1)부분에서 1이란 것은 첫 번째 이미지를 뜻하는 것입니다. 그럼 두 번째 이미지는 div:nth-child(2)가 되겠죠? 이 부분을 잘 기억해 두세요.
 그럼 지금까지 얻은 정보를 이용해서 코드를 짜 보겠습니다.
var casper = require('casper').create({ verbose: true, logLevel: 'debug', pageSettings: { webSecurityEnabled: false }});
var utils = require('utils');
var url = '';
var args = casper.cli.args; //콘솔 창에서 실행할 때 검색어를 인자로 넣는데, 그 값을 읽어서 배열의 형태로 저장합니다.
if (args.length < 1) {  //검색어가 들어오지 않았을 경우
    casper.echo("검색어와 다운받을 파일의 수를 입력해주세요");
    casper.exit();
}
var url = 'https://pixabay.com/ko/photos/?hp=&image_type=&cat=&min_width=&min_height=&q=' + encodeURIComponent(args[0]) + '&order=' //Pixabay 홈페이지에 검색어로 접속합니다.

 현재까지의 코드를 설명해 보겠습니다. 1번 줄에  webSecurityEnabled: false는 이미지를 다운로드받기 위해서 넣은 코드입니다. 저 코드가 없으면 다운로드 에러가 발생합니다. util 모듈은 조금 이따 가져올 JSON 형식의 파일을 콘솔 창에 표시하며 분석하기 위해 가져왔습니다. 4번 줄에서 콘솔 창에서 실행할 때 검색어를 인자로 넣는다는 것은 'casperjs crawler.js 고양이'와 같은 형태로 넣는다는 뜻입니다.
 마저 코드를 작성해 보겠습니다.
casper.start(); 
casper.userAgent('User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36'); //User-Agent를 일반적인 컴퓨터 환경으로 잡습니다. (User-Agent에 따라 페이지 레이아웃을 바꾸는 홈페이지가 많이 존재하기 때문)
casper.viewport(1920, 1080); 
casper.open(url); 
casper.then(function () {
    var n = this.getElementsInfo('#content > div > div:nth-child(2) > div > div > div').length; //웹페이지에 표시된 이미지의 개수를 저장합니다.
    if (args.length >= 2) //첫 인자의 개수가 2 이상인 경우(이 값으로는 다운로드할 이미지의 개수가 주어진다.)
        n = args[1];
    for (var i = 1; i <= n; i++) {
        var img = this.getElementInfo('#content > div > div:nth-child(2) > div > div > div:nth-child(' + i + ') > a > img').attributes.src; //이미지의 주소를 가져온다.
        var img2 = img.split('__');
        var img3 = img.split('.');
        var higherImg = img2[0] + '_1280.' + img3[img3.length - 1];
        console.log(higherImg);
        this.download(higherImg, args[0] + '_' + i + '.png'); //이미지 다운로드
    }
    casper.echo("DONE!!");
})

 코드 중간에 보시면 img2, img3 변수가 있는데 이 변수들은 고해상도 이미지를 다운받는데 사용됩니다. console.logcasper.echo로 img 변수의 값을 확인해 보면 __320.jpg 또는 __320.png라는 주소가 공통으로 있습니다. 그래서 Pixabay의 이미지들을 좀 더 분석해 본 결과 __320.jpg/__320.png 대신 _1280.jpg_1280.png로 바꿔서 넣으면 더 고해상도의 이미지를 다운받을 수 있는 것을 알아냈습니다. 따라서 __320을 _1280으로 바꾸는 코드를 중간에 삽입하였고, 파일 이름을 각각 <검색어>_(n번째 이미지).png로 바꾸어 저장하게 하였습니다.
 중간중간 getElementInfo()download()와 같이 처음 보는 함수를 몇 개 썼는데, 이 함수들에 대한 자세한 설명은 링크를 타고 들어가면 CasperJS 공식 API 문서에 나와있습니다. 이와 같이 공식 API 문서를 보는 습관은 매우 중요하므로 잘 익혀 두시기 바랍니다.
 만들어진 프로그램을 실행하면 다음과 같은 실행 결과를 얻을 수 있습니다.
>>casperjs crawler.js 고양이
 이상으로 오늘 포스팅을 마치겠습니다. 이해가 안되는 부분이나 질문이 있으시면 댓글로 남겨주세요!!

댓글

댓글 쓰기

이 블로그의 인기 게시물

PhantomJS로 Blogger댓글 조회 프로그램 작성하기

PhantomJs와 CasperJs