몇개월전의 작성된 SNS 크롤러가 작동하나 테스트겸 돌렸더니 오류를 뿜어내길레 살펴보니..


selector 부분쪽을 손을 본것인지 안되길레 수정했습니다


API 권한이나 좀 풀어주지...


변경된 부분은 이미지,Like 표시 등등 미세하게 바꿔놨습니다.



https://github.com/choy1379/-tagtop


인스타그램만수정했습니다


WRITTEN BY
내가달이다

,

새로 프로젝트를 하면서 이전에 사용한 SpookyJS 를 npm 을 이용하여 설치후 


테스트 데이터를 넣은후 실행을 해보았다 


하지만 ...




이와 같이 오류가 계속 발생하는것이다 특별한 작업을 수행하지도 않았는데 말이다 ... 


구글링을해보아도 안나오길레 삽질을한결과 .. 


tiny-jsonrpc  이놈을 설치해 주니 정상동작 한다.. 아 이것때문에 30분날렸습니다 


npm install tiny-jsonrpc   


설치해주면 끝 


WRITTEN BY
내가달이다

,

유튜브 , 트위터 API 를 이용해 검색한 데이터를 한곳에 모아 보는 웹페이지를 제작하려했다


그런데 유튜브, 트위터 각각 api 에서 가져오다보니 이 두 데이터를 한 배열에 모아서 보여주려고 하니 어찌할까 하다가 


랜덤 배열을 이용해 볼까 한다 .. 


우선 랜덤 배열 http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array 



1
2
3
4
5
6
7
8
9
10
11
12
              this.SumArrayData[0= new Array();
                  for(var i =0; i<5; i++)
                  {
                    this.SumArrayData[0][i] = this.tweetsArray[i];
                  }
                  for(var i=0; this.YoutubeArray.length>i; i++)
                  {  
                    this.SumArrayData[0][this.SumArrayData[0].length]= this.YoutubeArray[i];
                  }
                  this.SumArrayData[0].sort(function(){return 0.5-Math.random()});
                  this.loading = false 
                }); 
cs



사이클은 이렇다


for문 만큼 SumArrayData[0][i] 에 트위터데이터 값을 넣어준다 


i를 5로 정한이유는 화면상에 트위터5개만보여주려고하기때문..


그 후 


for 문에서 sumArrayData[0].length 값에 유튜브 값을 넣어준다


앞에 0~4 까지 는 트위터데이터 값이고 5번부터 유튜브 데이터 값을 넣어준것이다 


this.SumArrayData[0].sort(function(){return 0.5-math.random()}); // 랜덤 함수



완성된 페이지는 랜덤으로 섞인다 





WRITTEN BY
내가달이다

,

최근 SNS크롤러를 만들면서 크롤링에흥미가생겨 casperjs 함수에 대해 몇개 소개해볼려고한다



this.fill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var links = [];
var casper = require('casper').create({
    pageSettings: {
        loadImages: true,//The script is much faster when this field is set to false
        loadPlugins: true,
        userAgent: 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36' 
 },
    
});
// 캐스퍼의 사이즈 옵션을 나타낸다 예제는 1024x768 해상도를 주었다
casper.options.viewportSize = {width: 1024, height: 768}
 
 
  //트위터 페이지에서 검색 텍스트 박스안에 #블랙베리 라는 예제를 입력해준다
casper.start('https://twitter.com/search?f=tweets&vertical=default&q=%23%EC%95%84%EC%9D%B4%ED%8F%B0&src=typd'function() {
    var fileLocate = 'screenShotTest/1.jpg';
// 캡쳐 부분이다
    this.captureSelector(fileLocate, "html");
    this.fill('form#global-nav-search', { 'q''#블랙베리' }, true);
 
});
 
 
cs



this.evaluate



대략적인 실행 매커니즘은 


 start -> then() -> evaluate() -> pass function - > Dom -> execute function -> return value


실제로 코드를 사용하게되면


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
 // 캐스퍼가 스타트후 그이후에 실행되는 구조
casper.then(function(){

  // latestID 라는 function 생성
    var latestId = function(){

//'#stream-items-id li' 값 반환
         return document.querySelector('#stream-items-id li').innerText

    };

   // this.evaluate 을 통해 함수실행시키고 return 값을 받는다
    console.log(this.evaluate(latestComment));
 
 
   
});
 
 
casper.run(function() {  
    var fileLocate = 'screenShotTest/2.jpg';
    this.captureSelector(fileLocate, "html");
    console.log('완료')
});
 

cs




scrolltoBottom


이 기능은 현재페이지의 스크롤을 최하단으로 이동한다 


1
2
3
4
5
6
7
8
9
10
11
12
13
                            // 페이지를 최하단으로 이동한다
this.scrollToBottom();
  
