자바스크립트/puppeteer, cheerio
* facebook 자동 로그인 + 좋아요 + 구독자 수 ( only puppeteer )
큰세상2000
2020. 11. 17. 00:19
반응형
참조 동영상 : https://www.youtube.com/watch?v=jw4exv4qv2E
분석은 로그인 한채로 진행하면 페이지 접근이 2-3 시간 정도 차단되므로 로그인 안한채로 하는것을 추천
index.js
const facebook = require("./facebook/index.js");
const facebook_id = '';
const facebook_pass = '';
(async () => {
// facebook 초기화
await facebook.initialize();
// 로그인
await facebook.login(facebook_id, facebook_pass);
// 페이스북 좋아요 카운트 가져오기
await facebook.like_follow_Count();
// 스크래핑 브라우저 종료
await facebook.close();
})();
facebook.js
const puppeteer = require('puppeteer');
const clickTag = require('../_inc/clickTag.js');
const fs = require('fs');
const BASE_URL = 'https://www.facebook.com/';
module.exports = {
browser: null,
page: null,
// 초기화
initialize: async () => {
// browser = await puppeteer.launch({ headless: false });
browser = await puppeteer.launch();
page = await browser.newPage();
// 브라우저 타임아웃 오류 제거, 대기 시간이 길어짐
await page.setDefaultNavigationTimeout(0);
},
// 로그인
login: async (username, password) => {
console.log('login start');
try {
await page.goto(BASE_URL, { waitUntil: 'networkidle2' });
/*
css : <a href="/accounts/login/?source=auth_switcher" tabindex="0">로그인</a>
셀렉터 : #react-root > section > main > div > div > div:nth-child(2) > p > a
*/
// await facebook.page.$eval('#edit-button', el => el.click());
// 로그인 페이지로 넘어가는 버튼 누르기
// let loginButton = await facebook.page.$x('a[contains(text(), "로그인")]');
// let loginButton = await facebook.page.$x('a[contains(., "로그인")]');
// await delay(3000);
console.log('id & pass input');
// 아이디와 비빌번호 입력
await page.type('input[name="email"]', username, { delay: 50 });
await page.type('input[name="pass"]', password, { delay: 50 });
// 로그인 페이지로 넘어가는 버튼 누르기
/*
css : <button class="sqdOP L3NKy y3zKF " type="submit">
<div class="Igw0E IwRSH eGOV_ _4EzTm">로그인</div></button>
*/
console.log('login button click');
await clickTag.clickByText(page, '로그인', 'button');
await clickTag.delay(2000);
} catch (e) {
console.debug(e);
}
},
// 좋아요, 구독자 갯수 가져오기
// 사이트 주소는 문서에서 가져온다
// ./rank.txt
// Big Hit Entertainment, fb.com/ibighit
// 방탄소년단, fb.com/bangtan.official
// ./rank_like_follower.txt
// 페이지명, 사이트명, 좋아요갯수, 구독자수 형식
like_follow_Count: async () => {
try {
var array = fs.readFileSync('./rank.txt').toString().split('\n');
var arr = [];
const fw = (data) => {
fs.appendFile('./rank_like_follower.txt', data, function (err) {
if (err) throw err;
console.log(data);
});
};
var arr = [];
for (i in array) {
arr = array[i].toString().split(', ');
if (arr.length > 2) {
arr[0] = arr[0] + ',' + arr[1];
arr[1] = arr[2];
}
if (arr.length > 3) {
arr[0] = arr[0] + ',' + arr[1] + ',' + arr[2];
arr[1] = arr[3];
}
let likeNumber = 0;
let followerNumber = 0;
// 사이트 주소가 지정이 안된경우가 아니라면 로딩 시작
if (arr[1] != 'fb.com/' && arr[1] != '') {
await page.goto('http://' + arr[1], {
// networkidle2 는 페이지 못 받고 죽는 경우가 생김
waitUntil: 'load',
// 타임아웃 제거
timeout: 0,
});
// 페이지 열릴때까지 대기 시간
await clickTag.delay(1500);
likeNumber = await page.evaluate(() => {
var aaa = 0;
// div 태그 중에서 '명이 좋아합니다' 라는 텍스트를 가진것을 찾아서 숫자만 뽑는다
for (const a of document.querySelectorAll('div')) {
if (a.textContent.includes('명이 좋아합니다')) {
aaa = a.textContent.replace(/[^0-9]/g, '');
}
}
// 추출 데이타가 없거나 0 이 아니라면 추출한 값을 리턴
// 그렇지 않다면 다시 한번 분석 시도
if (aaa != undefined && aaa != 0) {
return aaa;
}
for (const a of document.querySelectorAll('div')) {
if (a.textContent.includes('명이 좋아합니다')) {
aaa = a.textContent.replace(/[^0-9]/g, '');
}
}
return aaa;
});
// div 태그 중에서 '명이 팔로우합니다' 라는 텍스트를 가진것을 찾아서 숫자만 뽑는다
followerNumber = await page.evaluate(() => {
var aaa = 0;
for (const a of document.querySelectorAll('div')) {
if (a.textContent.includes('명이 팔로우합니다')) {
aaa = a.textContent.replace(/[^0-9]/g, '');
}
}
// 추출 데이타가 없거나 0 이 아니라면 추출한 값을 리턴
// 그렇지 않다면 다시 한번 분석 시도
if (aaa != undefined && aaa != 0) {
return aaa;
}
for (const a of document.querySelectorAll('div')) {
if (a.textContent.includes('명이 팔로우합니다')) {
return a.textContent.replace(/[^0-9]/g, '');
}
}
return aaa;
});
}
// 2번 분석시도를 했는데도 값이 안나오면 그냥 0으로 지정한다
if (likeNumber == undefined && followerNumber == undefined) {
likeNumber = 0;
followerNumber = 0;
}
// 파일에 분석해온 좋아요와 구독자수를 저장한다
fw(arr[0] + ',' + arr[1] + ',' + likeNumber + ',' + followerNumber + '\n');
}
} catch (e) {
console.debug(e);
}
await clickTag.delay(1000);
},
// 스크래핑 중단
close: async () => {
console.log('browser close');
await browser.close();
},
};
반응형