// 페이지를 최하단으로 이동후 현재페이지의 Top,scrollY값을 구한다
                            var scrollY = this.evaluate(function() {
                                    return window.scrollY;
                                });
                                
                             console.log(scrollY)
                            var scrollTop = this.evaluate(function() {
                                return window.document.body.scrollTop = document.body.scrollHeight;
                                });

                             console.log(scrollTop)
                  
 
cs




thenClick


1
2
3
4
5
6
7
8
 // 캐스퍼js 사이트접속후 첫번째 링크를 클릭하는 이벤트
casper.start('http://casperjs.org/').thenClick('a'function() {
    this.echo("I clicked on first link found, the page is now loaded.");
});
 
casper.run();
 
 
cs




thenEvaluate

1
2
3
4
5
6
7
// 구글에서 Chuck Norris 를 검색한다
casper.start('http://google.fr/').thenEvaluate(function(term) {
    document.querySelector('input[name="q"]').setAttribute('value', term);
    document.querySelector('form[name="f"]').submit();
}, 'Chuck Norris');
 
casper.run();
cs






WRITTEN BY
내가달이다

,

지난 포스팅에 말했다 싶이 일정 시간마다 instagram,twitter 데이터를 크롤링 하는 스케쥴링을 구현해볼 생각이다


처음에는 간단하게 twitter api,instagram api 만을 이용해서 가져오면되지않을까? 


라는 별거아닌 생각으로 프로그램 작성을 했다.. 


트위터는 api 를 무난하게 사용해 작성을하였는데.. 아뿔사... 


인스타그램은 .. 정책이변경되서 권한이 얻기가 ... 드릅게 빡세다 ...  





어쩔수없이 페이지 자체를 크롤링 하는 방향으로 포커스를 맞췄다  아 내시간 ㅁ느아ㅣㅡㅁ니ㅏㅇ




#트위터 ,인스타그램 페이지 크롤링






트위터 홈페이지에서 #블랙베리 라는 태그를 가지고 검색을 한 화면 이다


트위터  나 인스타그램 같은경우는 화면을 최하단으로 스크롤 할경우  자동으로 다음페이지를 불러오게 되어있다


이런문제때문에 생각해볼게 좀많아서 이걸 어찌하나 했는데 


http://blog.nundefined.com 이 글의 도움을 많이 받았다



우선 크롤링을 하기위해서는 


 


PhantomJS,CasperJS,SpookyJS 가 필요하다 


설치하는 방법은 구글에 많이있으니 참고해서 설치하시기 바랍니다..


간단하게 설명하자면

 

PhantomJS/CasperJS 같은경우는 webkit 기반의 headless browser 이다 즉, 단독브라우저로 웹테스트 할떄 많이들 사용한다고 하더라


SpookyJS 위의 CasperJS,PhantomJs같은 경우는 node 와 관계없이동작하기때문에 이를 컨트롤 하기 위해서 사용을한다 



function.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 scheduletwitter: function(count) {
 
            var searchquery = config.schedule.hashtag[count];    //앞서 저장되어있던 수집태그
            var id = config.schedule.name[count];                 //앞서 저장되어있던 id값    
            var encsearchquery = encodeURIComponent(searchquery);
            var url = 'https://twitter.com/search?f=tweets&vertical=default&q=%23'+encsearchquery+'&src=typd';
 
            var Spooky = require('spooky');
 
            var spooky = new Spooky({
                    casper: {
                          logLevel: 'debug',
                            verbose: false,
                            options: {
                                clientScripts: ['https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js']
                            },
                            viewportSize: {
                                        width: 1440, height: 768
                                    },
                               pageSettings: {
                                webSecurityEnabled: false
                                userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11" // Spoof being Chrome on a Mac (https://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx)
                            }
                            
                    }
                }, function (err) {
                    if (err) {
                        e = new Error('Failed to initialize SpookyJS');
                        e.details = err;
                        throw e;
                    }
 
             
                    spooky.start(url);
                         var twitter = function() {                            
                                spooky.then(function(){
                              this.scrollToBottom();
                                this.wait(1000);
                            var newScrolleds = this.evaluate(function() {
                                    return window.scrollY;
                                });
                            var newScrolled = this.evaluate(function() {
                                return window.document.body.scrollTop = document.body.scrollHeight;
                                });
                                    
                        });
                        spooky.then(function(){       
                        
                            this.scrollToBottom();
                            this.wait(1000);
                            var newScrolleds = this.evaluate(function() {
                                    return window.scrollY;
                                });
                                
                                this.emit('logs',newScrolleds)
                            var newScrolled = this.evaluate(function() {
                                return window.document.body.scrollTop = document.body.scrollHeight;
                                });
                                    this.emit('logs',newScrolled)
 
                            
                        });  
                    
                    }  
  
                        twitter()
               
 
                    }
 
                    spooky.run();
                             
                });
            spooky.on('logs'function (logs) {
                                        console.log(logs);
                                        });
 
  
 
 
}
cs



몇가지 코드를 살펴보자 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//spookyJS URL 접속
spooky.start(url)              
            //spookyJS 다음 행동           
            spooky.then(function(){    
                            //스크롤을 맨아래로 이동                 
                             this.scrollToBottom();   
                             // 1초 wait  
                              this.wait(1000);          
                            var newScrolleds = this.evaluate(function() {
                                     //현재 윈도우 y값
                                    return window.scrollY;  
                                });
                            var newScrolled = this.evaluate(function() {
                                //현재 윈도우 x값
                                return window.document.body.scrollTop = document.body.scrollHeight; 
                                });
 
                            // logs 값 전송
                            this.emit('logs',logs)
   
 // logs 값 get
  spooky.on('logs'function (logs) {
    console.log(logs);
     });
cs



해당 코드를 실행하게되면 검색어가 입력된 페이지를 접속한후 맨아래로 이동후 그 좌표 로그값을 받는 것이다



이런식으로 찍히게 된다 (정상작동)


본격적으로 데이터를 가져와보자




가져 오게 되면

1
2
3
4
5
6
7
        Userid = this.evaluate(function() {
                                                var elements = __utils__.findAll('#stream-items-id > li > div > div > div > a > span.username.js-action-profile-name');
                                                return elements.map(function(e) {
                                                    return e.innerText
                                                });
                                        });
        this.emit('dbinsert', Userid)
cs


이런식으로 변수에 저장시켜주면된다


값까지 찾았으니 그후에는 db 에 입력시켜줍시다


this.emit 을 통해 node 으로 돌아와서


1
2
3
4
   spooky.on('dbinsert'function (data) {
                    db.dummy.save(data, function(){
                        });
                });
cs


디비로 전송시켜주면 끝


이제 이걸 내가원하는 시간마다 돌아가게 스케쥴링을 걸어주자 


server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  var scheduler = new Scheduler(1);
 
 
            scheduler.add(8000function(done,res){
 
                
                setTimeout(function() {
                    for(var i = 0; i < config.schedule.hashtag.length; i++)
                    {
                        functions.scheduleinstagram(i)
                    }
                }, 3000);
 
                setTimeout(function() {
                    for(var i = 0; i < config.schedule.hashtag.length; i++)
                    {
                        functions.scheduletwitter(i)
                    }
                }, 3000);
            done();     
        });
cs



자이제 결과를 살펴보자




인스타그램도 이와 유사하다  궁금하신 부분이있으면 댓글달아주세여



WRITTEN BY
내가달이다

,

2 UI  에 이어서 마저 작성을한다



UI 에서 입력한값을 mongoDB로 입력할수있게해주려한다


2장에서 작성한 

collect.component.ts 추가 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   addinfo(
    email:string,
    name:string,
    hashtag:string,
    frcal:string,
    tocal:string,
     twitter:string,
    ){
      
      
       var query = {
                         "hashtag" : hashtag,
                          "email" :  email,
                          "frcal" : frcal,
                          "tocal" : tocal,
                          "twitter" : twitter,
                         "name"    : name
       }
       
        var headers = new Headers(); 
        headers.append('Content-Type''application/json')
        this.http.post('http://localhost:4100/dbUserinsert',query,{headers: headers}).subscribe((res) => {
        
    );
cs


server.js 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var express = require('express');
var request = require('request');
var bodyParser = require('body-parser');
var cors = require('cors');
var functions = require('./functions');
var dbsearch = require('./dbsearch');
var app = express();
var Scheduler = require('nschedule');
var config = require('./config');
var async = require('async');
 
 
 
 
           
         app.use(express.static(__dirname));
        app.post('/dbUserinsert',dbsearch.Userinsert);  //입력받은값 디비 저장
        app.listen(process.env.PORT || 4100);
        console.log("Server up on port 4100");
cs

MongoDB 설치

1
2
3
npm install mongojs -
//MongoDB 설치
 
cs


dbsearch.js 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var searchfunctions = require('./functions')
var mongojs = require('mongojs');
var db = mongojs('mongodb://''@''.mlab.com:63406/');
 
functions = {
 
 Userinsert : (req,res) => {
    var req = req.body;
    console.log(req)
     db.collect.save(req, function(err, result){
                if(err){
                    res.send(err); 
                    console.log(err);
                } else {
                    res.json(result);
                    console.log(result);
                }
            });
        
    }}  
cs




작성한 코드를 실행하게 되면


입력받은 값을  query 변수에 입력하고 JSON 으로 보내게 된다 


서버에서는 호출 된 URL http://localhost:4100/dbUserinsert app.post 시켜서  dbsearch.js 에 있는


Userinsert 함수를 실행시켜주게 된다 


완성이되면  이전페이지에서 보게된거처럼 그리드에 바인딩이 되어진다 




#입력된값을 DB 에 저장시키는 코드 까지 작성을 완료 했다

다음페이지에서는 일정시간마다 instagram,twitter 데이터를 크롤링 하는 스케쥴링을 포스팅할예정이다 




WRITTEN BY
내가달이다

,